diff --git a/base/.classpath b/base/.classpath new file mode 100644 index 0000000000..c97db317a7 --- /dev/null +++ b/base/.classpath @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/base/.packaging b/base/.packaging new file mode 100644 index 0000000000..a336b0bb42 --- /dev/null +++ b/base/.packaging @@ -0,0 +1,2 @@ + + diff --git a/base/.project b/base/.project new file mode 100644 index 0000000000..7e951739a9 --- /dev/null +++ b/base/.project @@ -0,0 +1,26 @@ + + + base + + + dbPort + looks + print + tools + + + + org.eclipse.jdt.core.javabuilder + + + + + com.ibm.etools.validation.validationbuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/base/.settings/org.eclipse.core.resources.prefs b/base/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000..2501aa6e02 --- /dev/null +++ b/base/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +#Sat Dec 17 10:51:04 PST 2005 +eclipse.preferences.version=1 +encoding//src/org/adempiere/model/MAttributeSetInstance.java=UTF-8 diff --git a/base/.xdoclet b/base/.xdoclet new file mode 100644 index 0000000000..a336b0bb42 --- /dev/null +++ b/base/.xdoclet @@ -0,0 +1,2 @@ + + diff --git a/base/Base.html b/base/Base.html new file mode 100644 index 0000000000..74bf251253 --- /dev/null +++ b/base/Base.html @@ -0,0 +1,29 @@ + + + +Project Base.jpx + + +

Project Notes

+
+Project: Base Functionality for Server and Client
+Author: Jorg Janke
+Version: $Id: Base.html,v 1.1 2006/04/21 17:41:36 jjanke Exp $ +
+Description: +

+The project creates the jar file Adempiere/base/Base.jar, which is included +in Server and Client jars (i.e. not directly distributed to minimize number of jars). + +

+
+Things to do...
+ + + + + diff --git a/base/RUN_build.bat b/base/RUN_build.bat new file mode 100644 index 0000000000..1c1fcd9104 --- /dev/null +++ b/base/RUN_build.bat @@ -0,0 +1,20 @@ +@Title Build Base +@Rem $Header: /cvsroot/adempiere/base/RUN_build.bat,v 1.10 2005/09/16 00:48:27 jjanke Exp $ +@Echo off + +@CALL ..\utils_dev\myDevEnv.bat +@IF NOT %ADEMPIERE_ENV%==Y GOTO NOBUILD + +@echo Cleanup ... +@"%JAVA_HOME%\bin\java" -Dant.home="." %ANT_PROPERTIES% org.apache.tools.ant.Main clean + +@echo Building ... +@"%JAVA_HOME%\bin\java" -Dant.home="." %ANT_PROPERTIES% org.apache.tools.ant.Main dist + +@Echo Done ... +@sleep 60 +@exit + +:NOBUILD +@Echo Check myDevEnv.bat (copy from myDevEnvTemplate.bat) +@Pause diff --git a/base/RUN_build.sh b/base/RUN_build.sh new file mode 100644 index 0000000000..5f80633c60 --- /dev/null +++ b/base/RUN_build.sh @@ -0,0 +1,18 @@ +# Module compiling script +# Ported from Windows script Marek Mosiewicz + + +SAVED_DIR=`pwd` #save current dir +cd `dirname $0`/../utils_dev #change dir to place where script resides - doesn not work with sym links +UTILS_DEV=`pwd` #this is adempiere source +cd $SAVED_DIR #back to the saved directory + +. $UTILS_DEV/myDevEnv.sh #call environment +echo done +if [ ! $ADEMPIERE_ENV==Y ] ; then + echo "Can't set developemeent environemnt - check myDevEnv.sh" + exit 1 +fi + +echo running Ant +$JAVA_HOME/bin/java -Dant.home="." $ANT_PROPERTIES org.apache.tools.ant.Main diff --git a/base/build.xml b/base/build.xml new file mode 100644 index 0000000000..c22fb9b4ae --- /dev/null +++ b/base/build.xml @@ -0,0 +1,88 @@ + + + + + + + + + This buildfile is used to build the base subproject within + the Adempiere project. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/base/documentation.bat b/base/documentation.bat new file mode 100644 index 0000000000..659c934f80 --- /dev/null +++ b/base/documentation.bat @@ -0,0 +1,5 @@ +@Rem API Documentation for Base + +call ..\doc\documentation.bat src doc -private + +@pause \ No newline at end of file diff --git a/base/packages.txt b/base/packages.txt new file mode 100644 index 0000000000..cd4f9cfa65 --- /dev/null +++ b/base/packages.txt @@ -0,0 +1,6 @@ +org.compiere +org.compiere.impexp +org.compiere.model +org.compiere.report.core +org.compiere.server +org.compiere.util diff --git a/base/packaging-build.xml b/base/packaging-build.xml new file mode 100644 index 0000000000..971b488314 --- /dev/null +++ b/base/packaging-build.xml @@ -0,0 +1,4 @@ + + + + diff --git a/base/src/org/compiere/Base.java b/base/src/org/compiere/Base.java new file mode 100644 index 0000000000..84675bc0ad --- /dev/null +++ b/base/src/org/compiere/Base.java @@ -0,0 +1,156 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere; + +import java.math.*; +import java.util.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Base Library Test Classes mainly for Optimize it + * + * @author Jorg Janke + * @version $Id: Base.java,v 1.5 2006/09/21 20:44:54 jjanke Exp $ + */ +class Base +{ + /** + * Base Test + */ + public static void test() + { + System.out.println("** Before Init **"); //$NON-NLS-1$ + getMemoryUsed(); + Properties ctx = Login.initTest(false); + // Log.printProperties(System.getProperties(), "System", false); + // + System.gc(); // cleanup Init + // + System.out.println("** Before Creation **"); + long start = getMemoryUsed(); + + // ******************************************************************* + + // Table=100, Shipper=142, Window=102, Reference=101 + int AD_Window_ID = 102; + long startTime = System.currentTimeMillis(); + GridWindowVO vo = GridWindowVO.create(Env.getCtx(), 1, AD_Window_ID); + GridWindow w = new GridWindow(vo); + long endDef = System.currentTimeMillis(); + System.out.println("Load Definition Time in ms = " + String.valueOf(endDef-startTime)); + if (1==2) // optional step + { + w.loadCompete(); + long endDefComplete = System.currentTimeMillis(); + System.out.println("Load Definition Complete Time in ms = " + String.valueOf(endDefComplete-startTime)); + } + w.query(); + long endData = System.currentTimeMillis(); + System.out.println("Load Data Time in ms = " + String.valueOf(endData-startTime)); + w.loadCompete(); + long endDataComplete = System.currentTimeMillis(); + System.out.println("Load Data Complete Time in ms = " + String.valueOf(endDataComplete-startTime)); + w.getTab(0).navigate(0); + + // ******************************************************************* +// sleep(); + + System.out.println("** Before Dispose **"); + getMemoryUsed(); + w.dispose(); +// sleep(); + // + System.out.println("** Before GC **"); + getMemoryUsed(); + w = null; + System.gc(); + System.out.println("** After GC **"); + getMemoryUsed(); + System.gc(); + + System.out.println("** Final **"); + long complete = System.currentTimeMillis(); + System.out.println("Complete Time in ms = " + String.valueOf(complete-startTime)); + long end = getMemoryUsed(); + System.out.println("Memory increase in kB = End-Start=" + String.valueOf((end-start)/1024)); + listThreads(); + // + System.out.println("API Test"); + System.out.println("64.72=" + MConversionRate.convert(ctx, new BigDecimal(100.0), 116, 100,0,0)); + System.out.println("0.647169=" + MConversionRate.getRate(116, 100, null, 0,0,0)); + System.out.println("12.5=" + MUOMConversion.convert(101, 102, new BigDecimal(100.0), true)); + + } // Base + + /** + * Get Used Memory in bytes + * @return memory used + */ + private static long getMemoryUsed() + { + long free = Runtime.getRuntime().freeMemory(); + long total = Runtime.getRuntime().totalMemory(); + long used = total - free; + // + System.out.println("Memory used in kB = Total(" + + String.valueOf(total/1024) + ")-Free(" + + String.valueOf(free/1024) + ") = " + String.valueOf(used/1024)); + System.out.println("Active Threads=" + Thread.activeCount()); + return used; + } // getMemoryUsed + + /** + * Sleep for a second + */ + private static void sleep() + { + System.out.println(".. sleeping-ini .. -> " + Thread.activeCount()); + Thread.yield(); + try + { + Thread.sleep(1000); + } + catch (final InterruptedException ie) + {} + System.out.println(".. sleeping-end .. -> " + Thread.activeCount()); + } // sleep + + /** + * List Threads + */ + private static void listThreads() + { + Thread[] list = new Thread[Thread.activeCount()]; + // int no = Thread.currentThread().enumerate(list); + for (int i = 0; i < list.length; i++) + { + if (list[i] != null) + System.out.println("Thread " + i + " - " + list[i].toString()); + } + } // listThreads + + /** + * Start + * @param args ignored + */ + public static void main(String[] args) + { + Base.test(); + Env.exitEnv(0); + } // main +} // Base diff --git a/base/src/org/compiere/MigrateData.java b/base/src/org/compiere/MigrateData.java new file mode 100644 index 0000000000..9f8f6a08e3 --- /dev/null +++ b/base/src/org/compiere/MigrateData.java @@ -0,0 +1,132 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; +import org.compiere.model.*; +import org.compiere.print.*; + +/** + * Migrate Data + * @author Jorg Janke + * @version $Id: MigrateData.java,v 1.3 2006/07/30 00:51:06 jjanke Exp $ + */ +public class MigrateData +{ + /** + * Migrate Data. + * Called from DB.afterMigration + */ + public MigrateData () + { + release252c(); + + // Update existing Print Format + PrintFormatUtil pfu = new PrintFormatUtil (Env.getCtx()); + pfu.addMissingColumns(); + } // MigrateData + + /** Logger */ + private static CLogger log = CLogger.getCLogger (MigrateData.class); + + /** + * Release 252c + */ + private void release252c() + { + String sql = "SELECT COUNT(*) FROM M_ProductDownload"; + int no = DB.getSQLValue(null, sql); + if (no > 0) + { + log.finer("No Need - Downloads #" + no); + return; + } + // + int count = 0; + sql = "SELECT AD_Client_ID, AD_Org_ID, M_Product_ID, Name, DownloadURL " + + "FROM M_Product " + + "WHERE DownloadURL IS NOT NULL"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + int AD_Client_ID = rs.getInt(1); + int AD_Org_ID = rs.getInt(2); + int M_Product_ID = rs.getInt(3); + String Name = rs.getString(4); + String DownloadURL = rs.getString(5); + // + Properties ctx = new Properties (Env.getCtx()); + Env.setContext(ctx, "#AD_Client_ID", AD_Client_ID); + Env.setContext(ctx, "AD_Client_ID", AD_Client_ID); + Env.setContext(ctx, "#AD_Org_ID", AD_Org_ID); + Env.setContext(ctx, "AD_Org_ID", AD_Org_ID); + MProductDownload pdl = new MProductDownload(ctx, 0, null); + pdl.setM_Product_ID(M_Product_ID); + pdl.setName(Name); + pdl.setDownloadURL(DownloadURL); + if (pdl.save()) + { + count++; + String sqlUpdate = "UPDATE M_Product SET DownloadURL = NULL WHERE M_Product_ID=" + M_Product_ID; + int updated = DB.executeUpdate(sqlUpdate, null); + if (updated != 1) + log.warning("Product not updated"); + } + else + log.warning("Product Download not created M_Product_ID=" + M_Product_ID); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + log.info("#" + count); + } // release252c + + + /** + * Migrate Data + * @param args ignored + */ + public static void main (String[] args) + { + Adempiere.startup(true); + new MigrateData(); + } // main + +} // MigrateData diff --git a/base/src/org/compiere/cm/CStageValidate.java b/base/src/org/compiere/cm/CStageValidate.java new file mode 100644 index 0000000000..2833fe1f75 --- /dev/null +++ b/base/src/org/compiere/cm/CStageValidate.java @@ -0,0 +1,63 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.cm; + +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.process.*; + +/** + * Validate Container Stage + * + * @author Jorg Janke + * @version $Id: CStageValidate.java,v 1.3 2006/07/30 00:51:06 jjanke Exp $ + */ +public class CStageValidate extends SvrProcess +{ + private int p_CM_CStage_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_CM_CStage_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt () + throws Exception + { + log.info("CM_CStage_ID=" + p_CM_CStage_ID); + MCStage stage = new MCStage (getCtx(), p_CM_CStage_ID, get_TrxName()); + return stage.validate(); + } // doIt + +} // CStageValidate diff --git a/base/src/org/compiere/cm/CacheHandler.java b/base/src/org/compiere/cm/CacheHandler.java new file mode 100644 index 0000000000..cae8363375 --- /dev/null +++ b/base/src/org/compiere/cm/CacheHandler.java @@ -0,0 +1,192 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.cm; + +import java.io.IOException; +import java.io.Reader; +import java.util.*; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import org.compiere.util.*; +import org.compiere.model.*; + +/** + * The CacheHandler handles deployment and clean of internal and external caches + * + * @author Yves Sandfort + * @version $Id$ + */ +public class CacheHandler { + protected String[] cacheURLs; + protected CLogger log; + + /** + * CacheHandler for single URL environment + * @param thisURL URL of this Server + * @param tLog thisLogger + * @param ctx Propertie Context + * @param trxName Transaction + */ + public CacheHandler(String thisURL, CLogger tLog, Properties ctx, String trxName) { + int [] theseServers = X_CM_BroadcastServer.getAllIDs ("CM_BroadcastServer", "CM_WebProject_ID=0", trxName); + if (theseServers!=null && theseServers.length>0) { + String [] thisURLs = new String [theseServers.length]; + for(int i=0;i=0) { + JNPURL = JNPURL.substring(JNPURL.indexOf("jnp://")+6); + } + if (JNPURL.indexOf(":")>=0) { + JNPURL = JNPURL.substring(0,JNPURL.indexOf(":")); + } + if (JNPURL.length()>0) { + return JNPURL; + } else { + return null; + } + } +} diff --git a/base/src/org/compiere/cm/CalloutTemplate.java b/base/src/org/compiere/cm/CalloutTemplate.java new file mode 100644 index 0000000000..71670bf5a8 --- /dev/null +++ b/base/src/org/compiere/cm/CalloutTemplate.java @@ -0,0 +1,56 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.cm; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; +import org.compiere.model.*; + +/** + * Template + * + * @author Yves Sandfort + * @version $Id$ + */ +public class CalloutTemplate extends CalloutEngine +{ + /** + * Invoice Line - Charge. + * - updates PriceActual from Charge + * - sets PriceLimit, PriceList to zero + * Calles tax + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String invalidate (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + // Summary ? + if (mTab.getValue("IsSummary")!=null) + { + mTab.setValue("IsValid", false); + return ""; + } + return ""; + } // charge +} // CalloutTemplate diff --git a/base/src/org/compiere/cm/MediaDirectDeploy.java b/base/src/org/compiere/cm/MediaDirectDeploy.java new file mode 100644 index 0000000000..c2642246f8 --- /dev/null +++ b/base/src/org/compiere/cm/MediaDirectDeploy.java @@ -0,0 +1,27 @@ +/****************************************************************************** + * 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. + * 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. + * You may reach us at: ComPiere, Inc. - http://www.adempiere.org/license.html + * 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA or info@adempiere.org + *****************************************************************************/ +package org.compiere.cm; + + +/** + * + * + * @author Yves Sandfort + * @version $Id$ + */ +public class MediaDirectDeploy +{ +} diff --git a/base/src/org/compiere/cm/StringUtil.java b/base/src/org/compiere/cm/StringUtil.java new file mode 100644 index 0000000000..74978639e0 --- /dev/null +++ b/base/src/org/compiere/cm/StringUtil.java @@ -0,0 +1,307 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.cm; + +import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/* + * @author Yves Sandfort + * @version $Revision$ + */ + +/** + * StringUtil is a helper class to run different String managements not implemented in Java Core + * + * @author Yves Sandfort + * @version $id$ + * + */ +public class StringUtil { + /** + * Replace all occurences of search with replace in original + * @param original the original String + * @param search the string to look for + * @param replace the string we will replace search with + * @return StringBuffer with result + */ + public static StringBuffer replace(StringBuffer original, String search, String replace) { + return doReplace (original, search, replace, false, true); + } + + /** + * Replace all occurences of search with replace in original + * @param original the original String + * @param search the string to look for + * @param replace the string we will replace search with + * @return String with result, null will get replaced by "" + */ + public static String replace (String original, String search, String replace) { + if (original==null) original = ""; + return doReplace (new StringBuffer(original), search, replace, false, true).toString(); + } + + /** + * Replace all occurences of search with replace in original + * @param original the original String + * @param search the string to look for + * @param replace the string we will replace search with + * @return String with result, null will get replaced by "" + */ + public static String replace (String original, char search, String replace) { + if (original==null) original = ""; + return doReplace (new StringBuffer(original), search, replace, true).toString(); + } + + /** + * Replace all or one occurence of search with replace in original + * @param original the original StringBuffer + * @param search String to get replaced + * @param replace String to replace + * @param ignoreCase should we ignore cases + * @param allOccurences should all Occurences get replaced + * @return StringBuffer with result + */ + public static StringBuffer replace(StringBuffer original, String search, String replace, boolean ignoreCase, boolean allOccurences) { + return doReplace (original, search, replace, ignoreCase, allOccurences); + } + + /** + * Replace all or one occurence of search with replace in original + * @param original the original StringBuffer + * @param search String to get replaced + * @param replace String to replace + * @param ignoreCase should we ignore cases + * @param allOccurences should all Occurences get replaced + * @return StringBuffer with result + */ + public static String replace(String original, String search, String replace, boolean ignoreCase, boolean allOccurences) { + if (original==null) original=""; + return replace(new StringBuffer(original), search, replace, ignoreCase, allOccurences).toString(); + } + + /** + * Replace one occurence of search with replace in original + * @param original StringBuffer + * @param search String to look for + * @param replace String to replace search with + * @return new StringBuffer with result + */ + public static StringBuffer replaceOne(StringBuffer original, String search, String replace) { + if (original.toString().indexOf(search)>=0) { + original.replace(original.toString().indexOf(search),original.toString().indexOf(search)+search.length(),replace); + } + return original; + } + + /** + * Replace one occurence of search with replace in original + * @param original String to look in + * @param search String to search for + * @param replace String to replace search with + * @return new String with result + */ + public static String replaceOne(String original, String search, String replace) { + StringBuffer toriginal = new StringBuffer(original); + if (toriginal.toString().indexOf(search)>=0) { + toriginal.replace(toriginal.toString().indexOf(search),toriginal.toString().indexOf(search)+search.length(),replace); + } + return toriginal.toString(); + } + + /** + * Run RegEx Expression against original String + * @param original StringBuffer with original context + * @param regex Regular Expression to run as query + * @param replace Replace String + * @param CASE_INSENSITIVE whether we should take care of case or not + * @return StringBuffer with result + */ + public static StringBuffer replaceRegex(StringBuffer original, String regex, String replace, boolean CASE_INSENSITIVE) { + int flags=0; + if (CASE_INSENSITIVE) flags=Pattern.CASE_INSENSITIVE; + Pattern p = Pattern.compile(regex, flags); + Matcher m = p.matcher(original); + StringBuffer newSB = new StringBuffer(); + boolean result = m.find(); + while(result) { + m.appendReplacement(newSB, replace); + result = m.find(); + } + m.appendTail(newSB); + return newSB; + } + + /** + * Run RegEx Expression against original String + * @param original StringBuffer with original context + * @param regex Regular Expression to run as query + * @param replace Replace String + * @param CASE_INSENSITIVE whether we should take care of case or not + * @return String with result + */ + public static String replaceRegex(String original, String regex, String replace, boolean CASE_INSENSITIVE) { + return replaceRegex(new StringBuffer(original), regex, replace, CASE_INSENSITIVE).toString(); + } + + private static StringBuffer doReplace(StringBuffer original, String alt, String neu, boolean ignoreCase, boolean allOccurences) { + int position = -1; + if (alt==null) alt=""; + if (neu==null) neu=""; + if (original==null) original = new StringBuffer(""); + int altNeuDiff = neu.length()-alt.length(); + if (neu.lastIndexOf(alt)>=altNeuDiff) altNeuDiff = neu.lastIndexOf(alt)+1; + if (ignoreCase) { + position = original.toString().toLowerCase().indexOf(alt.toLowerCase()); + while (position>=0) { + original.replace(position,position + alt.length(),neu); + position = original.toString().toLowerCase().indexOf(alt.toLowerCase(),position+altNeuDiff); + } + } else { + position = original.toString().indexOf(alt); + while (position>=0) { + original.replace(position,position + alt.length(),neu); + position = original.toString().indexOf(alt,position+altNeuDiff); + } + } + return original; + } + + private static StringBuffer doReplace(StringBuffer original, char alt, String neu, boolean allOccurences) { + int position = -1; + if (original==null) original = new StringBuffer(""); + int altNeuDiff = neu.length()-1; + if (neu.lastIndexOf(alt)>=altNeuDiff) altNeuDiff = neu.lastIndexOf(alt)+1; + position = original.toString().indexOf(alt); + while (position>=0) { + original.replace(position,position + 1,neu); + position = original.toString().indexOf(alt,position+altNeuDiff); + } + return original; + } + + /** + * This function will split a string based on a split character. + * @param searchIn The string to split + * @param splitter The separator + * @return String array of split values + */ + public static String[] split(String searchIn, String splitter) { + String[] results = new String[count(searchIn,splitter)+1]; + int position=0; + int i=0; + while (searchIn.indexOf(splitter,position)>=0) { + results[i]=searchIn.substring(position,searchIn.indexOf(splitter,position+2)); + position = searchIn.indexOf(splitter,position)+1; + i++; + } + results[(results.length-1)]=searchIn.substring(position); + return results; + } + + /** + * Remove String toBeRemoved from oroginal + * @param original String to look in + * @param toBeRemoved String to get removed + * @param ignoreCase should we take care of case + * @return String without toBeRemoved + */ + public static String remove(String original, String toBeRemoved, boolean ignoreCase) { + String thisResult = null; + if (!toBeRemoved.equals("") && toBeRemoved!=null) { + thisResult = replace(original, toBeRemoved, "", ignoreCase, true); + } + return thisResult; + } + + /** + * To split for indexes we will look for the next Word in tempstr + * @param tempStr to look into + * @return nextWord in String + */ + public static String getNextWord(String tempStr) { + String word = ""; + if (tempStr.indexOf(" ")>=0) { + word=tempStr.substring(0,tempStr.indexOf(" ")); + } else { + word=tempStr; + } + return word; + } + + /** + * For some save scnearios and analysis we should remove special characters, i.e. HTML + * @param tempStr to remove Special Char + * @return new String without special chars + */ + public static String removeSpecialChar(String tempStr) { + if (tempStr!=null) { + tempStr=replace(tempStr,",","", true, true); + tempStr=replace(tempStr,".","", true, true); + tempStr=replace(tempStr,"!","", true, true); + tempStr=replace(tempStr,"?","", true, true); + tempStr=replace(tempStr,"'","", true, true); + tempStr=replace(tempStr,":","", true, true); + tempStr=replace(tempStr,"(","", true, true); + tempStr=replace(tempStr,")","", true, true); + tempStr=replace(tempStr,"+","", true, true); + tempStr=replace(tempStr,"-","", true, true); + tempStr=replace(tempStr,">","", true, true); + tempStr=replace(tempStr,"<","", true, true); + tempStr=replace(tempStr,"/","", true, true); + while (tempStr.indexOf(" ")>0) { + tempStr=replace(tempStr," "," ", true, true); + } + tempStr=replace(tempStr," "," ", true, true); + } + return tempStr; + } + + /** + * Should return you the number of occurences of "find" in "orig + * @param orig The String to look in + * @param find The String to look for + * @return Number of occurences, 0 if none + */ + + public static int count(String orig, String find) { + int retVal = 0; + int pos = 0; + while (orig.indexOf(find,pos)>0) { + pos = orig.indexOf(find,pos)+1; + retVal++; + } + return retVal; + } + + /** + * Gnerate CRC String for tempStr + * @param tempStr + * @return CRC Code for tempStr + * @throws IOException + */ + public static String crc(String tempStr) throws IOException { + java.util.zip.Adler32 inChecker = new java.util.zip.Adler32(); + java.util.zip.CheckedInputStream in = null; + in = new java.util.zip.CheckedInputStream(new java.io.ByteArrayInputStream(tempStr.getBytes()), inChecker); + @SuppressWarnings("unused") int c; + while ((c = in.read()) != -1) c=0; + String myCheckSum = "" + inChecker.getValue(); + return myCheckSum; + } +} diff --git a/base/src/org/compiere/cm/TemplateValidate.java b/base/src/org/compiere/cm/TemplateValidate.java new file mode 100644 index 0000000000..61ccfca5f9 --- /dev/null +++ b/base/src/org/compiere/cm/TemplateValidate.java @@ -0,0 +1,57 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.cm; + +import java.util.logging.Level; +import org.compiere.process.*; +import org.compiere.model.*; + +/** + * CM Template Validation Process + * + * @author Jorg Janke + * @version $Id: TemplateValidate.java,v 1.3 2006/08/08 13:29:49 comdivision Exp $ + */ +public class TemplateValidate extends SvrProcess +{ + @Override + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + //else if (name.equals("CM_WebProject_ID")) + //p_CM_WebProject_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + @Override + protected String doIt () + throws Exception + { + MTemplate thisTemplate = new MTemplate(getCtx (), getRecord_ID (), get_TrxName ()); + thisTemplate.setIsValid (true); + thisTemplate.save (); + return null; + } + +} // TemplateValidate diff --git a/base/src/org/compiere/cm/WebProjectDeploy.java b/base/src/org/compiere/cm/WebProjectDeploy.java new file mode 100644 index 0000000000..1be0160bd9 --- /dev/null +++ b/base/src/org/compiere/cm/WebProjectDeploy.java @@ -0,0 +1,185 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.cm; + +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Deploy Web Project + * + * @author Jorg Janke + * @version $Id: WebProjectDeploy.java,v 1.10 2006/09/04 21:21:31 comdivision Exp $ + */ +public class WebProjectDeploy extends SvrProcess +{ + /** WebProject */ + private int p_CM_WebProject_ID = 0; + + /** Project */ + private MWebProject m_project = null; + /** Stage Hash Map */ + private HashMap m_map = new HashMap(); + /** List of IDs */ + private ArrayList m_idList = new ArrayList(); + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("CM_WebProject_ID")) + p_CM_WebProject_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt () + throws Exception + { + org.compiere.cm.CacheHandler thisHandler = new org.compiere.cm.CacheHandler(org.compiere.cm.CacheHandler.convertJNPURLToCacheURL(getCtx().getProperty("java.naming.provider.url")), log, getCtx(), get_TrxName()); + + log.info("CM_WebProject_ID=" + p_CM_WebProject_ID); + m_project = new MWebProject(getCtx(), p_CM_WebProject_ID, get_TrxName()); + if (m_project.get_ID() != p_CM_WebProject_ID) + throw new AdempiereUserError("@NotFound@ @CM_WebProject_ID@ " + p_CM_WebProject_ID); + + // Deploy Media + MMedia[] media = MMedia.getMedia(m_project); + MMediaServer[] mserver = MMediaServer.getMediaServer(m_project); + for (int i = 0; i < mserver.length; i++) + mserver[i].deploy(media); + + // Stage + MCStage[] stages = MCStage.getStages(m_project); + for (int i = 0; i < stages.length; i++) + m_map.put(new Integer(stages[i].getCM_CStage_ID()), stages[i]); + + // Copy Stage Tree + MTree treeS = new MTree (getCtx(), m_project.getAD_TreeCMS_ID(), false, false, get_TrxName()); + MTreeNode root = treeS.getRoot(); + copyStage(root, "/"); + + // Delete Inactive Containers + MContainer[] containers = MContainer.getContainers(m_project); + for (int i = 0; i < containers.length; i++) + { + MContainer container = containers[i]; + if (!m_idList.contains(new Integer(container.getCM_Container_ID()))) + { + String name = container.getName(); + if (container.delete(true)) + log.fine("Deleted: " + name); + else // e.g. was referenced + { + log.warning("Failed Delete: " + name); + addLog(0,null,null, "@Error@ @Delete@: " + name); + } + } + // Remove Container from cache + thisHandler.cleanContainer(container.get_ID()); + } // Delete Inactive + + // Sync Stage & Container Tree + MTree_NodeCMS nodesCMS[] = MTree_NodeCMS.getTree(getCtx(), m_project.getAD_TreeCMS_ID(), get_TrxName()); + MTree_NodeCMC nodesCMC[] = MTree_NodeCMC.getTree(getCtx(), m_project.getAD_TreeCMC_ID(), get_TrxName()); + for (int s = 0; s < nodesCMS.length; s++) + { + MTree_NodeCMS nodeCMS = nodesCMS[s]; + int Node_ID = nodeCMS.getNode_ID(); + for (int c = 0; c < nodesCMC.length; c++) + { + MTree_NodeCMC nodeCMC = nodesCMC[c]; + if (nodeCMC.getNode_ID() == Node_ID) + { + //if (nodeCMS.getParent_ID()!=0) + nodeCMC.setParent_ID(nodeCMS.getParent_ID()); + nodeCMC.setSeqNo(nodeCMS.getSeqNo()); + nodeCMC.save(); + break; + } + } + } // for all stage nodes + // Clean ContainerTree Cache + thisHandler.cleanContainerTree (p_CM_WebProject_ID); + + return "@Copied@ @CM_Container_ID@ #" + m_idList.size(); + } // doIt + + + /** + * Copy Stage + * @param node node + * @param path path + */ + private void copyStage (MTreeNode node, String path) + { + org.compiere.cm.CacheHandler thisHandler = new org.compiere.cm.CacheHandler(org.compiere.cm.CacheHandler.convertJNPURLToCacheURL(getCtx().getProperty("java.naming.provider.url")), log, getCtx(), get_TrxName()); + Integer ID = new Integer(node.getNode_ID()); + MCStage stage = m_map.get(ID); + // + int size = node.getChildCount(); + for (int i = 0; i < size; i++) + { + MTreeNode child = (MTreeNode)node.getChildAt(i); + ID = new Integer(child.getNode_ID()); + stage = m_map.get(ID); + if (stage == null) + { + log.warning("Not Found ID=" + ID); + continue; + } + if (!stage.isActive()) + continue; + // + if (stage != null && stage.isModified()) + { + MContainer cc = MContainer.copy (m_project, stage, path); + if (cc != null) + { + addLog (0, null, null, "@Copied@: " + cc.getName()); + m_idList.add(ID); + } + // Remove Container from cache + thisHandler.cleanContainer(cc.get_ID()); + // Reset Modified flag... + stage.setIsModified(false); + stage.save(stage.get_TrxName()); + } + if (child.isSummary()) + copyStage (child, path + stage.getRelativeURL() + "/"); + + } + } // copyStage + +} // WebProjectDeploy diff --git a/base/src/org/compiere/impexp/BankStatementLoaderInterface.java b/base/src/org/compiere/impexp/BankStatementLoaderInterface.java new file mode 100644 index 0000000000..8afff1ac24 --- /dev/null +++ b/base/src/org/compiere/impexp/BankStatementLoaderInterface.java @@ -0,0 +1,265 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.impexp; + +import org.compiere.model.*; + +import java.math.BigDecimal; +import java.sql.Timestamp; + + +/** + * Interface to be implemented by bank statement loader classes + * + * Bank statement loader classes that extend this interface can be loaded + * by the MBankStatementLoader controller class. + * The usage patter looks like this: + * + * -init() is called in order to initialize the loader + * + * -validate() is called, allowing the loader to perform data validation if + * it provides this. + * + * -loadLines() is called, request the loader to start loading statement lines + * + * -for everu statement line that the loader encounteres, it calls the + * saveLine() method of the MBankStatement controller object it obtained + * as part of the call to init() + * + * -The MBankStatementLoader controller object can now obtain the data for the current bank + * statement line by using the corresponding get methods of the loader class. + * + * @author Maarten Klinker, Eldir Tomassen + * @version $Id: BankStatementLoaderInterface.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ + +public interface BankStatementLoaderInterface +{ + /** + * Initialize the loader + * @param controller Reference to the MBankStatementLoader controller object + * @return Initialized succesfully + */ + public boolean init(MBankStatementLoader controller); + + /** + * Verify whether the data to be imported is valid + * @return Data is valid + * If the actual loaders does not do any validity checks + * it will just return true. + */ + public boolean isValid(); + + /** + * Start importing statement lines + * @return Statement lines imported succesfully + */ + public boolean loadLines(); + + /** + * Return the most recent error + * @return Error message + * This error message will be handled as a Adempiere message, + * (e.g. it can be translated) + */ + public String getLastErrorMessage(); + + /** + * Return the most recent error description + * @return Error discription + * This is an additional error description, it can be used to provided + * descriptive iformation, such as a file name or SQL error, that can not + * be translated by the Adempiere message system. + */ + public String getLastErrorDescription(); + + /** + * The last time this loader aquired bank statement data. + * For OFX this is the value. This is generally only available\ + * after loadLines() has been called. If a specific loader class + * does not provided this information it is allowed to return null + * @return Date last run + */ + public Timestamp getDateLastRun(); + + /** + * The routing number of the bank account for the statement line. + * @return Routing number + */ + public String getRoutingNo(); + + /** + * The account number of the bank account for the statement line. + * @return Bank account number + */ + public String getBankAccountNo(); + + /** + * Additional reference information + * Statement level reference information. If a specific loader class + * does not provided this, it is allowed to return null. + * @return Error discription + */ + public String getStatementReference(); + + /** + * Statement Date + * Date of the bank statement. If a specific loader does not provide this, + * it is allowed to return null. + * @return Statement Date + */ + public Timestamp getStatementDate(); + + /** + * Transaction ID assigned by the bank. + * For OFX this is the + * If a specific loader does not provide this, it is allowed to return + * null. + * @return Transaction ID + */ + public String getTrxID(); + + /** + * Additional reference information + * Statement line level reference information. + * For OFX this is the field. + * If a specific loader does not provided this, it is allowed to return null. + * @return Error discription + */ + public String getReference(); + + /** + * Check number + * Check number, in case the transaction was initiated by a check. + * For OFX this is the field, for MS-Money (OFC) this is the + * field. + * If a specific loader does not provide this, it is allowed to return null. + * @return Transaction reference + */ + public String getCheckNo(); + + /** + * Payee name + * Name information, for OFX this is the or + * field + * If a specific loader class does not provide this, it is allowed + * to return null. + * @return Payee name + */ + public String getPayeeName(); + + /** + * Payee account + * Account information of "the other party" + * If a specific loader class does not provide this, it is allowed + * to return null. + * @return Payee bank account number + */ + public String getPayeeAccountNo(); + + /** + * Statement line date + * This has to be provided by all loader classes. + * @return Statement line date + */ + public Timestamp getStatementLineDate(); + + /** + * Effective date + * Date theat the funds became available. + * If a specific loader does not provide this, it is allowed to return null. + * @return Effective date + */ + public Timestamp getValutaDate(); + + /** + * Transaction type + * @return Transaction type + * This returns the transaction type as used by the bank + * Whether a transaction is credit or debit depends on the amount (i.e. negative), + * this field is for reference only. + * If a specific loader class does not provide this, it is allowed + * to return null. + */ + public String getTrxType(); + + /** + * Indicates whether this transaction is a reversal + * @return true if this is a reversal + */ + public boolean getIsReversal(); + + /** + * Currency + * @return Currency + * Return the currency, if included in the statement data. + * It is returned as it appears in the import data, it should + * not be processed by the loader in any way. + * If a specific loader class does not provide this, it is allowed + * to return null. + */ + public String getCurrency(); + + /** + * Statement line amount + * @return Statement Line Amount + * This has to be provided by all loader classes. + */ + public BigDecimal getStmtAmt(); + + /** + * Transaction Amount + * @return Transaction Amount + */ + public BigDecimal getTrxAmt(); + + /** + * Interest Amount + * @return Interest Amount + */ + public BigDecimal getInterestAmt(); + + /** + * Transaction memo + * @return Memo + * Additional descriptive information. + * For OFX this is the filed, for SWIFT MT940 + * this is the "86" line. + * If a specific loader does not provide this, it is allowed to return null. + */ + public String getMemo(); + + /** + * Charge name + * @return Charge name + * Name of the charge, in case this transaction is a bank charge. + * If a specific loader class does not provide this, it is allowed + * to return null. + */ + public String getChargeName(); + + /** + * Charge amount + * @return Charge amount + * Name of the charge, in case this transaction is a bank charge. + * If a specific loader class does not provide this, it is allowed + * to return null. + */ + public BigDecimal getChargeAmt(); + +} //BankStatementLoaderInterface + diff --git a/base/src/org/compiere/impexp/BankStatementMatchInfo.java b/base/src/org/compiere/impexp/BankStatementMatchInfo.java new file mode 100644 index 0000000000..47917e0511 --- /dev/null +++ b/base/src/org/compiere/impexp/BankStatementMatchInfo.java @@ -0,0 +1,103 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.impexp; + +/** + * Bank Statement Match Information. + * Returned by Bank Statement Matcher + * + * @author Jorg Janke + * @version $Id: BankStatementMatchInfo.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class BankStatementMatchInfo +{ + /** + * Standard Constructor + */ + public BankStatementMatchInfo() + { + super(); + } // BankStatementMatchInfo + + + private int m_C_BPartner_ID = 0; + private int m_C_Payment_ID = 0; + private int m_C_Invoice_ID = 0; + + + /** + * Do we have a match? + * @return true if something could be matched + */ + public boolean isMatched() + { + return m_C_BPartner_ID > 0 || m_C_Payment_ID > 0 || m_C_Invoice_ID > 0; + } // isValid + + + /** + * Get matched BPartner + * @return BPartner + */ + public int getC_BPartner_ID() + { + return m_C_BPartner_ID; + } + /** + * Set matched BPartner + * @param C_BPartner_ID BPartner + */ + public void setC_BPartner_ID (int C_BPartner_ID) + { + m_C_BPartner_ID = C_BPartner_ID; + } + + /** + * Get matched Payment + * @return Payment + */ + public int getC_Payment_ID() + { + return m_C_Payment_ID; + } + /** + * Set matched Payment + * @param C_Payment_ID payment + */ + public void setC_Payment_ID (int C_Payment_ID) + { + m_C_Payment_ID = C_Payment_ID; + } + + /** + * Get matched Invoice + * @return invoice + */ + public int getC_Invoice_ID() + { + return m_C_Invoice_ID; + } + /** + * Set matched Invoice + * @param C_Invoice_ID invoice + */ + public void setC_Invoice_ID (int C_Invoice_ID) + { + m_C_Invoice_ID = C_Invoice_ID; + } + +} // BankStatementMatchInfo diff --git a/base/src/org/compiere/impexp/BankStatementMatcherInterface.java b/base/src/org/compiere/impexp/BankStatementMatcherInterface.java new file mode 100644 index 0000000000..a29b1884a5 --- /dev/null +++ b/base/src/org/compiere/impexp/BankStatementMatcherInterface.java @@ -0,0 +1,45 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.impexp; + +import org.compiere.model.*; + +/** + * Bank Statement Matcher Algorithm Interface + * + * @author Jorg Janke + * @version $Id: BankStatementMatcherInterface.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public interface BankStatementMatcherInterface +{ + /** + * Match Bank Statement Line + * @param bsl bank statement line + * @return found matches or null + */ + public BankStatementMatchInfo findMatch (MBankStatementLine bsl); + + + /** + * Match Bank Statement Import Line + * @param ibs bank statement import line + * @return found matches or null + */ + public BankStatementMatchInfo findMatch (X_I_BankStatement ibs); + + +} // BankStatementMatcherInterface diff --git a/base/src/org/compiere/impexp/CopyImportFormat.java b/base/src/org/compiere/impexp/CopyImportFormat.java new file mode 100644 index 0000000000..9559cc217a --- /dev/null +++ b/base/src/org/compiere/impexp/CopyImportFormat.java @@ -0,0 +1,89 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.impexp; + +import java.math.*; +import java.util.logging.*; +import org.compiere.process.*; + + +/** + * Copy Import Format (lines) + * + * @author Jorg Janke + * @version $Id: CopyImportFormat.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class CopyImportFormat extends SvrProcess +{ + private int from_AD_ImpFormat_ID = 0; + private int to_AD_ImpFormat_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_ImpFormat_ID")) + from_AD_ImpFormat_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + to_AD_ImpFormat_ID = getRecord_ID(); + } // prepare + + + /** + * Process Copy + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("doIt = From=" + from_AD_ImpFormat_ID + " To=" + to_AD_ImpFormat_ID); + MImpFormat from = new MImpFormat (getCtx(), from_AD_ImpFormat_ID, get_TrxName()); + if (from.getAD_ImpFormat_ID() != from_AD_ImpFormat_ID) + throw new Exception ("From Format not found - " + from_AD_ImpFormat_ID); + // + MImpFormat to = new MImpFormat (getCtx(), to_AD_ImpFormat_ID, get_TrxName()); + if (to.getAD_ImpFormat_ID() != to_AD_ImpFormat_ID) + throw new Exception ("To Format not found - " + from_AD_ImpFormat_ID); + // + if (from.getAD_Table_ID() != to.getAD_Table_ID()) + throw new Exception ("From-To do Not have same Format Table"); + // + MImpFormatRow[] rows = from.getRows(); // incl. inactive + for (int i = 0; i < rows.length; i++) + { + MImpFormatRow row = rows[i]; + MImpFormatRow copy = new MImpFormatRow (to, row); + if (!copy.save()) + throw new Exception ("Copy error"); + } + + String msg = "#" + rows.length; + if (!from.getFormatType().equals(to.getFormatType())) + return msg + " - Note: Format Type different!"; + return msg; + } // doIt + +} // CopyImportFormat diff --git a/base/src/org/compiere/impexp/ImpFormat.java b/base/src/org/compiere/impexp/ImpFormat.java new file mode 100644 index 0000000000..4f0157f4b0 --- /dev/null +++ b/base/src/org/compiere/impexp/ImpFormat.java @@ -0,0 +1,600 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.impexp; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Import Format a Row + * + * @author Jorg Janke + * @version $Id: ImpFormat.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public final class ImpFormat +{ + /** + * Format + * @param name name + * @param AD_Table_ID table + * @param formatType format type + */ + public ImpFormat (String name, int AD_Table_ID, String formatType) + { + setName(name); + setTable(AD_Table_ID); + setFormatType(formatType); + } // ImpFormat + + /** Logger */ + private static CLogger log = CLogger.getCLogger(ImpFormat.class); + + private String m_name; + private String m_formatType; + + /** The Table to be imported */ + private int m_AD_Table_ID; + private String m_tableName; + private String m_tablePK; + private String m_tableUnique1; + private String m_tableUnique2; + private String m_tableUniqueParent; + private String m_tableUniqueChild; + // + private String m_BPartner; + private ArrayList m_rows = new ArrayList(); + + /** + * Set Name + * @param newName new name + */ + public void setName(String newName) + { + if (newName == null || newName.length() == 0) + throw new IllegalArgumentException("Name must be at least 1 char"); + else + m_name = newName; + } + + /** + * Get Name + * @return name + */ + public String getName() + { + return m_name; + } // getName + + /** + * Import Table + * @param AD_Table_ID table + */ + public void setTable (int AD_Table_ID) + { + m_AD_Table_ID = AD_Table_ID; + m_tableName = null; + m_tablePK = null; + String sql = "SELECT t.TableName,c.ColumnName " + + "FROM AD_Table t INNER JOIN AD_Column c ON (t.AD_Table_ID=c.AD_Table_ID AND c.IsKey='Y') " + + "WHERE t.AD_Table_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Table_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + m_tableName = rs.getString(1); + m_tablePK = rs.getString(2); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "ImpFormat.setTable", e); + } + if (m_tableName == null || m_tablePK == null) + log.log(Level.SEVERE, "Data not found for AD_Table_ID=" + AD_Table_ID); + + // Set Additional Table Info + m_tableUnique1 = ""; + m_tableUnique2 = ""; + m_tableUniqueParent = ""; + m_tableUniqueChild = ""; + + if (m_AD_Table_ID == 311) // I_061_SyncItem + { + m_tableUnique1 = "H_UPC"; // UPC = unique + m_tableUnique2 = "Value"; + m_tableUniqueChild = "H_Commodity1"; // Vendor No may not be unique ! + m_tableUniqueParent = "H_PartnrID"; // Makes it unique + } + else if (m_AD_Table_ID == 532) // I_Product + { + m_tableUnique1 = "UPC"; // UPC = unique + m_tableUnique2 = "Value"; + m_tableUniqueChild = "VendorProductNo"; // Vendor No may not be unique ! + m_tableUniqueParent = "BPartner_Value"; // Makes it unique + } + else if (m_AD_Table_ID == 533) // I_BPartner + { + m_tableUnique1 = "Value"; // the key + } + else if (m_AD_Table_ID == 534) // I_ElementValue + { + m_tableUniqueParent = "ElementName"; // the parent key + m_tableUniqueChild = "Value"; // the key + } + else if (m_AD_Table_ID == 535) // I_ReportLine + { + m_tableUniqueParent = "ReportLineSetName"; // the parent key + m_tableUniqueChild = "Name"; // the key + } + } // setTable + + /** + * Get Import Table Name + * @return AD_Table_ID + */ + public int getAD_Table_ID() + { + return m_AD_Table_ID; + } // getAD_Table_ID + + /** Format Type - Fixed Length F */ + public static final String FORMATTYPE_FIXED = "F"; + /** Format Type - Comma Separated C */ + public static final String FORMATTYPE_COMMA = "C"; + /** Format Type - Tab Separated T */ + public static final String FORMATTYPE_TAB = "T"; + /** Format Type - XML X */ + public static final String FORMATTYPE_XML = "X"; + + /** + * Set Format Type + * @param newFormatType - F/C/T/X + */ + public void setFormatType(String newFormatType) + { + if (newFormatType.equals(FORMATTYPE_FIXED) || newFormatType.equals(FORMATTYPE_COMMA) + || newFormatType.equals(FORMATTYPE_TAB) || newFormatType.equals(FORMATTYPE_XML)) + m_formatType = newFormatType; + else + throw new IllegalArgumentException("FormatType must be F/C/T/X"); + } // setFormatType + + /** + * Set Format Type + * @return format type - F/C/T/X + */ + public String getFormatType() + { + return m_formatType; + } // getFormatType + + /** + * Set Business Partner + * @param newBPartner (value) + */ + public void setBPartner(String newBPartner) + { + m_BPartner = newBPartner; + } // setBPartner + + /** + * Get Business Partner + * @return BPartner (value) + */ + public String getBPartner() + { + return m_BPartner; + } // getVPartner + + /************************************************************************* + * Add Format Row + * @param row row + */ + public void addRow (ImpFormatRow row) + { + m_rows.add (row); + } // addRow + + /** + * Get Row + * @param index index + * @return Import Format Row + */ + public ImpFormatRow getRow (int index) + { + if (index >=0 && index < m_rows.size()) + return (ImpFormatRow)m_rows.get(index); + return null; + } // getRow + + /** + * Get Row Count + * @return row count + */ + public int getRowCount() + { + return m_rows.size(); + } // getRowCount + + /************************************************************************* + * Factory load + * @param name name + * @return Import Format + */ + public static ImpFormat load (String name) + { + log.config(name); + ImpFormat retValue = null; + String sql = "SELECT * FROM AD_ImpFormat WHERE Name=?"; + int ID = 0; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setString (1, name); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + retValue = new ImpFormat (name, rs.getInt("AD_Table_ID"), rs.getString("FormatType")); + ID = rs.getInt ("AD_ImpFormat_ID"); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + return null; + } + loadRows (retValue, ID); + return retValue; + } // getFormat + + /** + * Load Format Rows with ID + * @param format format + * @param ID id + */ + private static void loadRows (ImpFormat format, int ID) + { + String sql = "SELECT f.SeqNo,c.ColumnName,f.StartNo,f.EndNo,f.DataType,c.FieldLength," // 1..6 + + "f.DataFormat,f.DecimalPoint,f.DivideBy100,f.ConstantValue,f.Callout " // 7..11 + + "FROM AD_ImpFormat_Row f,AD_Column c " + + "WHERE f.AD_ImpFormat_ID=? AND f.AD_Column_ID=c.AD_Column_ID AND f.IsActive='Y'" + + "ORDER BY f.SeqNo"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt (1, ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + ImpFormatRow row = new ImpFormatRow (rs.getInt(1), + rs.getString(2), rs.getInt(3), rs.getInt(4), rs.getString(5), rs.getInt(6)); + // + row.setFormatInfo(rs.getString(7), rs.getString(8), + rs.getString(9).equals("Y"), + rs.getString(10), rs.getString(11)); + // + format.addRow (row); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + } // loadLines + + /************************************************************************* + * Parse Line returns ArrayList of values + * + * @param line line + * @param withLabel true if with label + * @param trace create trace info + * @param ignoreEmpty - ignore empty fields + * @return Array of values + */ + public String[] parseLine (String line, boolean withLabel, boolean trace, boolean ignoreEmpty) + { + if (trace) + log.config("" + line); + + ArrayList list = new ArrayList(); + // for all columns + for (int i = 0; i < m_rows.size(); i++) + { + ImpFormatRow row = (ImpFormatRow)m_rows.get(i); + StringBuffer entry = new StringBuffer (); + // Label-Start + if (withLabel) + { + entry.append(row.getColumnName()); + entry.append("="); + if (row.isString()) + entry.append("'"); + else if (row.isDate()) + entry.append("TO_DATE('"); + } + + // Get Data + String info = null; + if (row.isConstant()) + info = "Constant"; + else if (m_formatType.equals(FORMATTYPE_FIXED)) + { + // check length + if (row.getStartNo() > 0 && row.getEndNo() <= line.length()) + info = line.substring(row.getStartNo()-1, row.getEndNo()); + } + else + { + info = parseFlexFormat (line, m_formatType, row.getStartNo()); + } + + if (info == null) + info = ""; + + // Interpret Data + entry.append(row.parse(info)); + + // Label-End + if (withLabel) + { + if (row.isString()) + entry.append("'"); + else if (row.isDate()) + entry.append("','YYYY-MM-DD HH24:MI:SS')"); // JDBC Timestamp format w/o miliseconds + } + + if (!ignoreEmpty || (ignoreEmpty && info.length() != 0)) + list.add(entry.toString()); + // + if (trace) + log.fine(info + "=>" + entry.toString() + " (Length=" + info.length() + ")"); + } // for all columns + + String[] retValue = new String[list.size()]; + list.toArray(retValue); + return retValue; + } // parseLine + + /** + * Parse flexible line format. + * A bit inefficient as it always starts from the start + * + * @param line the line to be parsed + * @param formatType Comma or Tab + * @param fieldNo number of field to be returned + * @return field in lime or "" + @throws IllegalArgumentException if format unknows + * */ + private String parseFlexFormat (String line, String formatType, int fieldNo) + { + final char QUOTE = '"'; + // check input + char delimiter = ' '; + if (formatType.equals(FORMATTYPE_COMMA)) + delimiter = ','; + else if (formatType.equals(FORMATTYPE_TAB)) + delimiter = '\t'; + else + throw new IllegalArgumentException ("ImpFormat.parseFlexFormat - unknown format: " + formatType); + if (line == null || line.length() == 0 || fieldNo < 0) + return ""; + + // We need to read line sequentially as the fields may be delimited + // with quotes (") when fields contain the delimiter + // Example: "Artikel,bez","Artikel,""nr""",DEM,EUR + // needs to result in - Artikel,bez - Artikel,"nr" - DEM - EUR + int pos = 0; + int length = line.length(); + for (int field = 1; field <= fieldNo && pos < length; field++) + { + StringBuffer content = new StringBuffer(); + // two delimiter directly after each other + if (line.charAt(pos) == delimiter) + { + pos++; + continue; + } + // Handle quotes + if (line.charAt(pos) == QUOTE) + { + pos++; // move over beginning quote + while (pos < length) + { + // double quote + if (line.charAt(pos) == QUOTE && pos+1 < length && line.charAt(pos+1) == QUOTE) + { + content.append(line.charAt(pos++)); + pos++; + } + // end quote + else if (line.charAt(pos) == QUOTE) + { + pos++; + break; + } + // normal character + else + content.append(line.charAt(pos++)); + } + // we should be at end of line or a delimiter + if (pos < length && line.charAt(pos) != delimiter) + log.info("Did not find delimiter at pos " + pos + " " + line); + pos++; // move over delimiter + } + else // plain copy + { + while (pos < length && line.charAt(pos) != delimiter) + content.append(line.charAt(pos++)); + pos++; // move over delimiter + } + if (field == fieldNo) + return content.toString(); + } + + // nothing found + return ""; + } // parseFlexFormat + + /************************************************************************* + * Insert/Update Database. + * @param ctx context + * @param line line + * @param trxName transaction + * @return true if inserted/updated + */ + public boolean updateDB (Properties ctx, String line, String trxName) + { + if (line == null || line.trim().length() == 0) + { + log.finest("No Line"); + return false; + } + String[] nodes = parseLine (line, true, false, true); // with label, no trace, ignore empty + if (nodes.length == 0) + { + log.finest("Nothing parsed from: " + line); + return false; + } + // log.config( "ImpFormat.updateDB - listSize=" + nodes.length); + + // Standard Fields + int AD_Client_ID = Env.getAD_Client_ID(ctx); + int AD_Org_ID = Env.getAD_Org_ID(ctx); + if (getAD_Table_ID() == X_I_GLJournal.Table_ID) + AD_Org_ID = 0; + int UpdatedBy = Env.getAD_User_ID(ctx); + + + // Check if the record is already there ------------------------------ + StringBuffer sql = new StringBuffer ("SELECT COUNT(*), MAX(") + .append(m_tablePK).append(") FROM ").append(m_tableName) + .append(" WHERE AD_Client_ID=").append(AD_Client_ID).append(" AND ("); + // + String where1 = null; + String where2 = null; + String whereParentChild = null; + for (int i = 0; i < nodes.length; i++) + { + if (nodes[i].endsWith("=''") || nodes[i].endsWith("=0")) + ; + else if (nodes[i].startsWith(m_tableUnique1 + "=")) + where1 = nodes[i]; + else if (nodes[i].startsWith(m_tableUnique2 + "=")) + where2 = nodes[i]; + else if (nodes[i].startsWith(m_tableUniqueParent + "=") || nodes[i].startsWith(m_tableUniqueChild + "=")) + { + if (whereParentChild == null) + whereParentChild = nodes[i]; + else + whereParentChild += " AND " + nodes[i]; + } + } + StringBuffer find = new StringBuffer(); + if (where1 != null) + find.append(where1); + if (where2 != null) + { + if (find.length() > 0) + find.append(" OR "); + find.append(where2); + } + if (whereParentChild != null && whereParentChild.indexOf(" AND ") != -1) // need to have both criteria + { + if (find.length() > 0) + find.append(" OR (").append(whereParentChild).append(")"); // may have only one + else + find.append(whereParentChild); + } + sql.append(find).append(")"); + int count = 0; + int ID = 0; + try + { + if (find.length() > 0) + { + PreparedStatement pstmt = DB.prepareStatement(sql.toString(), trxName); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + count = rs.getInt(1); + if (count == 1) + ID = rs.getInt(2); + } + rs.close(); + pstmt.close(); + } + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql.toString(), e); + return false; + } + + + // Insert Basic Record ----------------------------------------------- + if (ID == 0) + { + ID = DB.getNextID(ctx, m_tableName, null); // get ID + sql = new StringBuffer("INSERT INTO ") + .append(m_tableName).append("(").append(m_tablePK).append(",") + .append("AD_Client_ID,AD_Org_ID,Created,CreatedBy,Updated,UpdatedBy,IsActive") // StdFields + .append(") VALUES (").append(ID).append(",") + .append(AD_Client_ID).append(",").append(AD_Org_ID) + .append(",SysDate,").append(UpdatedBy).append(",SysDate,").append(UpdatedBy).append(",'Y'") + .append(")"); + // + int no = DB.executeUpdate(sql.toString(), trxName); + if (no != 1) + { + log.log(Level.SEVERE, "Insert records=" + no + "; SQL=" + sql.toString()); + return false; + } + log.finer("New ID=" + ID + " " + find); + } + else + log.finer("Old ID=" + ID + " " + find); + + // Update Info ------------------------------------------------------- + sql = new StringBuffer ("UPDATE ") + .append(m_tableName).append(" SET "); + for (int i = 0; i < nodes.length; i++) + sql.append(nodes[i]).append(","); // column=value + sql.append("IsActive='Y',Processed='N',I_IsImported='N',Updated=SysDate,UpdatedBy=").append(UpdatedBy); + sql.append(" WHERE ").append(m_tablePK).append("=").append(ID); + // Update Cmd + int no = DB.executeUpdate(sql.toString(), trxName); + if (no != 1) + { + log.log(Level.SEVERE, m_tablePK + "=" + ID + " - rows updated=" + no); + return false; + } + return true; + } // updateDB + +} // ImpFormat diff --git a/base/src/org/compiere/impexp/ImpFormatRow.java b/base/src/org/compiere/impexp/ImpFormatRow.java new file mode 100644 index 0000000000..856a6cb262 --- /dev/null +++ b/base/src/org/compiere/impexp/ImpFormatRow.java @@ -0,0 +1,490 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.impexp; + +import java.math.*; +import java.sql.*; +import java.text.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Import Format Row with pasing capability + * + * @author Jorg Janke + * @version $Id: ImpFormatRow.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public final class ImpFormatRow +{ + /** + * Constructor for fixed format + * @param seqNo sequence + * @param columnName db dolumn name + * @param startNo start no + * @param endNo and no + * @param dataType data type - see constants DATATYPE_ + * @param maxLength if String it is the maximum length (truncated) + */ + public ImpFormatRow(int seqNo, String columnName, int startNo, int endNo, String dataType, int maxLength) + { + m_seqNo = seqNo; + setColumnName(columnName); + m_startNo = startNo; + m_endNo = endNo; + setDataType (dataType); + setMaxLength (maxLength); + } // ImpFormatRow + + /** + * Constructor for non-fixed format + * @param seqNo sequence + * @param columnName db column name + * @param dataType data type - see constants DATATYPE_ + * @param maxLength if String it is the maximum length (truncated) + */ + public ImpFormatRow(int seqNo, String columnName, String dataType, int maxLength) + { + m_seqNo = seqNo; + setColumnName(columnName); + setDataType (dataType); + setMaxLength (maxLength); + } // ImpFormatRow + + private int m_seqNo; + private String m_columnName; + private int m_startNo = 0; + private int m_endNo = 0; + private String m_dataType; + private String m_dataFormat = ""; + private String m_decimalPoint = "."; + private boolean m_divideBy100 = false; + private String m_constantValue = ""; + private boolean m_constantIsString = true; + // + private Callout m_callout = null; + private String m_method = null; + // + private SimpleDateFormat m_dformat = null; + private int m_maxLength = 0; + + /** Logger */ + private CLogger log = CLogger.getCLogger(getClass()); + + /** + * Sequence No + * @return seq no + */ + public int getSeqNo () + { + return m_seqNo; + } // getSeqNo + + /** + * Set Sequence No + * @param newSeqNo sequence + */ + public void setSeqNo (int newSeqNo) + { + m_seqNo = newSeqNo; + } // setSeqNo + + /** + * Start Position + * @param newStartNo start position + */ + public void setStartNo (int newStartNo) + { + m_startNo = newStartNo; + } // setStartNo + + /** + * Get Start Position + * @return start position + */ + public int getStartNo() + { + return m_startNo; + } // getStartNo + + /** + * End Position + * @param newEndNo end position + */ + public void setEndNo (int newEndNo) + { + m_endNo = newEndNo; + } // setEndNo + + /** + * Get End Position + * @return End Position + */ + public int getEndNo () + { + return m_endNo; + } // getEndNo + + /** + * Column + * @param columnName column name + */ + public void setColumnName (String columnName) + { + if (columnName == null || columnName.length() == 0) + throw new IllegalArgumentException("ColumnName must be at least 1 char"); + else + m_columnName = columnName; + } // setColumnName + + /** + * Get Column Name + * @return Column Name + */ + public String getColumnName() + { + return m_columnName; + } // getColumnName + + /** + * Data Type + * @param dataType data type - see constants DATATYPE_ + */ + public void setDataType (String dataType) + { + if (dataType.equals(DATATYPE_String) || dataType.equals(DATATYPE_Date) + || dataType.equals(DATATYPE_Number) || dataType.equals(DATATYPE_Constant)) + m_dataType = dataType; + else + throw new IllegalArgumentException("DataType must be S/D/N/C"); + } // setDataType + + /** String Data type */ + public static final String DATATYPE_String = "S"; + /** Data Data type */ + public static final String DATATYPE_Date = "D"; + /** Numeric Data type */ + public static final String DATATYPE_Number = "N"; + /** Constant Data type */ + public static final String DATATYPE_Constant = "C"; + + /** + * Data Type + * @return data type + */ + public String getDataType() + { + return m_dataType; + } // getDataType + + /** + * Is String + * @return true if data type is String + */ + public boolean isString() + { + if (m_dataType.equals(DATATYPE_Constant)) + return m_constantIsString; + return m_dataType.equals(DATATYPE_String); + } // isString + + /** + * Is Number + * @return true if data type is Number + */ + public boolean isNumber() + { + return m_dataType.equals(DATATYPE_Number); + } + + /** + * Is Date + * @return true if data type is Date + */ + public boolean isDate() + { + return m_dataType.equals(DATATYPE_Date); + } + + /** + * Is Constant + * @return true if data type is Constant + */ + public boolean isConstant() + { + return m_dataType.equals(DATATYPE_Constant); + } + + /** + * Set Format Info + * @param dataFormat data format - see constants DATATYPE_ + * @param decimalPoint decimal point representation + * @param divideBy100 divide number by 100 + * @param constantValue constant value + * @param callout Java callout + */ + public void setFormatInfo (String dataFormat, String decimalPoint, boolean divideBy100, + String constantValue, String callout) + { + if (dataFormat == null) + m_dataFormat = ""; + else + m_dataFormat = dataFormat; + // number + if (decimalPoint == null || !decimalPoint.equals(",")) + m_decimalPoint = "."; + else + m_decimalPoint = ","; + m_divideBy100 = divideBy100; + // constant + if (constantValue == null || constantValue.length() == 0 || !m_dataType.equals(DATATYPE_Constant)) + { + m_constantValue = ""; + m_constantIsString = true; + } + else + { + m_constantValue = constantValue; + m_constantIsString = false; + for (int i = 0; i < m_constantValue.length(); i++) + { + char c = m_constantValue.charAt(i); + if (!(Character.isDigit(c) || c == '.')) // if a constant number, it must be with . (not ,) + { + m_constantIsString = true; + break; + } + } + } + // callout + if (callout != null) + { + int methodStart = callout.lastIndexOf("."); + try + { + if (methodStart != -1) // no class + { + Class cClass = Class.forName(callout.substring(0,methodStart)); + m_callout = (Callout)cClass.newInstance(); + m_method = callout.substring(methodStart+1); + } + } + catch (Exception e) + { + log.log(Level.SEVERE, "MTab.setFormatInfo - " + e.toString()); + } + if (m_callout == null || m_method == null || m_method.length() == 0) + { + log.log(Level.SEVERE, "MTab.setFormatInfo - Invalid Callout " + callout); + m_callout = null; + } + } + } // setFormatInfo + + /** + * Get Format + * @return Data Format + */ + public String getDataFormat() + { + return m_dataFormat; + } + + /** + * Get Decimal Point + * @return Decimal Point + */ + public String getDecimalPoint() + { + return m_decimalPoint; + } + + /** + * Divide result by 100 + * @return true if result will be divided by 100 + */ + public boolean isDivideBy100() + { + return m_divideBy100; + } + + /** + * Get the constant value + * @return constant value + */ + public String getConstantValue() + { + return m_constantValue; + } + + /** + * Set maximum length for Strings (truncated). + * Ignored, if 0 + * @param maxLength max length + */ + public void setMaxLength (int maxLength) + { + m_maxLength = maxLength; + } // setMaxLength + + + /************************************************************************* + * Parse value. + * Field content in [] are treated as comments + * @param info data item + * @return pased info + */ + public String parse (String info) + { + if (info == null || info.length() == 0) + return ""; + + // Comment ? + if (info.startsWith("[") && info.endsWith("]")) + return ""; + // + String retValue = null; + if (isNumber()) + retValue = parseNumber (info); + else if (isDate()) + retValue = parseDate (info); + else if (isConstant()) + retValue = m_constantIsString ? parseString (m_constantValue) : m_constantValue; + else + retValue = parseString (info); + // + if (m_callout != null) + { + try + { + retValue = m_callout.convert (m_method, retValue); + } + catch (Exception e) + { + log.log(Level.SEVERE, "ImpFormatRow.parse - " + info + " (" + retValue + ")", e); + } + } + // + if (retValue == null) + retValue = ""; + return retValue.trim(); + } // parse + + + /** + * Return date as YYYY-MM-DD HH24:MI:SS (JDBC Timestamp format w/o miliseconds) + * @param info data + * @return date as JDBC format String + */ + private String parseDate (String info) + { + if (m_dformat == null) + { + try + { + m_dformat = new SimpleDateFormat(m_dataFormat); + } + catch (Exception e) + { + log.log(Level.SEVERE, "ImpFormatRow.parseDate Format=" + m_dataFormat, e); + } + if (m_dformat == null) + m_dformat = (SimpleDateFormat)DateFormat.getDateInstance(); + m_dformat.setLenient(true); + } + + Timestamp ts = null; + try + { + ts = new Timestamp (m_dformat.parse(info).getTime()); + } + catch (ParseException pe) + { + log.log(Level.SEVERE, "ImpFormatRow.parseDate - " + info, pe); + } + if (ts == null) + ts = new Timestamp (System.currentTimeMillis()); + // + String dateString = ts.toString(); + return dateString.substring(0, dateString.indexOf(".")); // cut off miliseconds + } // parseNumber + + /** + * Return String. + * - clean ' and backslash + * - check max length + * @param info data + * @return info with in SQL format + */ + private String parseString (String info) + { + String retValue = info; + // Length restriction + if (m_maxLength > 0 && retValue.length() > m_maxLength) + retValue = retValue.substring(0, m_maxLength); + + // copy characters (wee need to look through anyway) + StringBuffer out = new StringBuffer(retValue.length()); + for (int i = 0; i < retValue.length(); i++) + { + char c = retValue.charAt(i); + if (c == '\'') + out.append("''"); + else if (c == '\\') + out.append("\\\\"); + else + out.append(c); + } + return out.toString(); + } // parseString + + /** + * Return number with "." decimal + * @param info data + * @return converted number + */ + private String parseNumber (String info) + { + boolean hasPoint = info.indexOf(".") != -1; + boolean hasComma = info.indexOf(",") != -1; + // delete thousands + if (hasComma && m_decimalPoint.equals(".")) + info = info.replace(',', ' '); + if (hasPoint && m_decimalPoint.equals(",")) + info = info.replace('.', ' '); + hasComma = info.indexOf(",") != -1; + + // replace decimal + if (hasComma && m_decimalPoint.equals(",")) + info = info.replace(',', '.'); + + // remove everything but digits & '.' + char[] charArray = info.toCharArray(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < charArray.length; i++) + if (Character.isDigit(charArray[i]) || charArray[i] == '.') + sb.append(charArray[i]); + + if (sb.length() == 0) + return "0"; + BigDecimal bd = new BigDecimal(sb.toString()); + if (m_divideBy100) // assumed two decimal scale + bd = bd.divide(new BigDecimal(100.0), 2, BigDecimal.ROUND_HALF_UP); + return bd.toString(); + } // parseNumber + +} // ImpFormatFow diff --git a/base/src/org/compiere/impexp/MImpFormat.java b/base/src/org/compiere/impexp/MImpFormat.java new file mode 100644 index 0000000000..583acd73ba --- /dev/null +++ b/base/src/org/compiere/impexp/MImpFormat.java @@ -0,0 +1,98 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.impexp; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Import Format Model + * + * @author Jorg Janke + * @version $Id: MImpFormat.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MImpFormat extends X_AD_ImpFormat +{ + + /** + * Standard Constructor + * @param ctx context + * @param AD_ImpFormat_ID id + * @param trxName transaction + */ + public MImpFormat (Properties ctx, int AD_ImpFormat_ID, String trxName) + { + super (ctx, AD_ImpFormat_ID, trxName); + } // MImpFormat + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MImpFormat (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MImpFormat + + /** + * Get (all) Rows + * @return array of Rows + */ + public MImpFormatRow[] getRows() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM AD_ImpFormat_Row " + + "WHERE AD_ImpFormat_ID=? " + + "ORDER BY SeqNo"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getAD_ImpFormat_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MImpFormatRow (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getRows", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MImpFormatRow[] retValue = new MImpFormatRow[list.size ()]; + list.toArray (retValue); + return retValue; + } // getRows + +} // MImpFormat diff --git a/base/src/org/compiere/impexp/MImpFormatRow.java b/base/src/org/compiere/impexp/MImpFormatRow.java new file mode 100644 index 0000000000..216b406b51 --- /dev/null +++ b/base/src/org/compiere/impexp/MImpFormatRow.java @@ -0,0 +1,89 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.impexp; + +import java.sql.*; +import java.util.*; + +import org.compiere.model.*; + + +/** + * Import Format Row Model + * + * @author Jorg Janke + * @version $Id: MImpFormatRow.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MImpFormatRow extends X_AD_ImpFormat_Row +{ + + /** + * Standard Constructor + * @param ctx context + * @param AD_ImpFormat_Row_ID id + * @param trxName transaction + */ + public MImpFormatRow (Properties ctx, int AD_ImpFormat_Row_ID, String trxName) + { + super (ctx, AD_ImpFormat_Row_ID, trxName); + if (AD_ImpFormat_Row_ID == 0) + { + // setAD_ImpFormat_ID (0); Parent + // setAD_Column_ID (0); + // setDataType (null); + // setName (null); + // setSeqNo (10); + setDecimalPoint ("."); + setDivideBy100 (false); + } + } // MImpFormatRow + + /** + * Load Construcor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MImpFormatRow (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MImpFormatRow + + /** + * Parent Construcor + * @param format format parent + */ + public MImpFormatRow (MImpFormat format) + { + this (format.getCtx(), 0, format.get_TrxName()); + setAD_ImpFormat_ID(format.getAD_ImpFormat_ID()); + } // MImpFormatRow + + /** + * Parent/Copy Construcor + * @param parent format parent + * @param original to copy + */ + public MImpFormatRow (MImpFormat parent, MImpFormatRow original) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + copyValues(original, this); + setClientOrg(parent); + setAD_ImpFormat_ID(parent.getAD_ImpFormat_ID()); + } // MImpFormatRow + +} // MImpFormatRow diff --git a/base/src/org/compiere/impexp/OFX1ToXML.java b/base/src/org/compiere/impexp/OFX1ToXML.java new file mode 100644 index 0000000000..a541b01b42 --- /dev/null +++ b/base/src/org/compiere/impexp/OFX1ToXML.java @@ -0,0 +1,242 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.impexp; + +import java.io.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Covert OFX 1XX (SQGML) into valid XML + * + * SGML BASED OFX 1 compliant data is read from the BufferedReader + * passed to init. This class extends InputSream, allowing the + * XML compliant output data to be read from it. + * + * @author Maarten Klinker + * @version $Id: OFX1ToXML.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public final class OFX1ToXML extends InputStream implements Runnable +{ + /** Reader object */ + private PipedReader m_reader = new PipedReader(); + /** Writer object */ + private BufferedWriter m_writer; + /** Temp String */ + private String m_ofx = ""; + + /** Logger */ + private CLogger log = CLogger.getCLogger(getClass()); + + /** + * Constructor for OFX1ToXML + * @param is InputStream + * @throws IOException + */ + public OFX1ToXML(InputStream is) throws IOException + { + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + init(br); + } // OFX1ToXML + + /** + * Constructor for OFX1ToXML + * @param br BufferedReader + * @throws IOException + */ + public OFX1ToXML(BufferedReader br) throws IOException + { + init(br); + } // OFX1ToXML + + /** + * Method init + * @param br BufferedReader + * @throws IOException + */ + public void init(BufferedReader br) throws IOException + { + m_writer = new BufferedWriter(new PipedWriter(m_reader)); + String line = br.readLine(); + + write("\n"); + write(" 0) + { + write(line.replaceAll(":", "=\"") + "\" "); + } + line = br.readLine(); + } + write("?>\n"); + + while(line != null) + { + m_ofx += line + "\n"; + line = br.readLine(); + } + br.close(); + + new Thread(this).start(); + } //i nit + + /** + * Method run + * @see java.lang.Runnable#run() + */ + public void run() + { + boolean addCloseTag; + int tag2Start; + int tagStart; + int tagEnd; + String tag; + String line = ""; + + try + { + while(m_ofx != "") + { + addCloseTag = false; + tagStart = m_ofx.indexOf("<"); + if (tagStart == -1) + { + break; + } + tagEnd = m_ofx.indexOf(">"); + if (tagEnd <= tagStart + 1) + { + throw new IOException("PARSE ERROR: Invalid tag"); + } + tag = m_ofx.substring(tagStart + 1, tagEnd); + if (tag.indexOf(" ") != -1) + { + throw new IOException("PARSE ERROR: Invalid tag"); + } + if (!tag.startsWith("/")) + { + addCloseTag = (m_ofx.indexOf("") == -1); + } + tag2Start = m_ofx.indexOf("<", tagEnd); + if (m_ofx.indexOf("\n", tagEnd) < tag2Start) + { + tag2Start = m_ofx.indexOf("\n", tagEnd); + } + if (tag2Start == -1) + { + tag2Start = m_ofx.length(); + } + + String data=m_ofx.substring(tagEnd+1, tag2Start); + line = m_ofx.substring(0, tagEnd+1)+xmlEncodeTextAsPCDATA(data); + + m_ofx = m_ofx.substring(tag2Start); + if (addCloseTag) + { + line += ""; + } + write(line); + } + write(m_ofx); + m_writer.close(); + } + catch (IOException e) + { + log.log(Level.SEVERE, "Ofx1To2Convertor: IO Exception", e); + } + } // run + + /** + * Method write + * @param str String + * @throws IOException + */ + private void write(String str) throws IOException + { + m_writer.write(str, 0, str.length()); + } // write + + /** + * Method read + * @return int + * @throws IOException + */ + public int read() throws IOException + { + return m_reader.read(); + } // read + + /** + * Method read + * @param cbuf char[] + * @param off int + * @param len int + * @return int + * @throws IOException + */ + public int read(char[] cbuf, int off, int len) throws IOException + { + return m_reader.read(cbuf, off, len); + } // read + + + + + /** + * Encodes strings for XML + * @param text text + * @return string + */ + public final static String xmlEncodeTextAsPCDATA(String text) + { + if (text == null) + return null; + char c; + StringBuffer n = new StringBuffer (text.length () * 2); + for (int i = 0; i < text.length (); i++) + { + c = text.charAt (i); + switch (c) + { + case '&': + n.append ("&"); + break; + case '<': + n.append ("<"); + break; + case '>': + n.append (">"); + break; + case '"': + n.append ("""); + break; + case '\'': + n.append ("'"); + break; + default: + { + n.append (c); + break; + } + } + } + return n.toString (); + } // xmlEncodeTextAsPCDATA + + +} //Ofx1To2Convertor diff --git a/base/src/org/compiere/impexp/OFXBankStatementHandler.java b/base/src/org/compiere/impexp/OFXBankStatementHandler.java new file mode 100644 index 0000000000..2f48c3118f --- /dev/null +++ b/base/src/org/compiere/impexp/OFXBankStatementHandler.java @@ -0,0 +1,817 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.impexp; + +import org.compiere.model.*; +import org.compiere.util.Env; + +import java.io.*; +import java.math.BigDecimal; + +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.text.ParseException; + +import javax.xml.parsers.*; +import org.xml.sax.*; +import org.xml.sax.helpers.*; + + +/** + * Parser for OFX bank statements + * + * This class is a parser for OFX bankstatements. OFX versions from 102 to 202 + * and MS-Money OFC message sets are supported. + * Only fully XML compliant OFX data is supported. Files that are not XML + * compliant, e.g. OFX versions older then 200, will be preprocessed by + * the OFX1ToXML class before parsing. + * This class should be extended by a class that obtains the data to be parsed + * for example from a file, or using HTTP. + * + * @author Eldir Tomassen + * @version $Id: OFXBankStatementHandler.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ + +public abstract class OFXBankStatementHandler extends DefaultHandler +{ + + protected MBankStatementLoader m_controller; + protected String m_errorMessage = ""; + protected String m_errorDescription = ""; + protected BufferedReader m_reader = null; + + protected SAXParser m_parser; + protected boolean m_success = false; + //private boolean m_valid = false; + + protected StatementLine m_line; + protected String m_routingNo = "0"; + protected String m_bankAccountNo = null; + protected String m_currency = null; + protected int HEADER_SIZE = 20; + + protected boolean m_test = false; + protected Timestamp m_dateLastRun = null; + protected Timestamp m_statementDate = null; + + StringBuffer m_valueBuffer = new StringBuffer(); + + + + /** XML OFX Tag */ + public static final String XML_OFX_TAG = "OFX"; + + /** XML SIGNONMSGSRSV2 Tag */ + public static final String XML_SIGNONMSGSRSV2_TAG = "SIGNONMSGSRSV2"; + /** XML SIGNONMSGSRSV1 Tag */ + public static final String XML_SIGNONMSGSRSV1_TAG = "SIGNONMSGSRSV1"; + + /** Record-response aggregate */ + public static final String XML_SONRS_TAG = "SONRS"; + /** Date and time of the server response */ + public static final String XML_DTSERVER_TAG = "DTSERVER"; + /** Use USERKEY instead of USERID and USEPASS */ + public static final String XML_USERKEY_TAG = "USERKEY"; + /** Date and time that USERKEY expires */ + public static final String XML_TSKEYEXPIRE_TAG = "TSKEYEXPIRE"; + /** Language */ + public static final String XML_LANGUAGE_TAG = "LANGUAGE"; + /** Date and rime last update to profile information*/ + public static final String XML_DTPROFUP_TAG = "DTPROFUP"; + + /** Status aggregate */ + public static final String XML_STATUS_TAG = "STATUS"; + + + /** Statement-response aggregate */ + public static final String XML_STMTRS_TAG = "STMTRS"; + /** XML CURDEF Tag */ + public static final String XML_CURDEF_TAG = "CURDEF"; + + /** Account-from aggregate */ + public static final String XML_BANKACCTFROM_TAG = "BANKACCTFROM"; + /** Bank identifier */ + public static final String XML_BANKID_TAG = "BANKID"; + /** Branch identifier */ + public static final String XML_BRANCHID_TAG = "BRANCHID"; + /** XML ACCTID Tag */ + public static final String XML_ACCTID_TAG = "ACCTID"; + /** Type of account */ + public static final String XML_ACCTTYPE_TAG = "ACCTTYPE"; + /** Type of account */ + public static final String XML_ACCTTYPE2_TAG = "ACCTTYPE2"; + /** Checksum */ + public static final String XML_ACCTKEY_TAG = "ACCTKEY"; + + /** XML BANKTRANLIST Tag */ + public static final String XML_BANKTRANLIST_TAG = "BANKTRANLIST"; + /** XML DTSTART Tag */ + public static final String XML_DTSTART_TAG = "DTSTART"; + /** XML DTEND Tag */ + public static final String XML_DTEND_TAG = "DTEND"; + /** XML STMTTRN Tag */ + public static final String XML_STMTTRN_TAG = "STMTTRN"; + /** XML TRNTYPE Tag */ + public static final String XML_TRNTYPE_TAG = "TRNTYPE"; + /** XML TRNAMT Tag */ + public static final String XML_TRNAMT_TAG = "TRNAMT"; + /** Transaction date */ + public static final String XML_DTPOSTED_TAG = "DTPOSTED"; + /** Effective date */ + public static final String XML_DTAVAIL_TAG = "DTAVAIL"; + /** XML FITID Tag */ + public static final String XML_FITID_TAG = "FITID"; + /** XML CHECKNUM Tag */ + public static final String XML_CHECKNUM_TAG = "CHECKNUM"; + /** XML CHKNUM Tag (MS-Money OFC) */ + public static final String XML_CHKNUM_TAG = "CHKNUM"; + /** XML REFNUM Tag */ + public static final String XML_REFNUM_TAG = "REFNUM"; + /** Transaction Memo */ + public static final String XML_MEMO_TAG = "MEMO"; + /** XML NAME Tag */ + public static final String XML_NAME_TAG = "NAME"; + /** XML PAYEEID Tag */ + public static final String XML_PAYEEID_TAG = "PAYEEID"; + /** TXML PAYEE Tag */ + public static final String XML_PAYEE_TAG = "PAYEE"; + + /** XML LEDGERBAL Tag */ + public static final String XML_LEDGERBAL_TAG = "LEDGERBAL"; + /** XML BALAMT Tag */ + public static final String XML_BALAMT_TAG = "BALAMT"; + /** XML DTASOF Tag */ + public static final String XML_DTASOF_TAG = "DTASOF"; + /** XML AVAILBAL Tag */ + public static final String XML_AVAILBAL_TAG = "AVAILBAL"; + /** XML MKTGINFO Tag */ + public static final String XML_MKTGINFO_TAG = "MKTGINFO"; + + /** + * Initialize the loader + * * @param controller Reference to the BankStatementLoaderController + @return Initialized succesfully + */ + protected boolean init(MBankStatementLoader controller) + { + boolean result = false; + if (controller == null) + { + m_errorMessage = "ErrorInitializingParser"; + m_errorDescription = "ImportController is a null reference"; + return result; + } + this.m_controller = controller; + try + { + SAXParserFactory factory = SAXParserFactory.newInstance(); + m_parser = factory.newSAXParser(); + result = true; + } + catch(ParserConfigurationException e) + { + m_errorMessage = "ErrorInitializingParser"; + m_errorDescription = "Unable to configure SAX parser: " + e.getMessage(); + } + catch(SAXException e) + { + m_errorMessage = "ErrorInitializingParser"; + m_errorDescription = "Unable to initialize SAX parser: " + e.getMessage(); + } + return result; + } // init + + /** + * Attach OFX input source, detect whether we are dealing with OFX1 + * (SGML) or OFX2 (XML). In case of OFX1, process the data to create + * valid XML. + * @param is Reference to the BankStatementLoaderController + * @return true if input is valid OFX data + */ + protected boolean attachInput(InputStream is) + { + boolean isOfx1 = true; + boolean result = false; + + try + { + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + reader.mark(HEADER_SIZE + 100); + String header = ""; + for (int i = 0; i < HEADER_SIZE; i++) + { + header = header + reader.readLine(); + } + if ((header.indexOf(") + * is detected. + * @param uri String + * @param localName String + * @param qName String + * @throws SAXException + * @see org.xml.sax.ContentHandler#endElement(String, String, String) + */ + public void endElement (String uri, String localName, String qName) throws SAXException + { + + String XML_TAG=qName; + String value=m_valueBuffer.toString(); + + try + { + //Read statment level data + + /* + * Default currency for this set of statement lines + * --- + */ + if (XML_TAG.equals(XML_CURDEF_TAG)) + { + m_currency = value; + } + + /* Routing Number (or SWIFT Code) for this set of statement lines + * ---- + */ + else if (XML_TAG.equals(XML_BANKID_TAG)) + { + m_routingNo = value; + } + + /* + * Bank Account Number for this set of bank statement lines + * ---- + */ + else if (XML_TAG.equals(XML_ACCTID_TAG)) + { + m_bankAccountNo = value; + } + + /* + * Last date for this set of statement lines + * This is the date that should be specified as the + * for the next batch of statement lines, in order not to miss any + * transactions. + * ---- + */ + else if (XML_TAG.equals(XML_DTEND_TAG)) + { + m_dateLastRun = parseOfxDate(value); + } + + /* + * + * ---- + */ + else if (XML_TAG.equals(XML_DTASOF_TAG)) + { + m_statementDate = parseOfxDate(value); + } + + + //Read statement line level data + + /* + * Transaction type, e.g. DEBIT, CREDIT, SRVCHG + * ---- + */ + else if (XML_TAG.equals(XML_TRNTYPE_TAG)) + { + m_line.trxType = value; + } + + /* + * Statement line date + * ---- + */ + else if (XML_TAG.equals(XML_DTPOSTED_TAG)) + { + m_line.statementLineDate = parseOfxDate(value); + } + + /* + * Valuta date + * ---- + */ + else if (XML_TAG.equals(XML_DTAVAIL_TAG)) + { + m_line.valutaDate = parseOfxDate(value); + } + + /* + * Total statement line amount + * ---- + */ + else if (XML_TAG.equals(XML_TRNAMT_TAG)) + { + m_line.stmtAmt = new BigDecimal(value); + } + + /* + * Transaction Identification + * ---- + */ + else if (XML_TAG.equals(XML_FITID_TAG)) + { + m_line.trxID = value; + } + + /* + * Check number for check transactions + * CHECKNUM for generic OFX, CHKNUM for MS-Money OFC + * ---- + */ + else if ((XML_TAG.equals(XML_CHECKNUM_TAG)) || (XML_TAG.equals(XML_CHKNUM_TAG))) + { + m_line.checkNo = value; + } + + /* + * Statement line reference + * Additional transaction reference information + * ---- + */ + else if (XML_TAG.equals(XML_REFNUM_TAG)) + { + m_line.reference = value; + } + + /* + * Transaction memo + * ---- + */ + else if (XML_TAG.equals(XML_MEMO_TAG)) + { + m_line.memo = value; + } + + /* + * Payee Name + * ---- + */ + else if (XML_TAG.equals(XML_NAME_TAG)) + { + m_line.payeeName = value; + } + } + catch(Exception e) + { + + m_errorDescription = "Invalid data: " + value + " <-> " + e.getMessage(); + throw new SAXException("Invalid data: " + value); + } + + if (qName.equals(XML_STMTTRN_TAG)) + { + if (!m_test) + { + if (!m_controller.saveLine()) + { + m_errorMessage = m_controller.getErrorMessage(); + m_errorDescription = m_controller.getErrorDescription(); + throw new SAXException(m_errorMessage); + } + } + } + } // endElement + + + /** + * Method parseOfxDate + * @param value String + * @return Timestamp + * @throws ParseException + */ + private Timestamp parseOfxDate(String value) throws ParseException + { + try + { + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); + sdf.setLenient(false); + return new Timestamp (sdf.parse(value).getTime()); + } + catch(Exception e) + { + throw new ParseException("Error parsing date: " + value, 0); + } + } //parseOfxDate + + /** + * Method getLastErrorMessage + * @return String + */ + public String getLastErrorMessage() + { + return m_errorMessage; + } + + /** + * Method getLastErrorDescription + * @return String + */ + public String getLastErrorDescription() + { + return m_errorDescription; + } + + /** + * @author ET + * @version $Id: OFXBankStatementHandler.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ + class StatementLine + { + protected String routingNo = null; + protected String bankAccountNo = null; + protected String statementReference = null; + + + protected Timestamp statementLineDate = null; + protected String reference = null; + protected Timestamp valutaDate; + protected String trxType = null; + protected boolean isReversal = false; + protected String currency = null; + protected BigDecimal stmtAmt = null; + protected String memo = null; + protected String chargeName = null; + protected BigDecimal chargeAmt = null; + protected String payeeAccountNo = null; + protected String payeeName = null; + protected String trxID = null; + protected String checkNo = null; + + + /** + * Constructor for StatementLine + * @param RoutingNo String + * @param BankAccountNo String + * @param Currency String + */ + public StatementLine(String RoutingNo, String BankAccountNo, String Currency) + { + bankAccountNo = BankAccountNo; + routingNo = RoutingNo; + currency = Currency; + } + + } + +} //OFXBankStatementHandler diff --git a/base/src/org/compiere/impexp/OFXFileBankStatementLoader.java b/base/src/org/compiere/impexp/OFXFileBankStatementLoader.java new file mode 100644 index 0000000000..a3d29c5b5e --- /dev/null +++ b/base/src/org/compiere/impexp/OFXFileBankStatementLoader.java @@ -0,0 +1,100 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.impexp; + +import org.compiere.model.*; + +import java.io.*; + +import org.xml.sax.SAXException; + +/** + * Loader for OFX bank statements (file based) + * + * @author Eldir Tomassen + * @version $Id: + */ + +public final class OFXFileBankStatementLoader extends OFXBankStatementHandler implements BankStatementLoaderInterface +{ + + /** + * Method init + * @param controller MBankStatementLoader + * @return boolean + * @see org.compiere.impexp.BankStatementLoaderInterface#init(MBankStatementLoader) + */ + public boolean init(MBankStatementLoader controller) + { + boolean result = false; + FileInputStream m_stream = null; + try + { + // Try to open the file specified as a process parameter + if (controller.getLocalFileName() != null) + { + m_stream = new FileInputStream(controller.getLocalFileName()); + } + // Try to open the file specified as part of the loader configuration + else if (controller.getFileName() != null) + { + m_stream = new FileInputStream(controller.getFileName()); + } + else + { + return result; + } + if (!super.init(controller)) + { + return result; + } + if (m_stream == null) + { + return result; + } + result = attachInput(m_stream); + } + catch(Exception e) + { + m_errorMessage = "ErrorReadingData"; + m_errorDescription = ""; + } + + return result; + } // init + + + /** + * Method characters + * @param ch char[] + * @param start int + * @param length int + * @throws SAXException + * @see org.xml.sax.ContentHandler#characters(char[], int, int) + */ + public void characters (char ch[], int start, int length) + throws SAXException + { + /* + * There are no additional things to do when importing from file. + * All data is handled by OFXBankStatementHandler + */ + super.characters(ch, start, length); + } // characterS + + +} // OFXFileBankStatementLoader diff --git a/base/src/org/compiere/impexp/package.html b/base/src/org/compiere/impexp/package.html new file mode 100644 index 0000000000..eaceadcaad --- /dev/null +++ b/base/src/org/compiere/impexp/package.html @@ -0,0 +1,34 @@ + + + + + + + +Provides for.... + +

Package Specification

+ + + +

Related Documentation

+ +For overviews, tutorials, examples, guides, and tool documentation, please see: + + + + + + diff --git a/base/src/org/compiere/model/AdempiereProcessor.java b/base/src/org/compiere/model/AdempiereProcessor.java new file mode 100644 index 0000000000..aeacea8a08 --- /dev/null +++ b/base/src/org/compiere/model/AdempiereProcessor.java @@ -0,0 +1,111 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Processor Interface + * + * @author Jorg Janke + * @version $Id: AdempiereProcessor.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public interface AdempiereProcessor +{ + /** + * Get Client + * @return AD_Client_ID + */ + public int getAD_Client_ID(); + + /** + * Get Name + * @return Name + */ + public String getName(); + + /** + * Get Description + * @return Description + */ + public String getDescription(); + + /** + * Get Context + * @return context + */ + public Properties getCtx(); + + /** + * Get the frequency type + * @return frequency type + */ + public String getFrequencyType(); + + /** + * Get the frequency + * @return frequency + */ + public int getFrequency(); + + + /** + * Get Unique ID + * @return Unique ID + */ + public String getServerID(); + + /** + * Get the date Next run + * @param requery requery database + * @return date next run + */ + public Timestamp getDateNextRun (boolean requery); + + /** + * Set Date Next Run + * @param dateNextWork next work + */ + public void setDateNextRun(Timestamp dateNextWork); + + /** + * Get the date Last run + * @return date lext run + */ + public Timestamp getDateLastRun (); + + /** + * Set Date Last Run + * @param dateLastRun last run + */ + public void setDateLastRun(Timestamp dateLastRun); + + /** + * Save + * @return true if saved + */ + public boolean save(); + + + /** + * Get Processor Logs + * @return logs + */ + public AdempiereProcessorLog[] getLogs(); + +} // AdempiereProcessor diff --git a/base/src/org/compiere/model/AdempiereProcessorLog.java b/base/src/org/compiere/model/AdempiereProcessorLog.java new file mode 100644 index 0000000000..8338d92d96 --- /dev/null +++ b/base/src/org/compiere/model/AdempiereProcessorLog.java @@ -0,0 +1,65 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; + +/** + * Processor Log Interface + * + * @author Jorg Janke + * @version $Id: AdempiereProcessorLog.java,v 1.3 2006/07/30 00:51:04 jjanke Exp $ + */ +public interface AdempiereProcessorLog +{ + /** + * Get Created Date + * @return created + */ + public Timestamp getCreated(); + + /** + * Get Summary. Textual summary of this request + * @return Summary + */ + public String getSummary (); + + /** + * Get Description. Optional short description of the record + * @return description + */ + public String getDescription (); + + /** + * Get Error. An Error occured in the execution + * @return true if error + */ + public boolean isError (); + + /** + * Get Reference. Reference for this record + * @return reference + */ + public String getReference (); + + /** + * Get Text Message. Text Message + * @return text message + */ + public String getTextMsg (); + +} // AdempiereProcessorLog diff --git a/base/src/org/compiere/model/Callout.java b/base/src/org/compiere/model/Callout.java new file mode 100644 index 0000000000..52051e30f0 --- /dev/null +++ b/base/src/org/compiere/model/Callout.java @@ -0,0 +1,60 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.util.*; + +/** + * Callout Interface for Callout. + * Used in MTab and ImpFormatRow + * + * @author Jorg Janke + * @version $Id: Callout.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public interface Callout +{ + /** + * Start Callout. + *

+ * Callout's are used for cross field validation and setting values in other fields + * when returning a non empty (error message) string, an exception is raised + *

+ * When invoked, the Tab model has the new value! + * + * @param ctx Context + * @param method Method name + * @param WindowNo current Window No + * @param mTab Model Tab + * @param mField Model Field + * @param value The new value + * @param oldValue The old value + * @return Error message or "" + */ + public String start (Properties ctx, String method, int WindowNo, + GridTab mTab, GridField mField, Object value, Object oldValue); + + /** + * Conversion Rules. + * Convert a String + * + * @param method in notation User_Function + * @param value the value + * @return converted String or Null if no method found + */ + public String convert (String method, String value); + +} // callout diff --git a/base/src/org/compiere/model/CalloutAssignment.java b/base/src/org/compiere/model/CalloutAssignment.java new file mode 100644 index 0000000000..dbc313ae57 --- /dev/null +++ b/base/src/org/compiere/model/CalloutAssignment.java @@ -0,0 +1,106 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Resource Assignment Callout + * + * @author Jorg Janke + * @version $Id: CalloutAssignment.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class CalloutAssignment extends CalloutEngine +{ + + /** + * Assignment_Product. + * - called from S_ResourceAssignment_ID + * - sets M_Product_ID, Description + * - Qty.. + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String product (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive() || value == null) + return ""; + // get value + int S_ResourceAssignment_ID = ((Integer)value).intValue(); + if (S_ResourceAssignment_ID == 0) + return ""; + setCalloutActive(true); + + int M_Product_ID = 0; + String Name = null; + String Description = null; + BigDecimal Qty = null; + String sql = "SELECT p.M_Product_ID, ra.Name, ra.Description, ra.Qty " + + "FROM S_ResourceAssignment ra" + + " INNER JOIN M_Product p ON (p.S_Resource_ID=ra.S_Resource_ID) " + + "WHERE ra.S_ResourceAssignment_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, S_ResourceAssignment_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + M_Product_ID = rs.getInt (1); + Name = rs.getString(2); + Description = rs.getString(3); + Qty = rs.getBigDecimal(4); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "product", e); + } + + log.fine("S_ResourceAssignment_ID=" + S_ResourceAssignment_ID + " - M_Product_ID=" + M_Product_ID); + if (M_Product_ID != 0) + { + mTab.setValue ("M_Product_ID", new Integer (M_Product_ID)); + if (Description != null) + Name += " (" + Description + ")"; + if (!".".equals(Name)) + mTab.setValue("Description", Name); + // + String variable = "Qty"; // TimeExpenseLine + if (mTab.getTableName().startsWith("C_Order")) + variable = "QtyOrdered"; + else if (mTab.getTableName().startsWith("C_Invoice")) + variable = "QtyInvoiced"; + if (Qty != null) + mTab.setValue(variable, Qty); + } + setCalloutActive(false); + return ""; + } // product + +} // CalloutAssignment diff --git a/base/src/org/compiere/model/CalloutBankStatement.java b/base/src/org/compiere/model/CalloutBankStatement.java new file mode 100644 index 0000000000..05c72891fd --- /dev/null +++ b/base/src/org/compiere/model/CalloutBankStatement.java @@ -0,0 +1,151 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Bank Statement Callout + * + * @author Jorg Janke + * @version $Id: CalloutBankStatement.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class CalloutBankStatement extends CalloutEngine +{ + /** + * Bank Account Changed. + * Update Beginning Balance + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String bankAccount (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (value == null) + return ""; + int C_BankAccount_ID = ((Integer)value).intValue(); + MBankAccount ba = MBankAccount.get(ctx, C_BankAccount_ID); + mTab.setValue("BeginningBalance", ba.getCurrentBalance()); + return ""; + } // bankAccount + + /** + * BankStmt - Amount. + * Calculate ChargeAmt = StmtAmt - TrxAmt - InterestAmt + * or id Charge is entered - InterestAmt = StmtAmt - TrxAmt - ChargeAmt + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String amount (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive()) + return ""; + setCalloutActive(true); + + // Get Stmt & Trx + BigDecimal stmt = (BigDecimal)mTab.getValue("StmtAmt"); + if (stmt == null) + stmt = Env.ZERO; + BigDecimal trx = (BigDecimal)mTab.getValue("TrxAmt"); + if (trx == null) + trx = Env.ZERO; + BigDecimal bd = stmt.subtract(trx); + + // Charge - calculate Interest + if (mField.getColumnName().equals("ChargeAmt")) + { + BigDecimal charge = (BigDecimal)value; + if (charge == null) + charge = Env.ZERO; + bd = bd.subtract(charge); + // log.trace(log.l5_DData, "Interest (" + bd + ") = Stmt(" + stmt + ") - Trx(" + trx + ") - Charge(" + charge + ")"); + mTab.setValue("InterestAmt", bd); + } + // Calculate Charge + else + { + BigDecimal interest = (BigDecimal)mTab.getValue("InterestAmt"); + if (interest == null) + interest = Env.ZERO; + bd = bd.subtract(interest); + // log.trace(log.l5_DData, "Charge (" + bd + ") = Stmt(" + stmt + ") - Trx(" + trx + ") - Interest(" + interest + ")"); + mTab.setValue("ChargeAmt", bd); + } + setCalloutActive(false); + return ""; + } // amount + + + /** + * BankStmt - Payment. + * Update Transaction Amount when payment is selected + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String payment (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_Payment_ID = (Integer)value; + if (C_Payment_ID == null || C_Payment_ID.intValue() == 0) + return ""; + // + BigDecimal stmt = (BigDecimal)mTab.getValue("StmtAmt"); + if (stmt == null) + stmt = Env.ZERO; + + String sql = "SELECT PayAmt FROM C_Payment_v WHERE C_Payment_ID=?"; // 1 + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_Payment_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + BigDecimal bd = rs.getBigDecimal(1); + mTab.setValue("TrxAmt", bd); + if (stmt.compareTo(Env.ZERO) == 0) + mTab.setValue("StmtAmt", bd); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "BankStmt_Payment", e); + return e.getLocalizedMessage(); + } + // Recalculate Amounts + amount (ctx, WindowNo, mTab, mField, value); + return ""; + } // payment + +} // CalloutBankStatement diff --git a/base/src/org/compiere/model/CalloutCashJournal.java b/base/src/org/compiere/model/CalloutCashJournal.java new file mode 100644 index 0000000000..892674ecc3 --- /dev/null +++ b/base/src/org/compiere/model/CalloutCashJournal.java @@ -0,0 +1,150 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Cash Book Journal Callouts + * + * @author Jorg Janke + * @version $Id: CalloutCashJournal.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class CalloutCashJournal extends CalloutEngine +{ + /** + * Cash Journal Line Invoice. + * when Invoice selected + * - set C_Currency, DiscountAnt, Amount, WriteOffAmt + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String invoice (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive()) // assuming it is resetting value + return ""; + setCalloutActive(true); + + Integer C_Invoice_ID = (Integer)value; + if (C_Invoice_ID == null || C_Invoice_ID.intValue() == 0) + { + mTab.setValue("C_Currency_ID", null); + setCalloutActive(false); + return ""; + } + + // Date + Timestamp ts = Env.getContextAsDate(ctx, WindowNo, "DateAcct"); // from C_Cash + if (ts == null) + ts = new Timestamp(System.currentTimeMillis()); + // + String sql = "SELECT C_BPartner_ID, C_Currency_ID," // 1..2 + + "invoiceOpen(C_Invoice_ID, 0), IsSOTrx, " // 3..4 + + "paymentTermDiscount(invoiceOpen(C_Invoice_ID, 0),C_Currency_ID,C_PaymentTerm_ID,DateInvoiced,?) " + + "FROM C_Invoice WHERE C_Invoice_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setTimestamp(1, ts); + pstmt.setInt(2, C_Invoice_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + mTab.setValue("C_Currency_ID", new Integer(rs.getInt(2))); + BigDecimal PayAmt = rs.getBigDecimal(3); + BigDecimal DiscountAmt = rs.getBigDecimal(5); + boolean isSOTrx = "Y".equals(rs.getString(4)); + if (!isSOTrx) + { + PayAmt = PayAmt.negate(); + DiscountAmt = DiscountAmt.negate(); + } + // + mTab.setValue("Amount", PayAmt.subtract(DiscountAmt)); + mTab.setValue("DiscountAmt", DiscountAmt); + mTab.setValue("WriteOffAmt", Env.ZERO); + Env.setContext(ctx, WindowNo, "InvTotalAmt", PayAmt.toString()); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "invoice", e); + setCalloutActive(false); + return e.getLocalizedMessage(); + } + setCalloutActive(false); + return ""; + } // CashJournal_Invoice + + + /** + * Cash Journal Line Invoice Amounts. + * when DiscountAnt, Amount, WriteOffAmt change + * making sure that add up to InvTotalAmt (created by CashJournal_Invoice) + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String amounts (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + // Needs to be Invoice + if (isCalloutActive() || !"I".equals(mTab.getValue("CashType"))) + return ""; + // Check, if InvTotalAmt exists + String total = Env.getContext(ctx, WindowNo, "InvTotalAmt"); + if (total == null || total.length() == 0) + return ""; + BigDecimal InvTotalAmt = new BigDecimal(total); + setCalloutActive(true); + + BigDecimal PayAmt = (BigDecimal)mTab.getValue("Amount"); + BigDecimal DiscountAmt = (BigDecimal)mTab.getValue("DiscountAmt"); + BigDecimal WriteOffAmt = (BigDecimal)mTab.getValue("WriteOffAmt"); + String colName = mField.getColumnName(); + log.fine(colName + " - Invoice=" + InvTotalAmt + + " - Amount=" + PayAmt + ", Discount=" + DiscountAmt + ", WriteOff=" + WriteOffAmt); + + // Amount - calculate write off + if (colName.equals("Amount")) + { + WriteOffAmt = InvTotalAmt.subtract(PayAmt).subtract(DiscountAmt); + mTab.setValue("WriteOffAmt", WriteOffAmt); + } + else // calculate PayAmt + { + PayAmt = InvTotalAmt.subtract(DiscountAmt).subtract(WriteOffAmt); + mTab.setValue("Amount", PayAmt); + } + + setCalloutActive(false); + return ""; + } // amounts + +} // CalloutCashJournal diff --git a/base/src/org/compiere/model/CalloutEngine.java b/base/src/org/compiere/model/CalloutEngine.java new file mode 100644 index 0000000000..c8828a5e85 --- /dev/null +++ b/base/src/org/compiere/model/CalloutEngine.java @@ -0,0 +1,242 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.lang.reflect.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Callout Emgine. + * + * @author Jorg Janke + * @version $Id: CalloutEngine.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class CalloutEngine implements Callout +{ + /** + * Constructor + */ + public CalloutEngine() + { + super(); + } + + /** Logger */ + protected CLogger log = CLogger.getCLogger(getClass()); + + /** + * Start Callout. + *

+ * Callout's are used for cross field validation and setting values in other fields + * when returning a non empty (error message) string, an exception is raised + *

+ * When invoked, the Tab model has the new value! + * + * @param ctx Context + * @param methodName Method name + * @param WindowNo current Window No + * @param mTab Model Tab + * @param mField Model Field + * @param value The new value + * @param oldValue The old value + * @return Error message or "" + */ + public String start (Properties ctx, String methodName, int WindowNo, + GridTab mTab, GridField mField, Object value, Object oldValue) + { + if (methodName == null || methodName.length() == 0) + throw new IllegalArgumentException ("No Method Name"); + // + String retValue = ""; + StringBuffer msg = new StringBuffer(methodName).append(" - ") + .append(mField.getColumnName()) + .append("=").append(value) + .append(" (old=").append(oldValue) + .append(") {active=").append(isCalloutActive()).append("}"); + if (!isCalloutActive()) + log.info (msg.toString()); + + // Find Method + Method method = getMethod(methodName); + if (method == null) + throw new IllegalArgumentException ("Method not found: " + methodName); + int argLength = method.getParameterTypes().length; + if (!(argLength == 5 || argLength == 6)) + throw new IllegalArgumentException ("Method " + methodName + + " has invalid no of arguments: " + argLength); + + // Call Method + try + { + Object[] args = null; + if (argLength == 6) + args = new Object[] {ctx, new Integer(WindowNo), mTab, mField, value, oldValue}; + else + args = new Object[] {ctx, new Integer(WindowNo), mTab, mField, value}; + retValue = (String)method.invoke(this, args); + } + catch (Exception e) + { + setCalloutActive(false); + Throwable ex = e.getCause(); // InvocationTargetException + if (ex == null) + ex = e; + log.log(Level.SEVERE, "start: " + methodName, ex); + ex.printStackTrace(System.err); + retValue = ex.getLocalizedMessage(); + } + return retValue; + } // start + + /** + * Conversion Rules. + * Convert a String + * + * @param methodName method name + * @param value the value + * @return converted String or Null if no method found + */ + public String convert (String methodName, String value) + { + if (methodName == null || methodName.length() == 0) + throw new IllegalArgumentException ("No Method Name"); + // + String retValue = null; + StringBuffer msg = new StringBuffer(methodName).append(" - ").append(value); + log.info (msg.toString()); + // + // Find Method + Method method = getMethod(methodName); + if (method == null) + throw new IllegalArgumentException ("Method not found: " + methodName); + int argLength = method.getParameterTypes().length; + if (argLength != 1) + throw new IllegalArgumentException ("Method " + methodName + + " has invalid no of arguments: " + argLength); + + // Call Method + try + { + Object[] args = new Object[] {value}; + retValue = (String)method.invoke(this, args); + } + catch (Exception e) + { + setCalloutActive(false); + log.log(Level.SEVERE, "convert: " + methodName, e); + e.printStackTrace(System.err); + } + return retValue; + } // convert + + /** + * Get Method + * @param methodName method name + * @return method or null + */ + private Method getMethod (String methodName) + { + Method[] allMethods = getClass().getMethods(); + for (int i = 0; i < allMethods.length; i++) + { + if (methodName.equals(allMethods[i].getName())) + return allMethods[i]; + } + return null; + } // getMethod + + /*************************************************************************/ + + private static boolean s_calloutActive = false; + + /** + * Is Callout Active + * @return true if active + */ + protected static boolean isCalloutActive() + { + return s_calloutActive; + } // isCalloutActive + + /** + * Set Callout (in)active + * @param active active + */ + protected static void setCalloutActive (boolean active) + { + s_calloutActive = active; + } // setCalloutActive + + /** + * Set Account Date Value. + * org.compiere.model.CalloutEngine.dateAcct + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String dateAcct (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive()) // assuming it is resetting value + return ""; + // setCalloutActive(true); + if (value == null || !(value instanceof Timestamp)) + return ""; + mTab.setValue("DateAcct", value); + // setCalloutActive(false); + return ""; + } // dateAcct + + /** + * Rate - set Multiply Rate from Divide Rate and vice versa + * org.compiere.model.CalloutEngine.rate + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String rate (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive() || value == null) // assuming it is Conversion_Rate + return ""; + setCalloutActive(true); + + BigDecimal rate1 = (BigDecimal)value; + BigDecimal rate2 = Env.ZERO; + BigDecimal one = new BigDecimal(1.0); + + if (rate1.doubleValue() != 0.0) // no divide by zero + rate2 = one.divide(rate1, 12, BigDecimal.ROUND_HALF_UP); + // + if (mField.getColumnName().equals("MultiplyRate")) + mTab.setValue("DivideRate", rate2); + else + mTab.setValue("MultiplyRate", rate2); + log.info(mField.getColumnName() + "=" + rate1 + " => " + rate2); + setCalloutActive(false); + return ""; + } // rate + +} // CalloutEngine diff --git a/base/src/org/compiere/model/CalloutGLJournal.java b/base/src/org/compiere/model/CalloutGLJournal.java new file mode 100644 index 0000000000..86645a0216 --- /dev/null +++ b/base/src/org/compiere/model/CalloutGLJournal.java @@ -0,0 +1,227 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * GL Journal Callout + * + * @author Jorg Janke + * @version $Id: CalloutGLJournal.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class CalloutGLJournal extends CalloutEngine +{ + /** + * Journal - Period. + * Check that selected period is in DateAcct Range or Adjusting Period + * Called when C_Period_ID or DateAcct, DateDoc changed + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String period (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + String colName = mField.getColumnName(); + if (value == null || isCalloutActive()) + return ""; + setCalloutActive(true); + + int AD_Client_ID = Env.getContextAsInt(ctx, WindowNo, "AD_Client_ID"); + Timestamp DateAcct = null; + if (colName.equals("DateAcct")) + DateAcct = (Timestamp)value; + else + DateAcct = (Timestamp)mTab.getValue("DateAcct"); + int C_Period_ID = 0; + if (colName.equals("C_Period_ID")) + C_Period_ID = ((Integer)value).intValue(); + + // When DateDoc is changed, update DateAcct + if (colName.equals("DateDoc")) + { + mTab.setValue("DateAcct", value); + } + + // When DateAcct is changed, set C_Period_ID + else if (colName.equals("DateAcct")) + { + String sql = "SELECT C_Period_ID " + + "FROM C_Period " + + "WHERE C_Year_ID IN " + + " (SELECT C_Year_ID FROM C_Year WHERE C_Calendar_ID =" + + " (SELECT C_Calendar_ID FROM AD_ClientInfo WHERE AD_Client_ID=?))" + + " AND ? BETWEEN StartDate AND EndDate" + // globalqss - cruiz - Bug [ 1577712 ] Financial Period Bug + + " AND IsActive='Y'" + + " AND PeriodType='S'"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Client_ID); + pstmt.setTimestamp(2, DateAcct); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + C_Period_ID = rs.getInt(1); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + setCalloutActive(false); + return e.getLocalizedMessage(); + } + if (C_Period_ID != 0) + mTab.setValue("C_Period_ID", new Integer(C_Period_ID)); + } + + // When C_Period_ID is changed, check if in DateAcct range and set to end date if not + else + { + String sql = "SELECT PeriodType, StartDate, EndDate " + + "FROM C_Period WHERE C_Period_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_Period_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + String PeriodType = rs.getString(1); + Timestamp StartDate = rs.getTimestamp(2); + Timestamp EndDate = rs.getTimestamp(3); + if (PeriodType.equals("S")) // Standard Periods + { + // out of range - set to last day + if (DateAcct == null + || DateAcct.before(StartDate) || DateAcct.after(EndDate)) + mTab.setValue("DateAcct", EndDate); + } + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + setCalloutActive(false); + return e.getLocalizedMessage(); + } + } + setCalloutActive(false); + return ""; + } // Journal_Period + + /** + * Journal/Line - rate. + * Set CurrencyRate from DateAcct, C_ConversionType_ID, C_Currency_ID + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String rate (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (value == null) + return ""; + + // Source info + Integer Currency_ID = (Integer)mTab.getValue("C_Currency_ID"); + int C_Currency_ID = Currency_ID.intValue(); + Integer ConversionType_ID = (Integer)mTab.getValue("C_ConversionType_ID"); + int C_ConversionType_ID = ConversionType_ID.intValue(); + Timestamp DateAcct = (Timestamp)mTab.getValue("DateAcct"); + if (DateAcct == null) + DateAcct = new Timestamp(System.currentTimeMillis()); + // + int C_AcctSchema_ID = Env.getContextAsInt(ctx, WindowNo, "C_AcctSchema_ID"); + MAcctSchema as = MAcctSchema.get (ctx, C_AcctSchema_ID); + int AD_Client_ID = Env.getContextAsInt(ctx, WindowNo, "AD_Client_ID"); + int AD_Org_ID = Env.getContextAsInt(ctx, WindowNo, "AD_Org_ID"); + + BigDecimal CurrencyRate = MConversionRate.getRate(C_Currency_ID, as.getC_Currency_ID(), + DateAcct, C_ConversionType_ID, AD_Client_ID, AD_Org_ID); + log.fine("rate = " + CurrencyRate); + if (CurrencyRate == null) + CurrencyRate = Env.ZERO; + mTab.setValue("CurrencyRate", CurrencyRate); + + return ""; + } // rate + + /** + * JournalLine - Amt. + * Convert the source amount to accounted amount (AmtAcctDr/Cr) + * Called when source amount (AmtSourceCr/Dr) or rate changes + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String amt (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + String colName = mField.getColumnName(); + if (value == null || isCalloutActive()) + return ""; + + setCalloutActive(true); + + // Get Target Currency & Precision from C_AcctSchema.C_Currency_ID + int C_AcctSchema_ID = Env.getContextAsInt(ctx, WindowNo, "C_AcctSchema_ID"); + MAcctSchema as = MAcctSchema.get(ctx, C_AcctSchema_ID); + int Precision = as.getStdPrecision(); + + BigDecimal CurrencyRate = (BigDecimal)mTab.getValue("CurrencyRate"); + if (CurrencyRate == null) + { + CurrencyRate = Env.ONE; + mTab.setValue("CurrencyRate", CurrencyRate); + } + + // AmtAcct = AmtSource * CurrencyRate ==> Precision + BigDecimal AmtSourceDr = (BigDecimal)mTab.getValue("AmtSourceDr"); + if (AmtSourceDr == null) + AmtSourceDr = Env.ZERO; + BigDecimal AmtSourceCr = (BigDecimal)mTab.getValue("AmtSourceCr"); + if (AmtSourceCr == null) + AmtSourceCr = Env.ZERO; + + BigDecimal AmtAcctDr = AmtSourceDr.multiply(CurrencyRate); + AmtAcctDr = AmtAcctDr.setScale(Precision, BigDecimal.ROUND_HALF_UP); + mTab.setValue("AmtAcctDr", AmtAcctDr); + BigDecimal AmtAcctCr = AmtSourceCr.multiply(CurrencyRate); + AmtAcctCr = AmtAcctCr.setScale(Precision, BigDecimal.ROUND_HALF_UP); + mTab.setValue("AmtAcctCr", AmtAcctCr); + + setCalloutActive(false); + return ""; + } // amt + +} // CalloutGLJournal diff --git a/base/src/org/compiere/model/CalloutInOut.java b/base/src/org/compiere/model/CalloutInOut.java new file mode 100644 index 0000000000..fa9ff5b845 --- /dev/null +++ b/base/src/org/compiere/model/CalloutInOut.java @@ -0,0 +1,521 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; +import com.sun.org.apache.bcel.internal.generic.*; + + +/** + * Shipment/Receipt Callouts + * + * @author Jorg Janke + * @version $Id: CalloutInOut.java,v 1.7 2006/07/30 00:51:05 jjanke Exp $ + */ +public class CalloutInOut extends CalloutEngine +{ + /** + * C_Order - Order Defaults. + * @param ctx + * @param WindowNo + * @param mTab + * @param mField + * @param value + * @return error message or "" + */ + public String order (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_Order_ID = (Integer)value; + if (C_Order_ID == null || C_Order_ID.intValue() == 0) + return ""; + // No Callout Active to fire dependent values + if (isCalloutActive()) // prevent recursive + return ""; + + // Get Details + MOrder order = new MOrder (ctx, C_Order_ID.intValue(), null); + if (order.get_ID() != 0) + { + mTab.setValue("DateOrdered", order.getDateOrdered()); + mTab.setValue("POReference", order.getPOReference()); + mTab.setValue("AD_Org_ID", new Integer(order.getAD_Org_ID())); + mTab.setValue("AD_OrgTrx_ID", new Integer(order.getAD_OrgTrx_ID())); + mTab.setValue("C_Activity_ID", new Integer(order.getC_Activity_ID())); + mTab.setValue("C_Campaign_ID", new Integer(order.getC_Campaign_ID())); + mTab.setValue("C_Project_ID", new Integer(order.getC_Project_ID())); + mTab.setValue("User1_ID", new Integer(order.getUser1_ID())); + mTab.setValue("User2_ID", new Integer(order.getUser2_ID())); + mTab.setValue("M_Warehouse_ID", new Integer(order.getM_Warehouse_ID())); + // + mTab.setValue("DeliveryRule", order.getDeliveryRule()); + mTab.setValue("DeliveryViaRule", order.getDeliveryViaRule()); + mTab.setValue("M_Shipper_ID", new Integer(order.getM_Shipper_ID())); + mTab.setValue("FreightCostRule", order.getFreightCostRule()); + mTab.setValue("FreightAmt", order.getFreightAmt()); + + mTab.setValue("C_BPartner_ID", new Integer(order.getC_BPartner_ID())); + } + return ""; + } // order + + + /** + * InOut - DocType. + * - sets MovementType + * - gets DocNo + * @param ctx + * @param WindowNo + * @param mTab + * @param mField + * @param value + * @return error message or "" + */ + public String docType (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_DocType_ID = (Integer)value; + if (C_DocType_ID == null || C_DocType_ID.intValue() == 0) + return ""; + + String sql = "SELECT d.DocBaseType, d.IsDocNoControlled, s.CurrentNext " + + "FROM C_DocType d, AD_Sequence s " + + "WHERE C_DocType_ID=?" // 1 + + " AND d.DocNoSequence_ID=s.AD_Sequence_ID(+)"; + try + { + Env.setContext(ctx, WindowNo, "C_DocTypeTarget_ID", C_DocType_ID.intValue()); + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_DocType_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + // Set Movement Type + String DocBaseType = rs.getString("DocBaseType"); + if (DocBaseType.equals("MMS")) // Material Shipments + mTab.setValue("MovementType", "C-"); // Customer Shipments + else if (DocBaseType.equals("MMR")) // Material Receipts + mTab.setValue("MovementType", "V+"); // Vendor Receipts + + // DocumentNo + if (rs.getString("IsDocNoControlled").equals("Y")) + mTab.setValue("DocumentNo", "<" + rs.getString("CurrentNext") + ">"); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + return e.getLocalizedMessage(); + } + return ""; + } // docType + + + /** + * M_InOut - Defaults for BPartner. + * - Location + * - Contact + * @param ctx + * @param WindowNo + * @param mTab + * @param mField + * @param value + * @return error message or "" + */ + public String bpartner (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_BPartner_ID = (Integer)value; + if (C_BPartner_ID == null || C_BPartner_ID.intValue() == 0) + return ""; + + String sql = "SELECT p.AD_Language,p.C_PaymentTerm_ID," + + "p.M_PriceList_ID,p.PaymentRule,p.POReference," + + "p.SO_Description,p.IsDiscountPrinted," + + "p.SO_CreditLimit-p.SO_CreditUsed AS CreditAvailable," + + "l.C_BPartner_Location_ID,c.AD_User_ID " + + "FROM C_BPartner p, C_BPartner_Location l, AD_User c " + + "WHERE p.C_BPartner_ID=l.C_BPartner_ID(+)" + + " AND p.C_BPartner_ID=c.C_BPartner_ID(+)" + + " AND p.C_BPartner_ID=?"; // 1 + + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_BPartner_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + BigDecimal bd; + if (rs.next()) + { + // Location + Integer ii = new Integer(rs.getInt("C_BPartner_Location_ID")); + if (rs.wasNull()) + mTab.setValue("C_BPartner_Location_ID", null); + else + mTab.setValue("C_BPartner_Location_ID", ii); + // Contact + ii = new Integer(rs.getInt("AD_User_ID")); + if (rs.wasNull()) + mTab.setValue("AD_User_ID", null); + else + mTab.setValue("AD_User_ID", ii); + + // CreditAvailable + double CreditAvailable = rs.getDouble("CreditAvailable"); + if (!rs.wasNull() && CreditAvailable < 0) + mTab.fireDataStatusEEvent("CreditLimitOver", + DisplayType.getNumberFormat(DisplayType.Amount).format(CreditAvailable), + false); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + return e.getLocalizedMessage(); + } + + return ""; + } // bpartner + + /** + * M_Warehouse. + * Set Organization and Default Locator + * @param ctx + * @param WindowNo + * @param mTab + * @param mField + * @param value + * @return error message or "" + */ + public String warehouse (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive()) + return ""; + Integer M_Warehouse_ID = (Integer)value; + if (M_Warehouse_ID == null || M_Warehouse_ID.intValue() == 0) + return ""; + setCalloutActive(true); + + String sql = "SELECT w.AD_Org_ID, l.M_Locator_ID " + + "FROM M_Warehouse w" + + " LEFT OUTER JOIN M_Locator l ON (l.M_Warehouse_ID=w.M_Warehouse_ID AND l.IsDefault='Y') " + + "WHERE w.M_Warehouse_ID=?"; // 1 + + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, M_Warehouse_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + BigDecimal bd; + if (rs.next()) + { + // Org + Integer ii = new Integer(rs.getInt(1)); + int AD_Org_ID = Env.getContextAsInt(ctx, WindowNo, "AD_Org_ID"); + if (AD_Org_ID != ii.intValue()) + mTab.setValue("AD_Org_ID", ii); + // Locator + ii = new Integer(rs.getInt(2)); + if (rs.wasNull()) + Env.setContext(ctx, WindowNo, 0, "M_Locator_ID", null); + else + { + log.config("M_Locator_ID=" + ii); + Env.setContext(ctx, WindowNo, "M_Locator_ID", ii.intValue()); + } + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + setCalloutActive(false); + return e.getLocalizedMessage(); + } + + setCalloutActive(false); + return ""; + } // warehouse + + + /************************************************************************** + * OrderLine Callout + * @param ctx context + * @param WindowNo window no + * @param mTab tab model + * @param mField field model + * @param value new value + * @return error message or "" + */ + public String orderLine (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_OrderLine_ID = (Integer)value; + if (C_OrderLine_ID == null || C_OrderLine_ID.intValue() == 0) + return ""; + setCalloutActive(true); + + // Get Details + MOrderLine ol = new MOrderLine (ctx, C_OrderLine_ID.intValue(), null); + if (ol.get_ID() != 0) + { + mTab.setValue("M_Product_ID", new Integer(ol.getM_Product_ID())); + mTab.setValue("M_AttributeSetInstance_ID", new Integer(ol.getM_AttributeSetInstance_ID())); + // + mTab.setValue("C_UOM_ID", new Integer(ol.getC_UOM_ID())); + BigDecimal MovementQty = ol.getQtyOrdered().subtract(ol.getQtyDelivered()); + mTab.setValue("MovementQty", MovementQty); + BigDecimal QtyEntered = MovementQty; + if (ol.getQtyEntered().compareTo(ol.getQtyOrdered()) != 0) + QtyEntered = QtyEntered.multiply(ol.getQtyEntered()) + .divide(ol.getQtyOrdered(), 12, BigDecimal.ROUND_HALF_UP); + mTab.setValue("QtyEntered", QtyEntered); + // + mTab.setValue("C_Activity_ID", new Integer(ol.getC_Activity_ID())); + mTab.setValue("C_Campaign_ID", new Integer(ol.getC_Campaign_ID())); + mTab.setValue("C_Project_ID", new Integer(ol.getC_Project_ID())); + mTab.setValue("C_ProjectPhase_ID", new Integer(ol.getC_ProjectPhase_ID())); + mTab.setValue("C_ProjectTask_ID", new Integer(ol.getC_ProjectTask_ID())); + mTab.setValue("AD_OrgTrx_ID", new Integer(ol.getAD_OrgTrx_ID())); + mTab.setValue("User1_ID", new Integer(ol.getUser1_ID())); + mTab.setValue("User2_ID", new Integer(ol.getUser2_ID())); + } + setCalloutActive(false); + return ""; + } // orderLine + + /** + * M_InOutLine - Default UOM/Locator for Product. + * @param ctx context + * @param WindowNo window no + * @param mTab tab model + * @param mField field model + * @param value new value + * @return error message or "" + */ + public String product (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive()) + return ""; + Integer M_Product_ID = (Integer)value; + if (M_Product_ID == null || M_Product_ID.intValue() == 0) + return ""; + setCalloutActive(true); + + // Set Attribute & Locator + int M_Locator_ID = 0; + if (Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_Product_ID") == M_Product_ID.intValue() + && Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_AttributeSetInstance_ID") != 0) + { + mTab.setValue("M_AttributeSetInstance_ID", + new Integer(Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_AttributeSetInstance_ID"))); + M_Locator_ID = Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_Locator_ID"); + if (M_Locator_ID != 0) + mTab.setValue("M_Locator_ID", new Integer(M_Locator_ID)); + } + else + mTab.setValue("M_AttributeSetInstance_ID", null); + // + int M_Warehouse_ID = Env.getContextAsInt(ctx, WindowNo, "M_Warehouse_ID"); + boolean IsSOTrx = "Y".equals(Env.getContext(ctx, WindowNo, "IsSOTrx")); + if (IsSOTrx) + { + setCalloutActive(false); + return ""; + } + + // Set UOM/Locator/Qty + MProduct product = MProduct.get(ctx, M_Product_ID.intValue()); + mTab.setValue("C_UOM_ID", new Integer (product.getC_UOM_ID())); + BigDecimal QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); + mTab.setValue("MovementQty", QtyEntered); + if (M_Locator_ID != 0) + ; // already set + else if (product.getM_Locator_ID() != 0) + { + MLocator loc = MLocator.get(ctx, product.getM_Locator_ID()); + if (M_Warehouse_ID == loc.getM_Warehouse_ID()) + mTab.setValue("M_Locator_ID", new Integer (product.getM_Locator_ID())); + else + log.fine("No Locator for M_Product_ID=" + M_Product_ID + " and M_Warehouse_ID=" + M_Warehouse_ID); + } + else + log.fine("No Locator for M_Product_ID=" + M_Product_ID); + setCalloutActive(false); + return ""; + } // product + + /** + * InOut Line - Quantity. + * - called from C_UOM_ID, QtyEntered, MovementQty + * - enforces qty UOM relationship + * @param ctx context + * @param WindowNo window no + * @param mTab tab model + * @param mField field model + * @param value new value + * @return error message or "" + */ + public String qty (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive() || value == null) + return ""; + setCalloutActive(true); + + int M_Product_ID = Env.getContextAsInt(ctx, WindowNo, "M_Product_ID"); + // log.log(Level.WARNING,"qty - init - M_Product_ID=" + M_Product_ID); + BigDecimal MovementQty, QtyEntered; + + // No Product + if (M_Product_ID == 0) + { + QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); + mTab.setValue("MovementQty", QtyEntered); + } + // UOM Changed - convert from Entered -> Product + else if (mField.getColumnName().equals("C_UOM_ID")) + { + int C_UOM_To_ID = ((Integer)value).intValue(); + QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); + BigDecimal QtyEntered1 = QtyEntered.setScale(MUOM.getPrecision(ctx, C_UOM_To_ID), BigDecimal.ROUND_HALF_UP); + if (QtyEntered.compareTo(QtyEntered1) != 0) + { + log.fine("Corrected QtyEntered Scale UOM=" + C_UOM_To_ID + + "; QtyEntered=" + QtyEntered + "->" + QtyEntered1); + QtyEntered = QtyEntered1; + mTab.setValue("QtyEntered", QtyEntered); + } + MovementQty = MUOMConversion.convertProductFrom (ctx, M_Product_ID, + C_UOM_To_ID, QtyEntered); + if (MovementQty == null) + MovementQty = QtyEntered; + boolean conversion = QtyEntered.compareTo(MovementQty) != 0; + log.fine("UOM=" + C_UOM_To_ID + + ", QtyEntered=" + QtyEntered + + " -> " + conversion + + " MovementQty=" + MovementQty); + Env.setContext(ctx, WindowNo, "UOMConversion", conversion ? "Y" : "N"); + mTab.setValue("MovementQty", MovementQty); + } + // No UOM defined + else if (Env.getContextAsInt(ctx, WindowNo, "C_UOM_ID") == 0) + { + QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); + mTab.setValue("MovementQty", QtyEntered); + } + // QtyEntered changed - calculate MovementQty + else if (mField.getColumnName().equals("QtyEntered")) + { + int C_UOM_To_ID = Env.getContextAsInt(ctx, WindowNo, "C_UOM_ID"); + QtyEntered = (BigDecimal)value; + BigDecimal QtyEntered1 = QtyEntered.setScale(MUOM.getPrecision(ctx, C_UOM_To_ID), BigDecimal.ROUND_HALF_UP); + if (QtyEntered.compareTo(QtyEntered1) != 0) + { + log.fine("Corrected QtyEntered Scale UOM=" + C_UOM_To_ID + + "; QtyEntered=" + QtyEntered + "->" + QtyEntered1); + QtyEntered = QtyEntered1; + mTab.setValue("QtyEntered", QtyEntered); + } + MovementQty = MUOMConversion.convertProductFrom (ctx, M_Product_ID, + C_UOM_To_ID, QtyEntered); + if (MovementQty == null) + MovementQty = QtyEntered; + boolean conversion = QtyEntered.compareTo(MovementQty) != 0; + log.fine("UOM=" + C_UOM_To_ID + + ", QtyEntered=" + QtyEntered + + " -> " + conversion + + " MovementQty=" + MovementQty); + Env.setContext(ctx, WindowNo, "UOMConversion", conversion ? "Y" : "N"); + mTab.setValue("MovementQty", MovementQty); + } + // MovementQty changed - calculate QtyEntered (should not happen) + else if (mField.getColumnName().equals("MovementQty")) + { + int C_UOM_To_ID = Env.getContextAsInt(ctx, WindowNo, "C_UOM_ID"); + MovementQty = (BigDecimal)value; + int precision = MProduct.get(ctx, M_Product_ID).getUOMPrecision(); + BigDecimal MovementQty1 = MovementQty.setScale(precision, BigDecimal.ROUND_HALF_UP); + if (MovementQty.compareTo(MovementQty1) != 0) + { + log.fine("Corrected MovementQty " + + MovementQty + "->" + MovementQty1); + MovementQty = MovementQty1; + mTab.setValue("MovementQty", MovementQty); + } + QtyEntered = MUOMConversion.convertProductTo (ctx, M_Product_ID, + C_UOM_To_ID, MovementQty); + if (QtyEntered == null) + QtyEntered = MovementQty; + boolean conversion = MovementQty.compareTo(QtyEntered) != 0; + log.fine("UOM=" + C_UOM_To_ID + + ", MovementQty=" + MovementQty + + " -> " + conversion + + " QtyEntered=" + QtyEntered); + Env.setContext(ctx, WindowNo, "UOMConversion", conversion ? "Y" : "N"); + mTab.setValue("QtyEntered", QtyEntered); + } + // + setCalloutActive(false); + return ""; + } // qty + + /** + * M_InOutLine - ASI. + * @param ctx context + * @param WindowNo window no + * @param mTab tab model + * @param mField field model + * @param value new value + * @return error message or "" + */ + public String asi (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive()) + return ""; + Integer M_ASI_ID = (Integer)value; + if (M_ASI_ID == null || M_ASI_ID.intValue() == 0) + return ""; + setCalloutActive(true); + // + int M_Product_ID = Env.getContextAsInt(ctx, WindowNo, "M_Product_ID"); + int M_Warehouse_ID = Env.getContextAsInt(ctx, WindowNo, "M_Warehouse_ID"); + int M_Locator_ID = Env.getContextAsInt(ctx, WindowNo, "M_Locator_ID"); + log.fine("M_Product_ID=" + M_Product_ID + + ", M_ASI_ID=" + M_ASI_ID + + " - M_Warehouse_ID=" + M_Warehouse_ID + + ", M_Locator_ID=" + M_Locator_ID); + // Check Selection + int M_AttributeSetInstance_ID = Env.getContextAsInt(Env.getCtx(), Env.WINDOW_INFO, Env.TAB_INFO, "M_AttributeSetInstance_ID"); + if (M_ASI_ID.intValue() == M_AttributeSetInstance_ID) + { + int selectedM_Locator_ID = Env.getContextAsInt(Env.getCtx(), Env.WINDOW_INFO, Env.TAB_INFO, "M_Locator_ID"); + if (selectedM_Locator_ID != 0) + { + log.fine("Selected M_Locator_ID=" + selectedM_Locator_ID); + mTab.setValue("M_Locator_ID", new Integer (selectedM_Locator_ID)); + } + } + setCalloutActive(false); + return ""; + } // asi + +} // CalloutInOut diff --git a/base/src/org/compiere/model/CalloutInventory.java b/base/src/org/compiere/model/CalloutInventory.java new file mode 100644 index 0000000000..6f5caa37bb --- /dev/null +++ b/base/src/org/compiere/model/CalloutInventory.java @@ -0,0 +1,124 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Physical Inventory Callouts + * + * @author Jorg Janke + * @version $Id: CalloutInventory.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class CalloutInventory extends CalloutEngine +{ + /** + * Product/Locator/ASI modified. + * Set Attribute Set Instance + * + * @param ctx Context + * @param WindowNo current Window No + * @param mTab Model Tab + * @param mField Model Field + * @param value The new value + * @return Error message or "" + */ + public String product (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive()) + return ""; + Integer InventoryLine = (Integer)mTab.getValue("M_InventoryLine_ID"); + if (InventoryLine != null && InventoryLine.intValue() != 0) + return ""; + + // New Line - Get Book Value + int M_Product_ID = 0; + Integer Product = (Integer)mTab.getValue("M_Product_ID"); + if (Product != null) + M_Product_ID = Product.intValue(); + if (M_Product_ID == 0) + return ""; + int M_Locator_ID = 0; + Integer Locator = (Integer)mTab.getValue("M_Locator_ID"); + if (Locator != null) + M_Locator_ID = Locator.intValue(); + if (M_Locator_ID == 0) + return ""; + + setCalloutActive(true); + // Set Attribute + int M_AttributeSetInstance_ID = 0; + Integer ASI = (Integer)mTab.getValue("M_AttributeSetInstance_ID"); + if (ASI != null) + M_AttributeSetInstance_ID = ASI.intValue(); + // Product Selection + if (Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_Product_ID") == M_Product_ID) + { + M_AttributeSetInstance_ID = Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_AttributeSetInstance_ID"); + if (M_AttributeSetInstance_ID != 0) + mTab.setValue("M_AttributeSetInstance_ID", new Integer(M_AttributeSetInstance_ID)); + else + mTab.setValue("M_AttributeSetInstance_ID", null); + } + + // Set QtyBook from first storage location + BigDecimal bd = null; + String sql = "SELECT QtyOnHand FROM M_Storage " + + "WHERE M_Product_ID=?" // 1 + + " AND M_Locator_ID=?" // 2 + + " AND M_AttributeSetInstance_ID=?"; + if (M_AttributeSetInstance_ID == 0) + sql = "SELECT SUM(QtyOnHand) FROM M_Storage " + + "WHERE M_Product_ID=?" // 1 + + " AND M_Locator_ID=?"; // 2 + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, M_Product_ID); + pstmt.setInt(2, M_Locator_ID); + if (M_AttributeSetInstance_ID != 0) + pstmt.setInt(3, M_AttributeSetInstance_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + bd = rs.getBigDecimal(1); + if (bd != null) + mTab.setValue("QtyBook", bd); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + setCalloutActive(false); + return e.getLocalizedMessage(); + } + // + log.info("M_Product_ID=" + M_Product_ID + + ", M_Locator_ID=" + M_Locator_ID + + ", M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID + + " - QtyBook=" + bd); + setCalloutActive(false); + return ""; + } // product + +} // CalloutInventory diff --git a/base/src/org/compiere/model/CalloutInvoice.java b/base/src/org/compiere/model/CalloutInvoice.java new file mode 100644 index 0000000000..2e05b0b229 --- /dev/null +++ b/base/src/org/compiere/model/CalloutInvoice.java @@ -0,0 +1,764 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Invoice Callouts + * + * @author Jorg Janke + * @version $Id: CalloutInvoice.java,v 1.4 2006/07/30 00:51:03 jjanke Exp $ + */ +public class CalloutInvoice extends CalloutEngine +{ + + /** + * Invoice Header - DocType. + * - PaymentRule + * - temporary Document + * Context: + * - DocSubTypeSO + * - HasCharges + * - (re-sets Business Partner info of required) + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String docType (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_DocType_ID = (Integer)value; + if (C_DocType_ID == null || C_DocType_ID.intValue() == 0) + return ""; + + String sql = "SELECT d.HasCharges,'N',d.IsDocNoControlled," + + "s.CurrentNext, d.DocBaseType " + + "FROM C_DocType d, AD_Sequence s " + + "WHERE C_DocType_ID=?" // 1 + + " AND d.DocNoSequence_ID=s.AD_Sequence_ID(+)"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_DocType_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + // Charges - Set Context + Env.setContext(ctx, WindowNo, "HasCharges", rs.getString(1)); + // DocumentNo + if (rs.getString(3).equals("Y")) + mTab.setValue("DocumentNo", "<" + rs.getString(4) + ">"); + // DocBaseType - Set Context + String s = rs.getString(5); + Env.setContext(ctx, WindowNo, "DocBaseType", s); + // AP Check & AR Credit Memo + if (s.startsWith("AP")) + mTab.setValue("PaymentRule", "S"); // Check + else if (s.endsWith("C")) + mTab.setValue("PaymentRule", "P"); // OnCredit + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + return e.getLocalizedMessage(); + } + return ""; + } // docType + + + /** + * Invoice Header- BPartner. + * - M_PriceList_ID (+ Context) + * - C_BPartner_Location_ID + * - AD_User_ID + * - POReference + * - SO_Description + * - IsDiscountPrinted + * - PaymentRule + * - C_PaymentTerm_ID + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String bPartner (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_BPartner_ID = (Integer)value; + if (C_BPartner_ID == null || C_BPartner_ID.intValue() == 0) + return ""; + + String sql = "SELECT p.AD_Language,p.C_PaymentTerm_ID," + + " COALESCE(p.M_PriceList_ID,g.M_PriceList_ID) AS M_PriceList_ID, p.PaymentRule,p.POReference," + + " 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 " + + "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')" + + " LEFT OUTER JOIN AD_User c ON (p.C_BPartner_ID=c.C_BPartner_ID) " + + "WHERE p.C_BPartner_ID=? AND p.IsActive='Y'"; // #1 + + boolean IsSOTrx = Env.getContext(ctx, WindowNo, "IsSOTrx").equals("Y"); + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_BPartner_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + // + if (rs.next()) + { + // PriceList & IsTaxIncluded & Currency + Integer ii = new Integer(rs.getInt(IsSOTrx ? "M_PriceList_ID" : "PO_PriceList_ID")); + if (!rs.wasNull()) + mTab.setValue("M_PriceList_ID", ii); + else + { // get default PriceList + int i = Env.getContextAsInt(ctx, "#M_PriceList_ID"); + if (i != 0) + mTab.setValue("M_PriceList_ID", new Integer(i)); + } + + // PaymentRule + String s = rs.getString(IsSOTrx ? "PaymentRule" : "PaymentRulePO"); + if (s != null && s.length() != 0) + { + if (Env.getContext(ctx, WindowNo, "DocBaseType").endsWith("C")) // Credits are Payment Term + s = "P"; + else if (IsSOTrx && (s.equals("S") || s.equals("U"))) // No Check/Transfer for SO_Trx + s = "P"; // Payment Term + mTab.setValue("PaymentRule", s); + } + // Payment Term + ii = new Integer(rs.getInt(IsSOTrx ? "C_PaymentTerm_ID" : "PO_PaymentTerm_ID")); + if (!rs.wasNull()) + mTab.setValue("C_PaymentTerm_ID", ii); + + // Location + int locID = rs.getInt("C_BPartner_Location_ID"); + // overwritten by InfoBP selection - works only if InfoWindow + // was used otherwise creates error (uses last value, may belong to differnt BP) + if (C_BPartner_ID.toString().equals(Env.getContext(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_BPartner_ID"))) + { + String loc = Env.getContext(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_BPartner_Location_ID"); + if (loc.length() > 0) + locID = Integer.parseInt(loc); + } + if (locID == 0) + mTab.setValue("C_BPartner_Location_ID", null); + else + mTab.setValue("C_BPartner_Location_ID", new Integer(locID)); + + // Contact - overwritten by InfoBP selection + int contID = rs.getInt("AD_User_ID"); + if (C_BPartner_ID.toString().equals(Env.getContext(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_BPartner_ID"))) + { + String cont = Env.getContext(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "AD_User_ID"); + if (cont.length() > 0) + contID = Integer.parseInt(cont); + } + if (contID == 0) + mTab.setValue("AD_User_ID", null); + else + mTab.setValue("AD_User_ID", new Integer(contID)); + + // CreditAvailable + if (IsSOTrx) + { + double CreditLimit = rs.getDouble("SO_CreditLimit"); + if (CreditLimit != 0) + { + double CreditAvailable = rs.getDouble("CreditAvailable"); + if (!rs.wasNull() && CreditAvailable < 0) + mTab.fireDataStatusEEvent("CreditLimitOver", + DisplayType.getNumberFormat(DisplayType.Amount).format(CreditAvailable), + false); + } + } + + // PO Reference + s = rs.getString("POReference"); + if (s != null && s.length() != 0) + mTab.setValue("POReference", s); + else + mTab.setValue("POReference", null); + // SO Description + s = rs.getString("SO_Description"); + if (s != null && s.trim().length() != 0) + mTab.setValue("Description", s); + // IsDiscountPrinted + s = rs.getString("IsDiscountPrinted"); + if (s != null && s.length() != 0) + mTab.setValue("IsDiscountPrinted", s); + else + mTab.setValue("IsDiscountPrinted", "N"); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "bPartner", e); + return e.getLocalizedMessage(); + } + + return ""; + } // bPartner + + /** + * Set Payment Term. + * Payment Term has changed + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String paymentTerm (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_PaymentTerm_ID = (Integer)value; + int C_Invoice_ID = Env.getContextAsInt(ctx, WindowNo, "C_Invoice_ID"); + if (C_PaymentTerm_ID == null || C_PaymentTerm_ID.intValue() == 0 + || C_Invoice_ID == 0) // not saved yet + return ""; + // + MPaymentTerm pt = new MPaymentTerm (ctx, C_PaymentTerm_ID.intValue(), null); + if (pt.get_ID() == 0) + return "PaymentTerm not found"; + + boolean valid = pt.apply (C_Invoice_ID); + mTab.setValue("IsPayScheduleValid", valid ? "Y" : "N"); + + return ""; + } // paymentTerm + + + /************************************************************************** + * Invoice Line - Product. + * - reset C_Charge_ID / M_AttributeSetInstance_ID + * - PriceList, PriceStd, PriceLimit, C_Currency_ID, EnforcePriceLimit + * - UOM + * Calls Tax + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String product (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer M_Product_ID = (Integer)value; + if (M_Product_ID == null || M_Product_ID.intValue() == 0) + return ""; + setCalloutActive(true); + mTab.setValue("C_Charge_ID", null); + + // Set Attribute + if (Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_Product_ID") == M_Product_ID.intValue() + && Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_AttributeSetInstance_ID") != 0) + mTab.setValue("M_AttributeSetInstance_ID", new Integer(Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_AttributeSetInstance_ID"))); + else + mTab.setValue("M_AttributeSetInstance_ID", null); + + /***** Price Calculation see also qty ****/ + boolean IsSOTrx = Env.getContext(ctx, WindowNo, "IsSOTrx").equals("Y"); + int C_BPartner_ID = Env.getContextAsInt(ctx, WindowNo, WindowNo, "C_BPartner_ID"); + BigDecimal Qty = (BigDecimal)mTab.getValue("QtyInvoiced"); + MProductPricing pp = new MProductPricing (M_Product_ID.intValue(), C_BPartner_ID, Qty, IsSOTrx); + // + int M_PriceList_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_ID"); + pp.setM_PriceList_ID(M_PriceList_ID); + int M_PriceList_Version_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_Version_ID"); + pp.setM_PriceList_Version_ID(M_PriceList_Version_ID); + Timestamp date = Env.getContextAsDate(ctx, WindowNo, "DateInvoiced"); + pp.setPriceDate(date); + // + mTab.setValue("PriceList", pp.getPriceList()); + mTab.setValue("PriceLimit", pp.getPriceLimit()); + mTab.setValue("PriceActual", pp.getPriceStd()); + mTab.setValue("PriceEntered", pp.getPriceStd()); + mTab.setValue("C_Currency_ID", new Integer(pp.getC_Currency_ID())); + // mTab.setValue("Discount", pp.getDiscount()); + mTab.setValue("C_UOM_ID", new Integer(pp.getC_UOM_ID())); + Env.setContext(ctx, WindowNo, "EnforcePriceLimit", pp.isEnforcePriceLimit() ? "Y" : "N"); + Env.setContext(ctx, WindowNo, "DiscountSchema", pp.isDiscountSchema() ? "Y" : "N"); + // + setCalloutActive(false); + return tax (ctx, WindowNo, mTab, mField, value); + } // product + + /** + * Invoice Line - Charge. + * - updates PriceActual from Charge + * - sets PriceLimit, PriceList to zero + * Calles tax + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String charge (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_Charge_ID = (Integer)value; + if (C_Charge_ID == null || C_Charge_ID.intValue() == 0) + return ""; + + // No Product defined + if (mTab.getValue("M_Product_ID") != null) + { + mTab.setValue("C_Charge_ID", null); + return "ChargeExclusively"; + } + mTab.setValue("M_AttributeSetInstance_ID", null); + mTab.setValue("S_ResourceAssignment_ID", null); + mTab.setValue("C_UOM_ID", new Integer(100)); // EA + + Env.setContext(ctx, WindowNo, "DiscountSchema", "N"); + String sql = "SELECT ChargeAmt FROM C_Charge WHERE C_Charge_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_Charge_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + mTab.setValue ("PriceEntered", rs.getBigDecimal (1)); + mTab.setValue ("PriceActual", rs.getBigDecimal (1)); + mTab.setValue ("PriceLimit", Env.ZERO); + mTab.setValue ("PriceList", Env.ZERO); + mTab.setValue ("Discount", Env.ZERO); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql + e); + return e.getLocalizedMessage(); + } + // + return tax (ctx, WindowNo, mTab, mField, value); + } // charge + + + /** + * Invoice Line - Tax. + * - basis: Product, Charge, BPartner Location + * - sets C_Tax_ID + * Calles Amount + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String tax (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + String column = mField.getColumnName(); + if (value == null) + return ""; + + // Check Product + int M_Product_ID = 0; + if (column.equals("M_Product_ID")) + M_Product_ID = ((Integer)value).intValue(); + else + M_Product_ID = Env.getContextAsInt(ctx, WindowNo, "M_Product_ID"); + int C_Charge_ID = 0; + if (column.equals("C_Charge_ID")) + C_Charge_ID = ((Integer)value).intValue(); + else + C_Charge_ID = Env.getContextAsInt(ctx, WindowNo, "C_Charge_ID"); + log.fine("Product=" + M_Product_ID + ", C_Charge_ID=" + C_Charge_ID); + if (M_Product_ID == 0 && C_Charge_ID == 0) + return amt (ctx, WindowNo, mTab, mField, value); // + + // Check Partner Location + int shipC_BPartner_Location_ID = Env.getContextAsInt(ctx, WindowNo, "C_BPartner_Location_ID"); + if (shipC_BPartner_Location_ID == 0) + return amt (ctx, WindowNo, mTab, mField, value); // + log.fine("Ship BP_Location=" + shipC_BPartner_Location_ID); + int billC_BPartner_Location_ID = shipC_BPartner_Location_ID; + log.fine("Bill BP_Location=" + billC_BPartner_Location_ID); + + // Dates + Timestamp billDate = Env.getContextAsDate(ctx, WindowNo, "DateInvoiced"); + log.fine("Bill Date=" + billDate); + Timestamp shipDate = billDate; + log.fine("Ship Date=" + shipDate); + + int AD_Org_ID = Env.getContextAsInt(ctx, WindowNo, "AD_Org_ID"); + log.fine("Org=" + AD_Org_ID); + + int M_Warehouse_ID = Env.getContextAsInt(ctx, "#M_Warehouse_ID"); + log.fine("Warehouse=" + M_Warehouse_ID); + + // + int C_Tax_ID = Tax.get(ctx, M_Product_ID, C_Charge_ID, billDate, shipDate, + AD_Org_ID, M_Warehouse_ID, billC_BPartner_Location_ID, shipC_BPartner_Location_ID, + Env.getContext(ctx, WindowNo, "IsSOTrx").equals("Y")); + log.info("Tax ID=" + C_Tax_ID); + // + if (C_Tax_ID == 0) + mTab.fireDataStatusEEvent(CLogger.retrieveError()); + else + mTab.setValue("C_Tax_ID", new Integer(C_Tax_ID)); + // + return amt (ctx, WindowNo, mTab, mField, value); + } // tax + + + /** + * Invoice - Amount. + * - called from QtyInvoiced, PriceActual + * - calculates LineNetAmt + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String amt (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive() || value == null) + return ""; + setCalloutActive(true); + + // log.log(Level.WARNING,"amt - init"); + int C_UOM_To_ID = Env.getContextAsInt(ctx, WindowNo, "C_UOM_ID"); + int M_Product_ID = Env.getContextAsInt(ctx, WindowNo, "M_Product_ID"); + int M_PriceList_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_ID"); + int StdPrecision = MPriceList.getStandardPrecision(ctx, M_PriceList_ID); + BigDecimal QtyEntered, QtyInvoiced, PriceEntered, PriceActual, PriceLimit, Discount, PriceList; + // get values + QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); + QtyInvoiced = (BigDecimal)mTab.getValue("QtyInvoiced"); + log.fine("QtyEntered=" + QtyEntered + ", Invoiced=" + QtyInvoiced + ", UOM=" + C_UOM_To_ID); + // + PriceEntered = (BigDecimal)mTab.getValue("PriceEntered"); + PriceActual = (BigDecimal)mTab.getValue("PriceActual"); + // Discount = (BigDecimal)mTab.getValue("Discount"); + PriceLimit = (BigDecimal)mTab.getValue("PriceLimit"); + PriceList = (BigDecimal)mTab.getValue("PriceList"); + log.fine("PriceList=" + PriceList + ", Limit=" + PriceLimit + ", Precision=" + StdPrecision); + log.fine("PriceEntered=" + PriceEntered + ", Actual=" + PriceActual);// + ", Discount=" + Discount); + + // Qty changed - recalc price + if ((mField.getColumnName().equals("QtyInvoiced") + || mField.getColumnName().equals("QtyEntered") + || mField.getColumnName().equals("M_Product_ID")) + && !"N".equals(Env.getContext(ctx, WindowNo, "DiscountSchema"))) + { + int C_BPartner_ID = Env.getContextAsInt(ctx, WindowNo, "C_BPartner_ID"); + if (mField.getColumnName().equals("QtyEntered")) + QtyInvoiced = MUOMConversion.convertProductTo (ctx, M_Product_ID, + C_UOM_To_ID, QtyEntered); + if (QtyInvoiced == null) + QtyInvoiced = QtyEntered; + boolean IsSOTrx = Env.getContext(ctx, WindowNo, "IsSOTrx").equals("Y"); + MProductPricing pp = new MProductPricing (M_Product_ID, C_BPartner_ID, QtyInvoiced, IsSOTrx); + pp.setM_PriceList_ID(M_PriceList_ID); + int M_PriceList_Version_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_Version_ID"); + pp.setM_PriceList_Version_ID(M_PriceList_Version_ID); + Timestamp date = (Timestamp)mTab.getValue("DateInvoiced"); + pp.setPriceDate(date); + // + PriceEntered = MUOMConversion.convertProductFrom (ctx, M_Product_ID, + C_UOM_To_ID, pp.getPriceStd()); + if (PriceEntered == null) + PriceEntered = pp.getPriceStd(); + // + log.fine("amt - QtyChanged -> PriceActual=" + pp.getPriceStd() + + ", PriceEntered=" + PriceEntered + ", Discount=" + pp.getDiscount()); + mTab.setValue("PriceActual", pp.getPriceStd()); + // mTab.setValue("Discount", pp.getDiscount()); + mTab.setValue("PriceEntered", PriceEntered); + Env.setContext(ctx, WindowNo, "DiscountSchema", pp.isDiscountSchema() ? "Y" : "N"); + } + else if (mField.getColumnName().equals("PriceActual")) + { + PriceActual = (BigDecimal)value; + PriceEntered = MUOMConversion.convertProductFrom (ctx, M_Product_ID, + C_UOM_To_ID, PriceActual); + if (PriceEntered == null) + PriceEntered = PriceActual; + // + log.fine("amt - PriceActual=" + PriceActual + + " -> PriceEntered=" + PriceEntered); + mTab.setValue("PriceEntered", PriceEntered); + } + else if (mField.getColumnName().equals("PriceEntered")) + { + PriceEntered = (BigDecimal)value; + PriceActual = MUOMConversion.convertProductTo (ctx, M_Product_ID, + C_UOM_To_ID, PriceEntered); + if (PriceActual == null) + PriceActual = PriceEntered; + // + log.fine("amt - PriceEntered=" + PriceEntered + + " -> PriceActual=" + PriceActual); + mTab.setValue("PriceActual", PriceActual); + } + + /** Discount entered - Calculate Actual/Entered + if (mField.getColumnName().equals("Discount")) + { + PriceActual = new BigDecimal ((100.0 - Discount.doubleValue()) / 100.0 * PriceList.doubleValue()); + if (PriceActual.scale() > StdPrecision) + PriceActual = PriceActual.setScale(StdPrecision, BigDecimal.ROUND_HALF_UP); + PriceEntered = MUOMConversion.convertProductFrom (ctx, M_Product_ID, + C_UOM_To_ID, PriceActual); + if (PriceEntered == null) + PriceEntered = PriceActual; + mTab.setValue("PriceActual", PriceActual); + mTab.setValue("PriceEntered", PriceEntered); + } + // calculate Discount + else + { + if (PriceList.intValue() == 0) + Discount = Env.ZERO; + else + Discount = new BigDecimal ((PriceList.doubleValue() - PriceActual.doubleValue()) / PriceList.doubleValue() * 100.0); + if (Discount.scale() > 2) + Discount = Discount.setScale(2, BigDecimal.ROUND_HALF_UP); + mTab.setValue("Discount", Discount); + } + log.fine("amt = PriceEntered=" + PriceEntered + ", Actual" + PriceActual + ", Discount=" + Discount); + /* */ + + // Check PriceLimit + String epl = Env.getContext(ctx, WindowNo, "EnforcePriceLimit"); + boolean enforce = Env.isSOTrx(ctx, WindowNo) && epl != null && epl.equals("Y"); + if (enforce && MRole.getDefault().isOverwritePriceLimit()) + enforce = false; + // Check Price Limit? + if (enforce && PriceLimit.doubleValue() != 0.0 + && PriceActual.compareTo(PriceLimit) < 0) + { + PriceActual = PriceLimit; + PriceEntered = MUOMConversion.convertProductFrom (ctx, M_Product_ID, + C_UOM_To_ID, PriceLimit); + if (PriceEntered == null) + PriceEntered = PriceLimit; + log.fine("amt =(under) PriceEntered=" + PriceEntered + ", Actual" + PriceLimit); + mTab.setValue ("PriceActual", PriceLimit); + mTab.setValue ("PriceEntered", PriceEntered); + mTab.fireDataStatusEEvent ("UnderLimitPrice", "", false); + // Repeat Discount calc + if (PriceList.intValue() != 0) + { + Discount = new BigDecimal ((PriceList.doubleValue () - PriceActual.doubleValue ()) / PriceList.doubleValue () * 100.0); + if (Discount.scale () > 2) + Discount = Discount.setScale (2, BigDecimal.ROUND_HALF_UP); + // mTab.setValue ("Discount", Discount); + } + } + + // Line Net Amt + BigDecimal LineNetAmt = QtyInvoiced.multiply(PriceActual); + if (LineNetAmt.scale() > StdPrecision) + LineNetAmt = LineNetAmt.setScale(StdPrecision, BigDecimal.ROUND_HALF_UP); + log.info("amt = LineNetAmt=" + LineNetAmt); + mTab.setValue("LineNetAmt", LineNetAmt); + + // Calculate Tax Amount for PO + boolean IsSOTrx = "Y".equals(Env.getContext(Env.getCtx(), WindowNo, "IsSOTrx")); + if (!IsSOTrx) + { + BigDecimal TaxAmt = null; + if (mField.getColumnName().equals("TaxAmt")) + { + TaxAmt = (BigDecimal)mTab.getValue("TaxAmt"); + } + else + { + Integer taxID = (Integer)mTab.getValue("C_Tax_ID"); + if (taxID != null) + { + int C_Tax_ID = taxID.intValue(); + MTax tax = new MTax (ctx, C_Tax_ID, null); + TaxAmt = tax.calculateTax(LineNetAmt, isTaxIncluded(WindowNo), StdPrecision); + mTab.setValue("TaxAmt", TaxAmt); + } + } + // Add it up + mTab.setValue("LineTotalAmt", LineNetAmt.add(TaxAmt)); + } + + setCalloutActive(false); + return ""; + } // amt + + /** + * Is Tax Included + * @param WindowNo window no + * @return tax included (default: false) + */ + private boolean isTaxIncluded (int WindowNo) + { + String ss = Env.getContext(Env.getCtx(), WindowNo, "IsTaxIncluded"); + // Not Set Yet + if (ss.length() == 0) + { + int M_PriceList_ID = Env.getContextAsInt(Env.getCtx(), WindowNo, "M_PriceList_ID"); + if (M_PriceList_ID == 0) + return false; + ss = DB.getSQLValueString(null, + "SELECT IsTaxIncluded FROM M_PriceList WHERE M_PriceList_ID=?", + M_PriceList_ID); + if (ss == null) + ss = "N"; + Env.setContext(Env.getCtx(), WindowNo, "IsTaxIncluded", ss); + } + return "Y".equals(ss); + } // isTaxIncluded + + /** + * Invoice Line - Quantity. + * - called from C_UOM_ID, QtyEntered, QtyInvoiced + * - enforces qty UOM relationship + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String qty (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive() || value == null) + return ""; + setCalloutActive(true); + + int M_Product_ID = Env.getContextAsInt(ctx, WindowNo, "M_Product_ID"); + // log.log(Level.WARNING,"qty - init - M_Product_ID=" + M_Product_ID); + BigDecimal QtyInvoiced, QtyEntered, PriceActual, PriceEntered; + + // No Product + if (M_Product_ID == 0) + { + QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); + mTab.setValue("QtyInvoiced", QtyEntered); + } + // UOM Changed - convert from Entered -> Product + else if (mField.getColumnName().equals("C_UOM_ID")) + { + int C_UOM_To_ID = ((Integer)value).intValue(); + QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); + BigDecimal QtyEntered1 = QtyEntered.setScale(MUOM.getPrecision(ctx, C_UOM_To_ID), BigDecimal.ROUND_HALF_UP); + if (QtyEntered.compareTo(QtyEntered1) != 0) + { + log.fine("Corrected QtyEntered Scale UOM=" + C_UOM_To_ID + + "; QtyEntered=" + QtyEntered + "->" + QtyEntered1); + QtyEntered = QtyEntered1; + mTab.setValue("QtyEntered", QtyEntered); + } + QtyInvoiced = MUOMConversion.convertProductFrom (ctx, M_Product_ID, + C_UOM_To_ID, QtyEntered); + if (QtyInvoiced == null) + QtyInvoiced = QtyEntered; + boolean conversion = QtyEntered.compareTo(QtyInvoiced) != 0; + PriceActual = (BigDecimal)mTab.getValue("PriceActual"); + PriceEntered = MUOMConversion.convertProductFrom (ctx, M_Product_ID, + C_UOM_To_ID, PriceActual); + if (PriceEntered == null) + PriceEntered = PriceActual; + log.fine("qty - UOM=" + C_UOM_To_ID + + ", QtyEntered/PriceActual=" + QtyEntered + "/" + PriceActual + + " -> " + conversion + + " QtyInvoiced/PriceEntered=" + QtyInvoiced + "/" + PriceEntered); + Env.setContext(ctx, WindowNo, "UOMConversion", conversion ? "Y" : "N"); + mTab.setValue("QtyInvoiced", QtyInvoiced); + mTab.setValue("PriceEntered", PriceEntered); + } + // QtyEntered changed - calculate QtyInvoiced + else if (mField.getColumnName().equals("QtyEntered")) + { + int C_UOM_To_ID = Env.getContextAsInt(ctx, WindowNo, "C_UOM_ID"); + QtyEntered = (BigDecimal)value; + BigDecimal QtyEntered1 = QtyEntered.setScale(MUOM.getPrecision(ctx, C_UOM_To_ID), BigDecimal.ROUND_HALF_UP); + if (QtyEntered.compareTo(QtyEntered1) != 0) + { + log.fine("Corrected QtyEntered Scale UOM=" + C_UOM_To_ID + + "; QtyEntered=" + QtyEntered + "->" + QtyEntered1); + QtyEntered = QtyEntered1; + mTab.setValue("QtyEntered", QtyEntered); + } + QtyInvoiced = MUOMConversion.convertProductFrom (ctx, M_Product_ID, + C_UOM_To_ID, QtyEntered); + if (QtyInvoiced == null) + QtyInvoiced = QtyEntered; + boolean conversion = QtyEntered.compareTo(QtyInvoiced) != 0; + log.fine("qty - UOM=" + C_UOM_To_ID + + ", QtyEntered=" + QtyEntered + + " -> " + conversion + + " QtyInvoiced=" + QtyInvoiced); + Env.setContext(ctx, WindowNo, "UOMConversion", conversion ? "Y" : "N"); + mTab.setValue("QtyInvoiced", QtyInvoiced); + } + // QtyInvoiced changed - calculate QtyEntered (should not happen) + else if (mField.getColumnName().equals("QtyInvoiced")) + { + int C_UOM_To_ID = Env.getContextAsInt(ctx, WindowNo, "C_UOM_ID"); + QtyInvoiced = (BigDecimal)value; + int precision = MProduct.get(ctx, M_Product_ID).getUOMPrecision(); + BigDecimal QtyInvoiced1 = QtyInvoiced.setScale(precision, BigDecimal.ROUND_HALF_UP); + if (QtyInvoiced.compareTo(QtyInvoiced1) != 0) + { + log.fine("Corrected QtyInvoiced Scale " + + QtyInvoiced + "->" + QtyInvoiced1); + QtyInvoiced = QtyInvoiced1; + mTab.setValue("QtyInvoiced", QtyInvoiced); + } + QtyEntered = MUOMConversion.convertProductTo (ctx, M_Product_ID, + C_UOM_To_ID, QtyInvoiced); + if (QtyEntered == null) + QtyEntered = QtyInvoiced; + boolean conversion = QtyInvoiced.compareTo(QtyEntered) != 0; + log.fine("qty - UOM=" + C_UOM_To_ID + + ", QtyInvoiced=" + QtyInvoiced + + " -> " + conversion + + " QtyEntered=" + QtyEntered); + Env.setContext(ctx, WindowNo, "UOMConversion", conversion ? "Y" : "N"); + mTab.setValue("QtyEntered", QtyEntered); + } + // + setCalloutActive(false); + return ""; + } // qty + + +} // CalloutInvoice diff --git a/base/src/org/compiere/model/CalloutInvoiceBatch.java b/base/src/org/compiere/model/CalloutInvoiceBatch.java new file mode 100644 index 0000000000..e57759ebaf --- /dev/null +++ b/base/src/org/compiere/model/CalloutInvoiceBatch.java @@ -0,0 +1,393 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Callouts for Invoice Batch + * + * @author Jorg Janke + * @version $Id: CalloutInvoiceBatch.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class CalloutInvoiceBatch extends CalloutEngine +{ + /** + * Invoice Batch Line - DateInvoiced. + * - updates DateAcct + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String date (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (value == null) + return ""; + mTab.setValue ("DateAcct", value); + // + setDocumentNo(ctx, WindowNo, mTab); + return ""; + } // date + + + + /** + * Invoice Batch Line - BPartner. + * - C_BPartner_Location_ID + * - AD_User_ID + * - PaymentRule + * - C_PaymentTerm_ID + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String bPartner (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_BPartner_ID = (Integer)value; + if (C_BPartner_ID == null || C_BPartner_ID.intValue() == 0) + return ""; + + String sql = "SELECT p.AD_Language,p.C_PaymentTerm_ID," + + " COALESCE(p.M_PriceList_ID,g.M_PriceList_ID) AS M_PriceList_ID, p.PaymentRule,p.POReference," + + " 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 " + + "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')" + + " LEFT OUTER JOIN AD_User c ON (p.C_BPartner_ID=c.C_BPartner_ID) " + + "WHERE p.C_BPartner_ID=? AND p.IsActive='Y'"; // #1 + + boolean IsSOTrx = Env.getContext(ctx, WindowNo, "IsSOTrx").equals("Y"); + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_BPartner_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + // + if (rs.next()) + { + // PaymentRule + String s = rs.getString(IsSOTrx ? "PaymentRule" : "PaymentRulePO"); + if (s != null && s.length() != 0) + { + if (Env.getContext(ctx, WindowNo, "DocBaseType").endsWith("C")) // Credits are Payment Term + s = "P"; + else if (IsSOTrx && (s.equals("S") || s.equals("U"))) // No Check/Transfer for SO_Trx + s = "P"; // Payment Term + // mTab.setValue("PaymentRule", s); + } + // Payment Term + Integer ii = new Integer(rs.getInt(IsSOTrx ? "C_PaymentTerm_ID" : "PO_PaymentTerm_ID")); + if (!rs.wasNull()) + mTab.setValue("C_PaymentTerm_ID", ii); + + // Location + int locID = rs.getInt("C_BPartner_Location_ID"); + // overwritten by InfoBP selection - works only if InfoWindow + // was used otherwise creates error (uses last value, may belong to differnt BP) + if (C_BPartner_ID.toString().equals(Env.getContext(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_BPartner_ID"))) + { + String loc = Env.getContext(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_BPartner_Location_ID"); + if (loc.length() > 0) + locID = Integer.parseInt(loc); + } + if (locID == 0) + mTab.setValue("C_BPartner_Location_ID", null); + else + mTab.setValue("C_BPartner_Location_ID", new Integer(locID)); + + // Contact - overwritten by InfoBP selection + int contID = rs.getInt("AD_User_ID"); + if (C_BPartner_ID.toString().equals(Env.getContext(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_BPartner_ID"))) + { + String cont = Env.getContext(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "AD_User_ID"); + if (cont.length() > 0) + contID = Integer.parseInt(cont); + } + if (contID == 0) + mTab.setValue("AD_User_ID", null); + else + mTab.setValue("AD_User_ID", new Integer(contID)); + + // CreditAvailable + if (IsSOTrx) + { + double CreditLimit = rs.getDouble("SO_CreditLimit"); + if (CreditLimit != 0) + { + double CreditAvailable = rs.getDouble("CreditAvailable"); + if (!rs.wasNull() && CreditAvailable < 0) + mTab.fireDataStatusEEvent("CreditLimitOver", + DisplayType.getNumberFormat(DisplayType.Amount).format(CreditAvailable), + false); + } + } + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + return e.getLocalizedMessage(); + } + // + setDocumentNo(ctx, WindowNo, mTab); + return tax (ctx, WindowNo, mTab, mField, value); + } // bPartner + + /** + * Document Type. + * - called from DocType + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String docType (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + setDocumentNo(ctx, WindowNo, mTab); + return ""; + } // docType + + /** + * Set Document No (increase existing) + * @param ctx Context + * @param WindowNo current Window No + * @param mTab Model Tab + */ + private void setDocumentNo (Properties ctx, int WindowNo, GridTab mTab) + { + // Get last line + int C_InvoiceBatch_ID = Env.getContextAsInt(ctx, WindowNo, "C_InvoiceBatch_ID"); + String sql = "SELECT COALESCE(MAX(C_InvoiceBatchLine_ID),0) FROM C_InvoiceBatchLine WHERE C_InvoiceBatch_ID=?"; + int C_InvoiceBatchLine_ID = DB.getSQLValue(null, sql, C_InvoiceBatch_ID); + if (C_InvoiceBatchLine_ID == 0) + return; + MInvoiceBatchLine last = new MInvoiceBatchLine(Env.getCtx(), C_InvoiceBatchLine_ID, null); + + // Need to Increase when different DocType or BP + int C_DocType_ID = Env.getContextAsInt(ctx, WindowNo, "C_DocType_ID"); + int C_BPartner_ID = Env.getContextAsInt(ctx, WindowNo, "C_BPartner_ID"); + if (C_DocType_ID == last.getC_DocType_ID() + && C_BPartner_ID == last.getC_BPartner_ID()) + return; + + // New Number + String oldDocNo = last.getDocumentNo(); + if (oldDocNo == null) + return; + int docNo = 0; + try + { + docNo = Integer.parseInt(oldDocNo); + } + catch (Exception e) + { + } + if (docNo == 0) + return; + String newDocNo = String.valueOf(docNo+1); + mTab.setValue("DocumentNo", newDocNo); + } // setDocumentNo + + /** + * Invoice Batch Line - Charge. + * - updates PriceEntered from Charge + * Calles tax + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String charge (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_Charge_ID = (Integer)value; + if (C_Charge_ID == null || C_Charge_ID.intValue() == 0) + return ""; + + String sql = "SELECT ChargeAmt FROM C_Charge WHERE C_Charge_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_Charge_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + mTab.setValue ("PriceEntered", rs.getBigDecimal (1)); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + return e.getLocalizedMessage(); + } + // + return tax (ctx, WindowNo, mTab, mField, value); + } // charge + + /** + * Invoice Line - Tax. + * - basis: Charge, BPartner Location + * - sets C_Tax_ID + * Calles Amount + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String tax (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + String column = mField.getColumnName(); + if (value == null) + return ""; + + int C_Charge_ID = 0; + if (column.equals("C_Charge_ID")) + C_Charge_ID = ((Integer)value).intValue(); + else + C_Charge_ID = Env.getContextAsInt(ctx, WindowNo, "C_Charge_ID"); + log.fine("C_Charge_ID=" + C_Charge_ID); + if (C_Charge_ID == 0) + return amt (ctx, WindowNo, mTab, mField, value); // + + // Check Partner Location + int C_BPartner_Location_ID = Env.getContextAsInt(ctx, WindowNo, "C_BPartner_Location_ID"); + if (C_BPartner_Location_ID == 0) + return amt (ctx, WindowNo, mTab, mField, value); // + log.fine("BP_Location=" + C_BPartner_Location_ID); + + // Dates + Timestamp billDate = Env.getContextAsDate(ctx, WindowNo, "DateInvoiced"); + log.fine("Bill Date=" + billDate); + Timestamp shipDate = billDate; + log.fine("Ship Date=" + shipDate); + + int AD_Org_ID = Env.getContextAsInt(ctx, WindowNo, "AD_Org_ID"); + log.fine("Org=" + AD_Org_ID); + + int M_Warehouse_ID = Env.getContextAsInt(ctx, "#M_Warehouse_ID"); + log.fine("Warehouse=" + M_Warehouse_ID); + + // + int C_Tax_ID = Tax.get(ctx, 0, C_Charge_ID, billDate, shipDate, + AD_Org_ID, M_Warehouse_ID, C_BPartner_Location_ID, C_BPartner_Location_ID, + Env.getContext(ctx, WindowNo, "IsSOTrx").equals("Y")); + log.info("Tax ID=" + C_Tax_ID); + // + if (C_Tax_ID == 0) + mTab.fireDataStatusEEvent(CLogger.retrieveError()); + else + mTab.setValue("C_Tax_ID", new Integer(C_Tax_ID)); + // + return amt (ctx, WindowNo, mTab, mField, value); + } // tax + + + /** + * Invoice - Amount. + * - called from QtyEntered, PriceEntered + * - calculates LineNetAmt + * @param ctx context + * @param WindowNo window no + * @param mTab tab + * @param mField field + * @param value value + * @return null or error message + */ + public String amt (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive() || value == null) + return ""; + setCalloutActive(true); + + int StdPrecision = 2; // temporary + + // get values + BigDecimal QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); + BigDecimal PriceEntered = (BigDecimal)mTab.getValue("PriceEntered"); + log.fine("QtyEntered=" + QtyEntered + ", PriceEntered=" + PriceEntered); + if (QtyEntered == null) + QtyEntered = Env.ZERO; + if (PriceEntered == null) + PriceEntered = Env.ZERO; + + // Line Net Amt + BigDecimal LineNetAmt = QtyEntered.multiply(PriceEntered); + if (LineNetAmt.scale() > StdPrecision) + LineNetAmt = LineNetAmt.setScale(StdPrecision, BigDecimal.ROUND_HALF_UP); + + // Calculate Tax Amount + boolean IsSOTrx = "Y".equals(Env.getContext(Env.getCtx(), WindowNo, "IsSOTrx")); + boolean IsTaxIncluded = "Y".equals(Env.getContext(Env.getCtx(), WindowNo, "IsTaxIncluded")); + + BigDecimal TaxAmt = null; + if (mField.getColumnName().equals("TaxAmt")) + { + TaxAmt = (BigDecimal)mTab.getValue("TaxAmt"); + } + else + { + Integer taxID = (Integer)mTab.getValue("C_Tax_ID"); + if (taxID != null) + { + int C_Tax_ID = taxID.intValue(); + MTax tax = new MTax (ctx, C_Tax_ID, null); + TaxAmt = tax.calculateTax(LineNetAmt, IsTaxIncluded, StdPrecision); + mTab.setValue("TaxAmt", TaxAmt); + } + } + + // + if (IsTaxIncluded) + { + mTab.setValue("LineTotalAmt", LineNetAmt); + mTab.setValue("LineNetAmt", LineNetAmt.subtract(TaxAmt)); + } + else + { + mTab.setValue("LineNetAmt", LineNetAmt); + mTab.setValue("LineTotalAmt", LineNetAmt.add(TaxAmt)); + } + setCalloutActive(false); + return ""; + } // amt + + + +} // CalloutInvoiceBatch diff --git a/base/src/org/compiere/model/CalloutMovement.java b/base/src/org/compiere/model/CalloutMovement.java new file mode 100644 index 0000000000..6f05b64103 --- /dev/null +++ b/base/src/org/compiere/model/CalloutMovement.java @@ -0,0 +1,55 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.util.*; +import org.compiere.util.*; + +/** + * Inventory Movement Callouts + * + * @author Jorg Janke + * @version $Id: CalloutMovement.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class CalloutMovement extends CalloutEngine +{ + /** + * Product modified + * Set Attribute Set Instance + * + * @param ctx Context + * @param WindowNo current Window No + * @param mTab Model Tab + * @param mField Model Field + * @param value The new value + * @return Error message or "" + */ + public String product (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer M_Product_ID = (Integer)value; + if (M_Product_ID == null || M_Product_ID.intValue() == 0) + return ""; + // Set Attribute + if (Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_Product_ID") == M_Product_ID.intValue() + && Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_AttributeSetInstance_ID") != 0) + mTab.setValue("M_AttributeSetInstance_ID", new Integer(Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_AttributeSetInstance_ID"))); + else + mTab.setValue("M_AttributeSetInstance_ID", null); + return ""; + } // product + +} // CalloutMove diff --git a/base/src/org/compiere/model/CalloutOrder.java b/base/src/org/compiere/model/CalloutOrder.java new file mode 100644 index 0000000000..622a8bccee --- /dev/null +++ b/base/src/org/compiere/model/CalloutOrder.java @@ -0,0 +1,1188 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Order Callouts. + * + * @author Jorg Janke + * @version $Id: CalloutOrder.java,v 1.5 2006/10/08 06:57:33 comdivision Exp $ + */ +public class CalloutOrder extends CalloutEngine +{ + /** Debug Steps */ + private boolean steps = false; + + /** + * Order Header Change - DocType. + * - InvoiceRuld/DeliveryRule/PaymentRule + * - temporary Document + * Context: + * - DocSubTypeSO + * - HasCharges + * - (re-sets Business Partner info of required) + * + * @param ctx Context + * @param WindowNo current Window No + * @param mTab Model Tab + * @param mField Model Field + * @param value The new value + * @return Error message or "" + */ + public String docType (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_DocType_ID = (Integer)value; // Actually C_DocTypeTarget_ID + if (C_DocType_ID == null || C_DocType_ID.intValue() == 0) + return ""; + + // Re-Create new DocNo, if there is a doc number already + // and the existing source used a different Sequence number + String oldDocNo = (String)mTab.getValue("DocumentNo"); + boolean newDocNo = (oldDocNo == null); + if (!newDocNo && oldDocNo.startsWith("<") && oldDocNo.endsWith(">")) + newDocNo = true; + Integer oldC_DocType_ID = (Integer)mTab.getValue("C_DocType_ID"); + + String sql = "SELECT d.DocSubTypeSO,d.HasCharges,'N'," // 1..3 + + "d.IsDocNoControlled,s.CurrentNext,s.CurrentNextSys," // 4..6 + + "s.AD_Sequence_ID,d.IsSOTrx " // 7..8 + + "FROM C_DocType d, AD_Sequence s " + + "WHERE C_DocType_ID=?" // #1 + + " AND d.DocNoSequence_ID=s.AD_Sequence_ID(+)"; + try + { + int AD_Sequence_ID = 0; + + // Get old AD_SeqNo for comparison + if (!newDocNo && oldC_DocType_ID.intValue() != 0) + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, oldC_DocType_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + AD_Sequence_ID = rs.getInt(6); + rs.close(); + pstmt.close(); + } + + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_DocType_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + String DocSubTypeSO = ""; + boolean IsSOTrx = true; + if (rs.next()) // we found document type + { + // Set Context: Document Sub Type for Sales Orders + DocSubTypeSO = rs.getString(1); + if (DocSubTypeSO == null) + DocSubTypeSO = "--"; + Env.setContext(ctx, WindowNo, "OrderType", DocSubTypeSO); + // No Drop Ship other than Standard + if (!DocSubTypeSO.equals(MOrder.DocSubTypeSO_Standard)) + mTab.setValue ("IsDropShip", "N"); + + // Delivery Rule + if (DocSubTypeSO.equals(MOrder.DocSubTypeSO_POS)) + mTab.setValue ("DeliveryRule", MOrder.DELIVERYRULE_Force); + else if (DocSubTypeSO.equals(MOrder.DocSubTypeSO_Prepay)) + mTab.setValue ("DeliveryRule", MOrder.DELIVERYRULE_AfterReceipt); + else + mTab.setValue ("DeliveryRule", MOrder.DELIVERYRULE_Availability); + + // Invoice Rule + if (DocSubTypeSO.equals(MOrder.DocSubTypeSO_POS) + || DocSubTypeSO.equals(MOrder.DocSubTypeSO_Prepay) + || DocSubTypeSO.equals(MOrder.DocSubTypeSO_OnCredit) ) + mTab.setValue ("InvoiceRule", MOrder.INVOICERULE_Immediate); + else + mTab.setValue ("InvoiceRule", MOrder.INVOICERULE_AfterDelivery); + + // Payment Rule - POS Order + if (DocSubTypeSO.equals(MOrder.DocSubTypeSO_POS)) + mTab.setValue("PaymentRule", MOrder.PAYMENTRULE_Cash); + else + mTab.setValue("PaymentRule", MOrder.PAYMENTRULE_OnCredit); + + // IsSOTrx + if ("N".equals(rs.getString(8))) + IsSOTrx = false; + + // Set Context: + Env.setContext(ctx, WindowNo, "HasCharges", rs.getString(2)); + // DocumentNo + if (rs.getString(4).equals("Y")) // IsDocNoControlled + { + if (!newDocNo && AD_Sequence_ID != rs.getInt(7)) + newDocNo = true; + if (newDocNo) + if (Ini.isPropertyBool(Ini.P_ADEMPIERESYS) && Env.getAD_Client_ID(Env.getCtx()) < 1000000) + mTab.setValue("DocumentNo", "<" + rs.getString(6) + ">"); + else + mTab.setValue("DocumentNo", "<" + rs.getString(5) + ">"); + } + } + rs.close(); + pstmt.close(); + // When BPartner is changed, the Rules are not set if + // it is a POS or Credit Order (i.e. defaults from Standard BPartner) + // This re-reads the Rules and applies them. + if (DocSubTypeSO.equals(MOrder.DocSubTypeSO_POS) + || DocSubTypeSO.equals(MOrder.DocSubTypeSO_Prepay)) // not for POS/PrePay + ; + else + { + sql = "SELECT PaymentRule,C_PaymentTerm_ID," // 1..2 + + "InvoiceRule,DeliveryRule," // 3..4 + + "FreightCostRule,DeliveryViaRule, " // 5..6 + + "PaymentRulePO,PO_PaymentTerm_ID " + + "FROM C_BPartner " + + "WHERE C_BPartner_ID=?"; // #1 + pstmt = DB.prepareStatement(sql, null); + int C_BPartner_ID = Env.getContextAsInt(ctx, WindowNo, "C_BPartner_ID"); + pstmt.setInt(1, C_BPartner_ID); + // + rs = pstmt.executeQuery(); + if (rs.next()) + { + // PaymentRule + String s = rs.getString(IsSOTrx ? "PaymentRule" : "PaymentRulePO"); + if (s != null && s.length() != 0) + { + if (IsSOTrx && (s.equals("B") || s.equals("S") || s.equals("U"))) // No Cash/Check/Transfer for SO_Trx + s = "P"; // Payment Term + if (!IsSOTrx && (s.equals("B"))) // No Cash for PO_Trx + s = "P"; // Payment Term + mTab.setValue("PaymentRule", s); + } + // Payment Term + Integer ii =new Integer(rs.getInt(IsSOTrx ? "C_PaymentTerm_ID" : "PO_PaymentTerm_ID")); + if (!rs.wasNull()) + mTab.setValue("C_PaymentTerm_ID", ii); + // InvoiceRule + s = rs.getString(3); + if (s != null && s.length() != 0) + mTab.setValue("InvoiceRule", s); + // DeliveryRule + s = rs.getString(4); + if (s != null && s.length() != 0) + mTab.setValue("DeliveryRule", s); + // FreightCostRule + s = rs.getString(5); + if (s != null && s.length() != 0) + mTab.setValue("FreightCostRule", s); + // DeliveryViaRule + s = rs.getString(6); + if (s != null && s.length() != 0) + mTab.setValue("DeliveryViaRule", s); + } + rs.close(); + pstmt.close(); + } // re-read customer rules + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + return e.getLocalizedMessage(); + } + + return ""; + } // docType + + + /** + * Order Header - BPartner. + * - M_PriceList_ID (+ Context) + * - C_BPartner_Location_ID + * - Bill_BPartner_ID/Bill_Location_ID + * - AD_User_ID + * - POReference + * - SO_Description + * - IsDiscountPrinted + * - InvoiceRule/DeliveryRule/PaymentRule/FreightCost/DeliveryViaRule + * - C_PaymentTerm_ID + * @param ctx Context + * @param WindowNo current Window No + * @param mTab Model Tab + * @param mField Model Field + * @param value The new value + * @return Error message or "" + */ + public String bPartner (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_BPartner_ID = (Integer)value; + if (C_BPartner_ID == null || C_BPartner_ID.intValue() == 0) + return ""; + setCalloutActive(true); + + String sql = "SELECT p.AD_Language,p.C_PaymentTerm_ID," + + " COALESCE(p.M_PriceList_ID,g.M_PriceList_ID) AS M_PriceList_ID, p.PaymentRule,p.POReference," + + " p.SO_Description,p.IsDiscountPrinted," + + " p.InvoiceRule,p.DeliveryRule,p.FreightCostRule,DeliveryViaRule," + + " p.SO_CreditLimit, p.SO_CreditLimit-p.SO_CreditUsed AS CreditAvailable," + + " lship.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," + + " lbill.C_BPartner_Location_ID AS Bill_Location_ID, p.SOCreditStatus " + + "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 lbill ON (p.C_BPartner_ID=lbill.C_BPartner_ID AND lbill.IsBillTo='Y' AND lbill.IsActive='Y')" + + " LEFT OUTER JOIN C_BPartner_Location lship ON (p.C_BPartner_ID=lship.C_BPartner_ID AND lship.IsShipTo='Y' AND lship.IsActive='Y')" + + " LEFT OUTER JOIN AD_User c ON (p.C_BPartner_ID=c.C_BPartner_ID) " + + "WHERE p.C_BPartner_ID=? AND p.IsActive='Y'"; // #1 + + boolean IsSOTrx = "Y".equals(Env.getContext(ctx, WindowNo, "IsSOTrx")); + + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_BPartner_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + // PriceList (indirect: IsTaxIncluded & Currency) + Integer ii = new Integer(rs.getInt(IsSOTrx ? "M_PriceList_ID" : "PO_PriceList_ID")); + if (!rs.wasNull()) + mTab.setValue("M_PriceList_ID", ii); + else + { // get default PriceList + int i = Env.getContextAsInt(ctx, "#M_PriceList_ID"); + if (i != 0) + mTab.setValue("M_PriceList_ID", new Integer(i)); + } + + // Bill-To + mTab.setValue("Bill_BPartner_ID", C_BPartner_ID); + int bill_Location_ID = rs.getInt("Bill_Location_ID"); + if (bill_Location_ID == 0) + mTab.setValue("Bill_Location_ID", null); + else + mTab.setValue("Bill_Location_ID", new Integer(bill_Location_ID)); + // Ship-To Location + int shipTo_ID = rs.getInt("C_BPartner_Location_ID"); + // overwritten by InfoBP selection - works only if InfoWindow + // was used otherwise creates error (uses last value, may belong to differnt BP) + if (C_BPartner_ID.toString().equals(Env.getContext(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_BPartner_ID"))) + { + String loc = Env.getContext(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_BPartner_Location_ID"); + if (loc.length() > 0) + shipTo_ID = Integer.parseInt(loc); + } + if (shipTo_ID == 0) + mTab.setValue("C_BPartner_Location_ID", null); + else + mTab.setValue("C_BPartner_Location_ID", new Integer(shipTo_ID)); + + // Contact - overwritten by InfoBP selection + int contID = rs.getInt("AD_User_ID"); + if (C_BPartner_ID.toString().equals(Env.getContext(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_BPartner_ID"))) + { + String cont = Env.getContext(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "AD_User_ID"); + if (cont.length() > 0) + contID = Integer.parseInt(cont); + } + if (contID == 0) + mTab.setValue("AD_User_ID", null); + else + { + mTab.setValue("AD_User_ID", new Integer(contID)); + mTab.setValue("Bill_User_ID", new Integer(contID)); + } + + // CreditAvailable + if (IsSOTrx) + { + double CreditLimit = rs.getDouble("SO_CreditLimit"); + String SOCreditStatus = rs.getString("SOCreditStatus"); + if (CreditLimit != 0) + { + double CreditAvailable = rs.getDouble("CreditAvailable"); + if (!rs.wasNull() && CreditAvailable < 0) + mTab.fireDataStatusEEvent("CreditLimitOver", + DisplayType.getNumberFormat(DisplayType.Amount).format(CreditAvailable), + false); + } + } + + // PO Reference + String s = rs.getString("POReference"); + if (s != null && s.length() != 0) + mTab.setValue("POReference", s); + // should not be reset to null if we entered already value! VHARCQ, accepted YS makes sense that way + // TODO: should get checked and removed if no longer needed! + /*else + mTab.setValue("POReference", null);*/ + + // SO Description + s = rs.getString("SO_Description"); + if (s != null && s.trim().length() != 0) + mTab.setValue("Description", s); + // IsDiscountPrinted + s = rs.getString("IsDiscountPrinted"); + if (s != null && s.length() != 0) + mTab.setValue("IsDiscountPrinted", s); + else + mTab.setValue("IsDiscountPrinted", "N"); + + // Defaults, if not Walkin Receipt or Walkin Invoice + String OrderType = Env.getContext(ctx, WindowNo, "OrderType"); + mTab.setValue("InvoiceRule", MOrder.INVOICERULE_AfterDelivery); + mTab.setValue("DeliveryRule", MOrder.DELIVERYRULE_Availability); + mTab.setValue("PaymentRule", MOrder.PAYMENTRULE_OnCredit); + if (OrderType.equals(MOrder.DocSubTypeSO_Prepay)) + { + mTab.setValue("InvoiceRule", MOrder.INVOICERULE_Immediate); + mTab.setValue("DeliveryRule", MOrder.DELIVERYRULE_AfterReceipt); + } + else if (OrderType.equals(MOrder.DocSubTypeSO_POS)) // for POS + mTab.setValue("PaymentRule", MOrder.PAYMENTRULE_Cash); + else + { + // PaymentRule + s = rs.getString(IsSOTrx ? "PaymentRule" : "PaymentRulePO"); + if (s != null && s.length() != 0) + { + if (s.equals("B")) // No Cache in Non POS + s = "P"; + if (IsSOTrx && (s.equals("S") || s.equals("U"))) // No Check/Transfer for SO_Trx + s = "P"; // Payment Term + mTab.setValue("PaymentRule", s); + } + // Payment Term + ii = new Integer(rs.getInt(IsSOTrx ? "C_PaymentTerm_ID" : "PO_PaymentTerm_ID")); + if (!rs.wasNull()) + mTab.setValue("C_PaymentTerm_ID", ii); + // InvoiceRule + s = rs.getString("InvoiceRule"); + if (s != null && s.length() != 0) + mTab.setValue("InvoiceRule", s); + // DeliveryRule + s = rs.getString("DeliveryRule"); + if (s != null && s.length() != 0) + mTab.setValue("DeliveryRule", s); + // FreightCostRule + s = rs.getString("FreightCostRule"); + if (s != null && s.length() != 0) + mTab.setValue("FreightCostRule", s); + // DeliveryViaRule + s = rs.getString("DeliveryViaRule"); + if (s != null && s.length() != 0) + mTab.setValue("DeliveryViaRule", s); + } + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + setCalloutActive(false); + return e.getLocalizedMessage(); + } + setCalloutActive(false); + return ""; + } // bPartner + + /** + * Order Header - Invoice BPartner. + * - M_PriceList_ID (+ Context) + * - Bill_Location_ID + * - Bill_User_ID + * - POReference + * - SO_Description + * - IsDiscountPrinted + * - InvoiceRule/PaymentRule + * - C_PaymentTerm_ID + * @param ctx Context + * @param WindowNo current Window No + * @param mTab Model Tab + * @param mField Model Field + * @param value The new value + * @return Error message or "" + */ + public String bPartnerBill (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive()) + return ""; + Integer bill_BPartner_ID = (Integer)value; + if (bill_BPartner_ID == null || bill_BPartner_ID.intValue() == 0) + return ""; + + String sql = "SELECT p.AD_Language,p.C_PaymentTerm_ID," + + "p.M_PriceList_ID,p.PaymentRule,p.POReference," + + "p.SO_Description,p.IsDiscountPrinted," + + "p.InvoiceRule,p.DeliveryRule,p.FreightCostRule,DeliveryViaRule," + + "p.SO_CreditLimit, p.SO_CreditLimit-p.SO_CreditUsed AS CreditAvailable," + + "c.AD_User_ID," + + "p.PO_PriceList_ID, p.PaymentRulePO, p.PO_PaymentTerm_ID," + + "lbill.C_BPartner_Location_ID AS Bill_Location_ID " + + "FROM C_BPartner p" + + " LEFT OUTER JOIN C_BPartner_Location lbill ON (p.C_BPartner_ID=lbill.C_BPartner_ID AND lbill.IsBillTo='Y' AND lbill.IsActive='Y')" + + " LEFT OUTER JOIN AD_User c ON (p.C_BPartner_ID=c.C_BPartner_ID) " + + "WHERE p.C_BPartner_ID=? AND p.IsActive='Y'"; // #1 + + boolean IsSOTrx = "Y".equals(Env.getContext(ctx, WindowNo, "IsSOTrx")); + + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, bill_BPartner_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + // PriceList (indirect: IsTaxIncluded & Currency) + Integer ii = new Integer(rs.getInt(IsSOTrx ? "M_PriceList_ID" : "PO_PriceList_ID")); + if (!rs.wasNull()) + mTab.setValue("M_PriceList_ID", ii); + else + { // get default PriceList + int i = Env.getContextAsInt(ctx, "#M_PriceList_ID"); + if (i != 0) + mTab.setValue("M_PriceList_ID", new Integer(i)); + } + + int bill_Location_ID = rs.getInt("Bill_Location_ID"); + // overwritten by InfoBP selection - works only if InfoWindow + // was used otherwise creates error (uses last value, may belong to differnt BP) + if (bill_BPartner_ID.toString().equals(Env.getContext(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_BPartner_ID"))) + { + String loc = Env.getContext(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_BPartner_Location_ID"); + if (loc.length() > 0) + bill_Location_ID = Integer.parseInt(loc); + } + if (bill_Location_ID == 0) + mTab.setValue("Bill_Location_ID", null); + else + mTab.setValue("Bill_Location_ID", new Integer(bill_Location_ID)); + + // Contact - overwritten by InfoBP selection + int contID = rs.getInt("AD_User_ID"); + if (bill_BPartner_ID.toString().equals(Env.getContext(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_BPartner_ID"))) + { + String cont = Env.getContext(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "AD_User_ID"); + if (cont.length() > 0) + contID = Integer.parseInt(cont); + } + if (contID == 0) + mTab.setValue("Bill_User_ID", null); + else + mTab.setValue("Bill_User_ID", new Integer(contID)); + + // CreditAvailable + if (IsSOTrx) + { + double CreditLimit = rs.getDouble("SO_CreditLimit"); + if (CreditLimit != 0) + { + double CreditAvailable = rs.getDouble("CreditAvailable"); + if (!rs.wasNull() && CreditAvailable < 0) + mTab.fireDataStatusEEvent("CreditLimitOver", + DisplayType.getNumberFormat(DisplayType.Amount).format(CreditAvailable), + false); + } + } + + // PO Reference + String s = rs.getString("POReference"); + if (s != null && s.length() != 0) + mTab.setValue("POReference", s); + else + mTab.setValue("POReference", null); + // SO Description + s = rs.getString("SO_Description"); + if (s != null && s.trim().length() != 0) + mTab.setValue("Description", s); + // IsDiscountPrinted + s = rs.getString("IsDiscountPrinted"); + if (s != null && s.length() != 0) + mTab.setValue("IsDiscountPrinted", s); + else + mTab.setValue("IsDiscountPrinted", "N"); + + // Defaults, if not Walkin Receipt or Walkin Invoice + String OrderType = Env.getContext(ctx, WindowNo, "OrderType"); + mTab.setValue("InvoiceRule", MOrder.INVOICERULE_AfterDelivery); + mTab.setValue("PaymentRule", MOrder.PAYMENTRULE_OnCredit); + if (OrderType.equals(MOrder.DocSubTypeSO_Prepay)) + mTab.setValue("InvoiceRule", MOrder.INVOICERULE_Immediate); + else if (OrderType.equals(MOrder.DocSubTypeSO_POS)) // for POS + mTab.setValue("PaymentRule", MOrder.PAYMENTRULE_Cash); + else + { + // PaymentRule + s = rs.getString(IsSOTrx ? "PaymentRule" : "PaymentRulePO"); + if (s != null && s.length() != 0) + { + if (s.equals("B")) // No Cache in Non POS + s = "P"; + if (IsSOTrx && (s.equals("S") || s.equals("U"))) // No Check/Transfer for SO_Trx + s = "P"; // Payment Term + mTab.setValue("PaymentRule", s); + } + // Payment Term + ii = new Integer(rs.getInt(IsSOTrx ? "C_PaymentTerm_ID" : "PO_PaymentTerm_ID")); + if (!rs.wasNull()) + mTab.setValue("C_PaymentTerm_ID", ii); + // InvoiceRule + s = rs.getString("InvoiceRule"); + if (s != null && s.length() != 0) + mTab.setValue("InvoiceRule", s); + } + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "bPartnerBill", e); + return e.getLocalizedMessage(); + } + + return ""; + } // bPartnerBill + + + /** + * Order Header - PriceList. + * (used also in Invoice) + * - C_Currency_ID + * - IsTaxIncluded + * Window Context: + * - EnforcePriceLimit + * - StdPrecision + * - M_PriceList_Version_ID + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String priceList (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer M_PriceList_ID = (Integer)value; + if (M_PriceList_ID == null || M_PriceList_ID.intValue()== 0) + return ""; + if (steps) log.warning("init"); + + String sql = "SELECT pl.IsTaxIncluded,pl.EnforcePriceLimit,pl.C_Currency_ID,c.StdPrecision," + + "plv.M_PriceList_Version_ID,plv.ValidFrom " + + "FROM M_PriceList pl,C_Currency c,M_PriceList_Version plv " + + "WHERE pl.C_Currency_ID=c.C_Currency_ID" + + " AND pl.M_PriceList_ID=plv.M_PriceList_ID" + + " AND pl.M_PriceList_ID=? " // 1 + + "ORDER BY plv.ValidFrom DESC"; + // Use newest price list - may not be future + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, M_PriceList_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + // Tax Included + mTab.setValue("IsTaxIncluded", new Boolean("Y".equals(rs.getString(1)))); + // Price Limit Enforce + Env.setContext(ctx, WindowNo, "EnforcePriceLimit", rs.getString(2)); + // Currency + Integer ii = new Integer(rs.getInt(3)); + mTab.setValue("C_Currency_ID", ii); + // PriceList Version + Env.setContext(ctx, WindowNo, "M_PriceList_Version_ID", rs.getInt(5)); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + return e.getLocalizedMessage(); + } + if (steps) log.warning("fini"); + + return ""; + } // priceList + + + /************************************************************************* + * Order Line - Product. + * - reset C_Charge_ID / M_AttributeSetInstance_ID + * - PriceList, PriceStd, PriceLimit, C_Currency_ID, EnforcePriceLimit + * - UOM + * Calls Tax + * + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String product (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer M_Product_ID = (Integer)value; + if (M_Product_ID == null || M_Product_ID.intValue() == 0) + return ""; + setCalloutActive(true); + if (steps) log.warning("init"); + // + mTab.setValue("C_Charge_ID", null); + // Set Attribute + if (Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_Product_ID") == M_Product_ID.intValue() + && Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_AttributeSetInstance_ID") != 0) + mTab.setValue("M_AttributeSetInstance_ID", new Integer(Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_AttributeSetInstance_ID"))); + else + mTab.setValue("M_AttributeSetInstance_ID", null); + + /***** Price Calculation see also qty ****/ + int C_BPartner_ID = Env.getContextAsInt(ctx, WindowNo, "C_BPartner_ID"); + BigDecimal Qty = (BigDecimal)mTab.getValue("QtyOrdered"); + boolean IsSOTrx = Env.getContext(ctx, WindowNo, "IsSOTrx").equals("Y"); + MProductPricing pp = new MProductPricing (M_Product_ID.intValue(), C_BPartner_ID, Qty, IsSOTrx); + // + int M_PriceList_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_ID"); + pp.setM_PriceList_ID(M_PriceList_ID); + /** PLV is only accurate if PL selected in header */ + int M_PriceList_Version_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_Version_ID"); + pp.setM_PriceList_Version_ID(M_PriceList_Version_ID); + Timestamp orderDate = (Timestamp)mTab.getValue("DateOrdered"); + pp.setPriceDate(orderDate); + // + mTab.setValue("PriceList", pp.getPriceList()); + mTab.setValue("PriceLimit", pp.getPriceLimit()); + mTab.setValue("PriceActual", pp.getPriceStd()); + mTab.setValue("PriceEntered", pp.getPriceStd()); + mTab.setValue("C_Currency_ID", new Integer(pp.getC_Currency_ID())); + mTab.setValue("Discount", pp.getDiscount()); + mTab.setValue("C_UOM_ID", new Integer(pp.getC_UOM_ID())); + mTab.setValue("QtyOrdered", mTab.getValue("QtyEntered")); + Env.setContext(ctx, WindowNo, "EnforcePriceLimit", pp.isEnforcePriceLimit() ? "Y" : "N"); + Env.setContext(ctx, WindowNo, "DiscountSchema", pp.isDiscountSchema() ? "Y" : "N"); + + // Check/Update Warehouse Setting + // int M_Warehouse_ID = Env.getContextAsInt(ctx, Env.WINDOW_INFO, "M_Warehouse_ID"); + // Integer wh = (Integer)mTab.getValue("M_Warehouse_ID"); + // if (wh.intValue() != M_Warehouse_ID) + // { + // mTab.setValue("M_Warehouse_ID", new Integer(M_Warehouse_ID)); + // ADialog.warn(,WindowNo, "WarehouseChanged"); + // } + + + if (Env.isSOTrx(ctx, WindowNo)) + { + MProduct product = MProduct.get (ctx, M_Product_ID.intValue()); + if (product.isStocked()) + { + BigDecimal QtyOrdered = (BigDecimal)mTab.getValue("QtyOrdered"); + int M_Warehouse_ID = Env.getContextAsInt(ctx, WindowNo, "M_Warehouse_ID"); + int M_AttributeSetInstance_ID = Env.getContextAsInt(ctx, WindowNo, "M_AttributeSetInstance_ID"); + BigDecimal available = MStorage.getQtyAvailable + (M_Warehouse_ID, M_Product_ID.intValue(), M_AttributeSetInstance_ID, null); + if (available == null) + available = Env.ZERO; + if (available.signum() == 0) + mTab.fireDataStatusEEvent ("NoQtyAvailable", "0", false); + else if (available.compareTo(QtyOrdered) < 0) + mTab.fireDataStatusEEvent ("InsufficientQtyAvailable", available.toString(), false); + else + { + Integer C_OrderLine_ID = (Integer)mTab.getValue("C_OrderLine_ID"); + if (C_OrderLine_ID == null) + C_OrderLine_ID = new Integer(0); + BigDecimal notReserved = MOrderLine.getNotReserved(ctx, + M_Warehouse_ID, M_Product_ID, M_AttributeSetInstance_ID, + C_OrderLine_ID.intValue()); + if (notReserved == null) + notReserved = Env.ZERO; + BigDecimal total = available.subtract(notReserved); + if (total.compareTo(QtyOrdered) < 0) + { + String info = Msg.parseTranslation(ctx, "@QtyAvailable@=" + available + + " - @QtyNotReserved@=" + notReserved + " = " + total); + mTab.fireDataStatusEEvent ("InsufficientQtyAvailable", + info, false); + } + } + } + } + // + setCalloutActive(false); + if (steps) log.warning("fini"); + return tax (ctx, WindowNo, mTab, mField, value); + } // product + + /** + * Order Line - Charge. + * - updates PriceActual from Charge + * - sets PriceLimit, PriceList to zero + * Calles tax + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String charge (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_Charge_ID = (Integer)value; + if (C_Charge_ID == null || C_Charge_ID.intValue() == 0) + return ""; + // No Product defined + if (mTab.getValue("M_Product_ID") != null) + { + mTab.setValue("C_Charge_ID", null); + return "ChargeExclusively"; + } + mTab.setValue("M_AttributeSetInstance_ID", null); + mTab.setValue("S_ResourceAssignment_ID", null); + mTab.setValue("C_UOM_ID", new Integer(100)); // EA + + Env.setContext(ctx, WindowNo, "DiscountSchema", "N"); + String sql = "SELECT ChargeAmt FROM C_Charge WHERE C_Charge_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_Charge_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + mTab.setValue ("PriceEntered", rs.getBigDecimal (1)); + mTab.setValue ("PriceActual", rs.getBigDecimal (1)); + mTab.setValue ("PriceLimit", Env.ZERO); + mTab.setValue ("PriceList", Env.ZERO); + mTab.setValue ("Discount", Env.ZERO); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + return e.getLocalizedMessage(); + } + // + return tax (ctx, WindowNo, mTab, mField, value); + } // charge + + + /** + * Order Line - Tax. + * - basis: Product, Charge, BPartner Location + * - sets C_Tax_ID + * Calles Amount + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String tax (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + String column = mField.getColumnName(); + if (value == null) + return ""; + if (steps) log.warning("init"); + + // Check Product + int M_Product_ID = 0; + if (column.equals("M_Product_ID")) + M_Product_ID = ((Integer)value).intValue(); + else + M_Product_ID = Env.getContextAsInt(ctx, WindowNo, "M_Product_ID"); + int C_Charge_ID = 0; + if (column.equals("C_Charge_ID")) + C_Charge_ID = ((Integer)value).intValue(); + else + C_Charge_ID = Env.getContextAsInt(ctx, WindowNo, "C_Charge_ID"); + log.fine("Product=" + M_Product_ID + ", C_Charge_ID=" + C_Charge_ID); + if (M_Product_ID == 0 && C_Charge_ID == 0) + return amt(ctx, WindowNo, mTab, mField, value); // + + // Check Partner Location + int shipC_BPartner_Location_ID = 0; + if (column.equals("C_BPartner_Location_ID")) + shipC_BPartner_Location_ID = ((Integer)value).intValue(); + else + shipC_BPartner_Location_ID = Env.getContextAsInt(ctx, WindowNo, "C_BPartner_Location_ID"); + if (shipC_BPartner_Location_ID == 0) + return amt(ctx, WindowNo, mTab, mField, value); // + log.fine("Ship BP_Location=" + shipC_BPartner_Location_ID); + + // + Timestamp billDate = Env.getContextAsDate(ctx, WindowNo, "DateOrdered"); + log.fine("Bill Date=" + billDate); + + Timestamp shipDate = Env.getContextAsDate(ctx, WindowNo, "DatePromised"); + log.fine("Ship Date=" + shipDate); + + int AD_Org_ID = Env.getContextAsInt(ctx, WindowNo, "AD_Org_ID"); + log.fine("Org=" + AD_Org_ID); + + int M_Warehouse_ID = Env.getContextAsInt(ctx, WindowNo, "M_Warehouse_ID"); + log.fine("Warehouse=" + M_Warehouse_ID); + + int billC_BPartner_Location_ID = Env.getContextAsInt(ctx, WindowNo, "Bill_Location_ID"); + if (billC_BPartner_Location_ID == 0) + billC_BPartner_Location_ID = shipC_BPartner_Location_ID; + log.fine("Bill BP_Location=" + billC_BPartner_Location_ID); + + // + int C_Tax_ID = Tax.get (ctx, M_Product_ID, C_Charge_ID, billDate, shipDate, + AD_Org_ID, M_Warehouse_ID, billC_BPartner_Location_ID, shipC_BPartner_Location_ID, + "Y".equals(Env.getContext(ctx, WindowNo, "IsSOTrx"))); + log.info("Tax ID=" + C_Tax_ID); + // + if (C_Tax_ID == 0) + mTab.fireDataStatusEEvent(CLogger.retrieveError()); + else + mTab.setValue("C_Tax_ID", new Integer(C_Tax_ID)); + // + if (steps) log.warning("fini"); + return amt(ctx, WindowNo, mTab, mField, value); + } // tax + + + /** + * Order Line - Amount. + * - called from QtyOrdered, Discount and PriceActual + * - calculates Discount or Actual Amount + * - calculates LineNetAmt + * - enforces PriceLimit + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String amt (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive() || value == null) + return ""; + setCalloutActive(true); + + if (steps) log.warning("init"); + int C_UOM_To_ID = Env.getContextAsInt(ctx, WindowNo, "C_UOM_ID"); + int M_Product_ID = Env.getContextAsInt(ctx, WindowNo, "M_Product_ID"); + int M_PriceList_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_ID"); + int StdPrecision = MPriceList.getStandardPrecision(ctx, M_PriceList_ID); + BigDecimal QtyEntered, QtyOrdered, PriceEntered, PriceActual, PriceLimit, Discount, PriceList; + // get values + QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); + QtyOrdered = (BigDecimal)mTab.getValue("QtyOrdered"); + log.fine("QtyEntered=" + QtyEntered + ", Ordered=" + QtyOrdered + ", UOM=" + C_UOM_To_ID); + // + PriceEntered = (BigDecimal)mTab.getValue("PriceEntered"); + PriceActual = (BigDecimal)mTab.getValue("PriceActual"); + Discount = (BigDecimal)mTab.getValue("Discount"); + PriceLimit = (BigDecimal)mTab.getValue("PriceLimit"); + PriceList = (BigDecimal)mTab.getValue("PriceList"); + log.fine("PriceList=" + PriceList + ", Limit=" + PriceLimit + ", Precision=" + StdPrecision); + log.fine("PriceEntered=" + PriceEntered + ", Actual=" + PriceActual + ", Discount=" + Discount); + + // Qty changed - recalc price + if ((mField.getColumnName().equals("QtyOrdered") + || mField.getColumnName().equals("QtyEntered") + || mField.getColumnName().equals("M_Product_ID")) + && !"N".equals(Env.getContext(ctx, WindowNo, "DiscountSchema"))) + { + int C_BPartner_ID = Env.getContextAsInt(ctx, WindowNo, "C_BPartner_ID"); + if (mField.getColumnName().equals("QtyEntered")) + QtyOrdered = MUOMConversion.convertProductTo (ctx, M_Product_ID, + C_UOM_To_ID, QtyEntered); + if (QtyOrdered == null) + QtyOrdered = QtyEntered; + boolean IsSOTrx = Env.getContext(ctx, WindowNo, "IsSOTrx").equals("Y"); + MProductPricing pp = new MProductPricing (M_Product_ID, C_BPartner_ID, QtyOrdered, IsSOTrx); + pp.setM_PriceList_ID(M_PriceList_ID); + int M_PriceList_Version_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_Version_ID"); + pp.setM_PriceList_Version_ID(M_PriceList_Version_ID); + Timestamp date = (Timestamp)mTab.getValue("DateOrdered"); + pp.setPriceDate(date); + // + PriceEntered = MUOMConversion.convertProductFrom (ctx, M_Product_ID, + C_UOM_To_ID, pp.getPriceStd()); + if (PriceEntered == null) + PriceEntered = pp.getPriceStd(); + // + log.fine("QtyChanged -> PriceActual=" + pp.getPriceStd() + + ", PriceEntered=" + PriceEntered + ", Discount=" + pp.getDiscount()); + mTab.setValue("PriceActual", pp.getPriceStd()); + mTab.setValue("Discount", pp.getDiscount()); + mTab.setValue("PriceEntered", PriceEntered); + Env.setContext(ctx, WindowNo, "DiscountSchema", pp.isDiscountSchema() ? "Y" : "N"); + } + else if (mField.getColumnName().equals("PriceActual")) + { + PriceActual = (BigDecimal)value; + PriceEntered = MUOMConversion.convertProductFrom (ctx, M_Product_ID, + C_UOM_To_ID, PriceActual); + if (PriceEntered == null) + PriceEntered = PriceActual; + // + log.fine("PriceActual=" + PriceActual + + " -> PriceEntered=" + PriceEntered); + mTab.setValue("PriceEntered", PriceEntered); + } + else if (mField.getColumnName().equals("PriceEntered")) + { + PriceEntered = (BigDecimal)value; + PriceActual = MUOMConversion.convertProductTo (ctx, M_Product_ID, + C_UOM_To_ID, PriceEntered); + if (PriceActual == null) + PriceActual = PriceEntered; + // + log.fine("PriceEntered=" + PriceEntered + + " -> PriceActual=" + PriceActual); + mTab.setValue("PriceActual", PriceActual); + } + + // Discount entered - Calculate Actual/Entered + if (mField.getColumnName().equals("Discount")) + { + PriceActual = new BigDecimal ((100.0 - Discount.doubleValue()) / 100.0 * PriceList.doubleValue()); + if (PriceActual.scale() > StdPrecision) + PriceActual = PriceActual.setScale(StdPrecision, BigDecimal.ROUND_HALF_UP); + PriceEntered = MUOMConversion.convertProductFrom (ctx, M_Product_ID, + C_UOM_To_ID, PriceActual); + if (PriceEntered == null) + PriceEntered = PriceActual; + mTab.setValue("PriceActual", PriceActual); + mTab.setValue("PriceEntered", PriceEntered); + } + // calculate Discount + else + { + if (PriceList.intValue() == 0) + Discount = Env.ZERO; + else + Discount = new BigDecimal ((PriceList.doubleValue() - PriceActual.doubleValue()) / PriceList.doubleValue() * 100.0); + if (Discount.scale() > 2) + Discount = Discount.setScale(2, BigDecimal.ROUND_HALF_UP); + mTab.setValue("Discount", Discount); + } + log.fine("PriceEntered=" + PriceEntered + ", Actual=" + PriceActual + ", Discount=" + Discount); + + // Check PriceLimit + String epl = Env.getContext(ctx, WindowNo, "EnforcePriceLimit"); + boolean enforce = Env.isSOTrx(ctx, WindowNo) && epl != null && epl.equals("Y"); + if (enforce && MRole.getDefault().isOverwritePriceLimit()) + enforce = false; + // Check Price Limit? + if (enforce && PriceLimit.doubleValue() != 0.0 + && PriceActual.compareTo(PriceLimit) < 0) + { + PriceActual = PriceLimit; + PriceEntered = MUOMConversion.convertProductFrom (ctx, M_Product_ID, + C_UOM_To_ID, PriceLimit); + if (PriceEntered == null) + PriceEntered = PriceLimit; + log.fine("(under) PriceEntered=" + PriceEntered + ", Actual" + PriceLimit); + mTab.setValue ("PriceActual", PriceLimit); + mTab.setValue ("PriceEntered", PriceEntered); + mTab.fireDataStatusEEvent ("UnderLimitPrice", "", false); + // Repeat Discount calc + if (PriceList.intValue() != 0) + { + Discount = new BigDecimal ((PriceList.doubleValue () - PriceActual.doubleValue ()) / PriceList.doubleValue () * 100.0); + if (Discount.scale () > 2) + Discount = Discount.setScale (2, BigDecimal.ROUND_HALF_UP); + mTab.setValue ("Discount", Discount); + } + } + + // Line Net Amt + BigDecimal LineNetAmt = QtyOrdered.multiply(PriceActual); + if (LineNetAmt.scale() > StdPrecision) + LineNetAmt = LineNetAmt.setScale(StdPrecision, BigDecimal.ROUND_HALF_UP); + log.info("LineNetAmt=" + LineNetAmt); + mTab.setValue("LineNetAmt", LineNetAmt); + // + setCalloutActive(false); + return ""; + } // amt + + /** + * Order Line - Quantity. + * - called from C_UOM_ID, QtyEntered, QtyOrdered + * - enforces qty UOM relationship + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String qty (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive() || value == null) + return ""; + setCalloutActive(true); + + int M_Product_ID = Env.getContextAsInt(ctx, WindowNo, "M_Product_ID"); + if (steps) log.warning("init - M_Product_ID=" + M_Product_ID + " - " ); + BigDecimal QtyOrdered = Env.ZERO; + BigDecimal QtyEntered, PriceActual, PriceEntered; + + // No Product + if (M_Product_ID == 0) + { + QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); + QtyOrdered = QtyEntered; + mTab.setValue("QtyOrdered", QtyOrdered); + } + // UOM Changed - convert from Entered -> Product + else if (mField.getColumnName().equals("C_UOM_ID")) + { + int C_UOM_To_ID = ((Integer)value).intValue(); + QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); + BigDecimal QtyEntered1 = QtyEntered.setScale(MUOM.getPrecision(ctx, C_UOM_To_ID), BigDecimal.ROUND_HALF_UP); + if (QtyEntered.compareTo(QtyEntered1) != 0) + { + log.fine("Corrected QtyEntered Scale UOM=" + C_UOM_To_ID + + "; QtyEntered=" + QtyEntered + "->" + QtyEntered1); + QtyEntered = QtyEntered1; + mTab.setValue("QtyEntered", QtyEntered); + } + QtyOrdered = MUOMConversion.convertProductFrom (ctx, M_Product_ID, + C_UOM_To_ID, QtyEntered); + if (QtyOrdered == null) + QtyOrdered = QtyEntered; + boolean conversion = QtyEntered.compareTo(QtyOrdered) != 0; + PriceActual = (BigDecimal)mTab.getValue("PriceActual"); + PriceEntered = MUOMConversion.convertProductFrom (ctx, M_Product_ID, + C_UOM_To_ID, PriceActual); + if (PriceEntered == null) + PriceEntered = PriceActual; + log.fine("UOM=" + C_UOM_To_ID + + ", QtyEntered/PriceActual=" + QtyEntered + "/" + PriceActual + + " -> " + conversion + + " QtyOrdered/PriceEntered=" + QtyOrdered + "/" + PriceEntered); + Env.setContext(ctx, WindowNo, "UOMConversion", conversion ? "Y" : "N"); + mTab.setValue("QtyOrdered", QtyOrdered); + mTab.setValue("PriceEntered", PriceEntered); + } + // QtyEntered changed - calculate QtyOrdered + else if (mField.getColumnName().equals("QtyEntered")) + { + int C_UOM_To_ID = Env.getContextAsInt(ctx, WindowNo, "C_UOM_ID"); + QtyEntered = (BigDecimal)value; + BigDecimal QtyEntered1 = QtyEntered.setScale(MUOM.getPrecision(ctx, C_UOM_To_ID), BigDecimal.ROUND_HALF_UP); + if (QtyEntered.compareTo(QtyEntered1) != 0) + { + log.fine("Corrected QtyEntered Scale UOM=" + C_UOM_To_ID + + "; QtyEntered=" + QtyEntered + "->" + QtyEntered1); + QtyEntered = QtyEntered1; + mTab.setValue("QtyEntered", QtyEntered); + } + QtyOrdered = MUOMConversion.convertProductFrom (ctx, M_Product_ID, + C_UOM_To_ID, QtyEntered); + if (QtyOrdered == null) + QtyOrdered = QtyEntered; + boolean conversion = QtyEntered.compareTo(QtyOrdered) != 0; + log.fine("UOM=" + C_UOM_To_ID + + ", QtyEntered=" + QtyEntered + + " -> " + conversion + + " QtyOrdered=" + QtyOrdered); + Env.setContext(ctx, WindowNo, "UOMConversion", conversion ? "Y" : "N"); + mTab.setValue("QtyOrdered", QtyOrdered); + } + // QtyOrdered changed - calculate QtyEntered (should not happen) + else if (mField.getColumnName().equals("QtyOrdered")) + { + int C_UOM_To_ID = Env.getContextAsInt(ctx, WindowNo, "C_UOM_ID"); + QtyOrdered = (BigDecimal)value; + int precision = MProduct.get(ctx, M_Product_ID).getUOMPrecision(); + BigDecimal QtyOrdered1 = QtyOrdered.setScale(precision, BigDecimal.ROUND_HALF_UP); + if (QtyOrdered.compareTo(QtyOrdered1) != 0) + { + log.fine("Corrected QtyOrdered Scale " + + QtyOrdered + "->" + QtyOrdered1); + QtyOrdered = QtyOrdered1; + mTab.setValue("QtyOrdered", QtyOrdered); + } + QtyEntered = MUOMConversion.convertProductTo (ctx, M_Product_ID, + C_UOM_To_ID, QtyOrdered); + if (QtyEntered == null) + QtyEntered = QtyOrdered; + boolean conversion = QtyOrdered.compareTo(QtyEntered) != 0; + log.fine("UOM=" + C_UOM_To_ID + + ", QtyOrdered=" + QtyOrdered + + " -> " + conversion + + " QtyEntered=" + QtyEntered); + Env.setContext(ctx, WindowNo, "UOMConversion", conversion ? "Y" : "N"); + mTab.setValue("QtyEntered", QtyEntered); + } + else + { + // QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); + QtyOrdered = (BigDecimal)mTab.getValue("QtyOrdered"); + } + + // Storage + if (M_Product_ID != 0 + && Env.isSOTrx(ctx, WindowNo) + && QtyOrdered.signum() > 0) // no negative (returns) + { + MProduct product = MProduct.get (ctx, M_Product_ID); + if (product.isStocked()) + { + int M_Warehouse_ID = Env.getContextAsInt(ctx, WindowNo, "M_Warehouse_ID"); + int M_AttributeSetInstance_ID = Env.getContextAsInt(ctx, WindowNo, "M_AttributeSetInstance_ID"); + BigDecimal available = MStorage.getQtyAvailable + (M_Warehouse_ID, M_Product_ID, M_AttributeSetInstance_ID, null); + if (available == null) + available = Env.ZERO; + if (available.signum() == 0) + mTab.fireDataStatusEEvent ("NoQtyAvailable", "0", false); + else if (available.compareTo(QtyOrdered) < 0) + mTab.fireDataStatusEEvent ("InsufficientQtyAvailable", available.toString(), false); + else + { + Integer C_OrderLine_ID = (Integer)mTab.getValue("C_OrderLine_ID"); + if (C_OrderLine_ID == null) + C_OrderLine_ID = new Integer(0); + BigDecimal notReserved = MOrderLine.getNotReserved(ctx, + M_Warehouse_ID, M_Product_ID, M_AttributeSetInstance_ID, + C_OrderLine_ID.intValue()); + if (notReserved == null) + notReserved = Env.ZERO; + BigDecimal total = available.subtract(notReserved); + if (total.compareTo(QtyOrdered) < 0) + { + String info = Msg.parseTranslation(ctx, "@QtyAvailable@=" + available + + " - @QtyNotReserved@=" + notReserved + " = " + total); + mTab.fireDataStatusEEvent ("InsufficientQtyAvailable", + info, false); + } + } + } + } + // + setCalloutActive(false); + return ""; + } // qty + +} // CalloutOrder + diff --git a/base/src/org/compiere/model/CalloutPaySelection.java b/base/src/org/compiere/model/CalloutPaySelection.java new file mode 100644 index 0000000000..d18763b5c6 --- /dev/null +++ b/base/src/org/compiere/model/CalloutPaySelection.java @@ -0,0 +1,137 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Payment Selection Callouts + * + * @author Jorg Janke + * @version $Id: CalloutPaySelection.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class CalloutPaySelection extends CalloutEngine +{ + /** + * Payment Selection Line - Payment Amount. + * - called from C_PaySelectionLine.PayAmt + * - update DifferenceAmt + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String payAmt (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive() || value == null) + return ""; + // get invoice info + Integer ii = (Integer)mTab.getValue("C_Invoice_ID"); + if (ii == null) + return ""; + int C_Invoice_ID = ii.intValue(); + if (C_Invoice_ID == 0) + return ""; + // + BigDecimal OpenAmt = (BigDecimal)mTab.getValue("OpenAmt"); + BigDecimal PayAmt = (BigDecimal)mTab.getValue("PayAmt"); + BigDecimal DiscountAmt = (BigDecimal)mTab.getValue("DiscountAmt"); + setCalloutActive(true); + BigDecimal DifferenceAmt = OpenAmt.subtract(PayAmt).subtract(DiscountAmt); + log.fine(" - OpenAmt=" + OpenAmt + " - PayAmt=" + PayAmt + + ", Discount=" + DiscountAmt + ", Difference=" + DifferenceAmt); + + mTab.setValue("DifferenceAmt", DifferenceAmt); + + setCalloutActive(false); + return ""; + } // PaySel_PayAmt + + /** + * Payment Selection Line - Invoice. + * - called from C_PaySelectionLine.C_Invoice_ID + * - update PayAmt & DifferenceAmt + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String invoice (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive() || value == null) + return ""; + // get value + int C_Invoice_ID = ((Integer)value).intValue(); + if (C_Invoice_ID == 0) + return ""; + int C_BankAccount_ID = Env.getContextAsInt(ctx, WindowNo, "C_BankAccount_ID"); + Timestamp PayDate = Env.getContextAsDate(ctx, "PayDate"); + if (PayDate == null) + PayDate = new Timestamp(System.currentTimeMillis()); + setCalloutActive(true); + + BigDecimal OpenAmt = Env.ZERO; + BigDecimal DiscountAmt = Env.ZERO; + Boolean IsSOTrx = Boolean.FALSE; + String sql = "SELECT currencyConvert(invoiceOpen(i.C_Invoice_ID, 0), i.C_Currency_ID," + + "ba.C_Currency_ID, i.DateInvoiced, i.C_ConversionType_ID, i.AD_Client_ID, i.AD_Org_ID)," + + " paymentTermDiscount(i.GrandTotal,i.C_Currency_ID,i.C_PaymentTerm_ID,i.DateInvoiced, ?), i.IsSOTrx " + + "FROM C_Invoice_v i, C_BankAccount ba " + + "WHERE i.C_Invoice_ID=? AND ba.C_BankAccount_ID=?"; // #1..2 + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_Invoice_ID); + pstmt.setInt(2, C_BankAccount_ID); + pstmt.setTimestamp(3, PayDate); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + OpenAmt = rs.getBigDecimal(1); + DiscountAmt = rs.getBigDecimal(2); + IsSOTrx = new Boolean ("Y".equals(rs.getString(3))); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + + log.fine(" - OpenAmt=" + OpenAmt + " (Invoice=" + C_Invoice_ID + ",BankAcct=" + C_BankAccount_ID + ")"); + mTab.setValue("OpenAmt", OpenAmt); + mTab.setValue("PayAmt", OpenAmt.subtract(DiscountAmt)); + mTab.setValue("DiscountAmt", DiscountAmt); + mTab.setValue("DifferenceAmt", Env.ZERO); + mTab.setValue("IsSOTrx", IsSOTrx); + + setCalloutActive(false); + return ""; + } // PaySel_Invoice + + +} // CalloutPaySelection diff --git a/base/src/org/compiere/model/CalloutPayment.java b/base/src/org/compiere/model/CalloutPayment.java new file mode 100644 index 0000000000..f27eedd5cb --- /dev/null +++ b/base/src/org/compiere/model/CalloutPayment.java @@ -0,0 +1,444 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Payment Callouts. + * org.compiere.model.CalloutPayment.* + * + * @author Jorg Janke + * @version $Id: CalloutPayment.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class CalloutPayment extends CalloutEngine +{ + /** + * Payment_Invoice. + * when Invoice selected + * - set C_Currency_ID + * - C_BPartner_ID + * - DiscountAmt = C_Invoice_Discount (ID, DateTrx) + * - PayAmt = invoiceOpen (ID) - Discount + * - WriteOffAmt = 0 + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String invoice (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_Invoice_ID = (Integer)value; + if (isCalloutActive() // assuming it is resetting value + || C_Invoice_ID == null || C_Invoice_ID.intValue() == 0) + return ""; + setCalloutActive(true); + mTab.setValue("C_Order_ID", null); + mTab.setValue("C_Charge_ID", null); + mTab.setValue("IsPrepayment", Boolean.FALSE); + // + mTab.setValue("DiscountAmt", Env.ZERO); + mTab.setValue("WriteOffAmt", Env.ZERO); + mTab.setValue("IsOverUnderPayment", Boolean.FALSE); + mTab.setValue("OverUnderAmt", Env.ZERO); + + int C_InvoicePaySchedule_ID = 0; + if (Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_Invoice_ID") == C_Invoice_ID.intValue() + && Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_InvoicePaySchedule_ID") != 0) + C_InvoicePaySchedule_ID = Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_InvoicePaySchedule_ID"); + + // Payment Date + Timestamp ts = (Timestamp)mTab.getValue("DateTrx"); + if (ts == null) + ts = new Timestamp(System.currentTimeMillis()); + // + String sql = "SELECT C_BPartner_ID,C_Currency_ID," // 1..2 + + " invoiceOpen(C_Invoice_ID, ?)," // 3 #1 + + " invoiceDiscount(C_Invoice_ID,?,?), IsSOTrx " // 4..5 #2/3 + + "FROM C_Invoice WHERE C_Invoice_ID=?"; // #4 + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_InvoicePaySchedule_ID); + pstmt.setTimestamp(2, ts); + pstmt.setInt(3, C_InvoicePaySchedule_ID); + pstmt.setInt(4, C_Invoice_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + mTab.setValue("C_BPartner_ID", new Integer(rs.getInt(1))); + int C_Currency_ID = rs.getInt(2); // Set Invoice Currency + mTab.setValue("C_Currency_ID", new Integer(C_Currency_ID)); + // + BigDecimal InvoiceOpen = rs.getBigDecimal(3); // Set Invoice OPen Amount + if (InvoiceOpen == null) + InvoiceOpen = Env.ZERO; + BigDecimal DiscountAmt = rs.getBigDecimal(4); // Set Discount Amt + if (DiscountAmt == null) + DiscountAmt = Env.ZERO; + mTab.setValue("PayAmt", InvoiceOpen.subtract(DiscountAmt)); + mTab.setValue("DiscountAmt", DiscountAmt); + // reset as dependent fields get reset + Env.setContext(ctx, WindowNo, "C_Invoice_ID", C_Invoice_ID.toString()); + mTab.setValue("C_Invoice_ID", C_Invoice_ID); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + setCalloutActive(false); + return e.getLocalizedMessage(); + } + + setCalloutActive(false); + return docType(ctx, WindowNo, mTab, mField, value); + } // invoice + + /** + * Payment_Order. + * when Waiting Payment Order selected + * - set C_Currency_ID + * - C_BPartner_ID + * - DiscountAmt = C_Invoice_Discount (ID, DateTrx) + * - PayAmt = invoiceOpen (ID) - Discount + * - WriteOffAmt = 0 + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String order (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_Order_ID = (Integer)value; + if (isCalloutActive() // assuming it is resetting value + || C_Order_ID == null || C_Order_ID.intValue() == 0) + return ""; + setCalloutActive(true); + mTab.setValue("C_Invoice_ID", null); + mTab.setValue("C_Charge_ID", null); + mTab.setValue("IsPrepayment", Boolean.TRUE); + // + mTab.setValue("DiscountAmt", Env.ZERO); + mTab.setValue("WriteOffAmt", Env.ZERO); + mTab.setValue("IsOverUnderPayment", Boolean.FALSE); + mTab.setValue("OverUnderAmt", Env.ZERO); + + // Payment Date + Timestamp ts = (Timestamp)mTab.getValue("DateTrx"); + if (ts == null) + ts = new Timestamp(System.currentTimeMillis()); + // + String sql = "SELECT C_BPartner_ID,C_Currency_ID, GrandTotal " + + "FROM C_Order WHERE C_Order_ID=?"; // #1 + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_Order_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + mTab.setValue("C_BPartner_ID", new Integer(rs.getInt(1))); + int C_Currency_ID = rs.getInt(2); // Set Order Currency + mTab.setValue("C_Currency_ID", new Integer(C_Currency_ID)); + // + BigDecimal GrandTotal = rs.getBigDecimal(3); // Set Pay Amount + if (GrandTotal == null) + GrandTotal = Env.ZERO; + mTab.setValue("PayAmt", GrandTotal); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + setCalloutActive(false); + return e.getLocalizedMessage(); + } + + setCalloutActive(false); + return docType(ctx, WindowNo, mTab, mField, value); + } // order + + /** + * Payment_Project. + * - reset - C_BPartner_ID, Invoice, Order, Project, + * Discount, WriteOff + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String project (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_Project_ID = (Integer)value; + if (isCalloutActive() // assuming it is resetting value + || C_Project_ID == null || C_Project_ID.intValue() == 0) + return ""; + setCalloutActive(true); + mTab.setValue("C_Charge_ID", null); + setCalloutActive(false); + return ""; + } // project + + /** + * Payment_Charge. + * - reset - C_BPartner_ID, Invoice, Order, Project, + * Discount, WriteOff + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String charge (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_Charge_ID = (Integer)value; + if (isCalloutActive() // assuming it is resetting value + || C_Charge_ID == null || C_Charge_ID.intValue() == 0) + return ""; + setCalloutActive(true); + mTab.setValue("C_Invoice_ID", null); + mTab.setValue("C_Order_ID", null); + mTab.setValue("C_Project_ID", null); + mTab.setValue("IsPrepayment", Boolean.FALSE); + // + mTab.setValue("DiscountAmt", Env.ZERO); + mTab.setValue("WriteOffAmt", Env.ZERO); + mTab.setValue("IsOverUnderPayment", Boolean.FALSE); + mTab.setValue("OverUnderAmt", Env.ZERO); + setCalloutActive(false); + return ""; + } // charge + + /** + * Payment_Document Type. + * Verify that Document Type (AP/AR) and Invoice (SO/PO) are in sync + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String docType (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + int C_Invoice_ID = Env.getContextAsInt(ctx, WindowNo, "C_Invoice_ID"); + int C_Order_ID = Env.getContextAsInt(ctx, WindowNo, "C_Order_ID"); + int C_DocType_ID = Env.getContextAsInt(ctx, WindowNo, "C_DocType_ID"); + log.fine("Payment_DocType - C_Invoice_ID=" + C_Invoice_ID + ", C_DocType_ID=" + C_DocType_ID); + MDocType dt = null; + if (C_DocType_ID != 0) + { + dt = MDocType.get(ctx, C_DocType_ID); + Env.setContext(ctx, WindowNo, "IsSOTrx", dt.isSOTrx() ? "Y" : "N"); + } + // Invoice + if (C_Invoice_ID != 0) + { + MInvoice inv = new MInvoice (ctx, C_Invoice_ID, null); + if (dt != null) + { + if (inv.isSOTrx() != dt.isSOTrx()) + return "PaymentDocTypeInvoiceInconsistent"; + } + } + // Order Waiting Payment (can only be SO) + if (C_Order_ID != 0 && !dt.isSOTrx()) + return "PaymentDocTypeInvoiceInconsistent"; + + return ""; + } // docType + + + /** + * Payment_Amounts. + * Change of: + * - IsOverUnderPayment -> set OverUnderAmt to 0 + * - C_Currency_ID, C_ConvesionRate_ID -> convert all + * - PayAmt, DiscountAmt, WriteOffAmt, OverUnderAmt -> PayAmt + * make sure that add up to InvoiceOpenAmt + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @param oldValue Old Value + * @return null or error message + */ + public String amounts (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value, Object oldValue) + { + if (isCalloutActive()) // assuming it is resetting value + return ""; + int C_Invoice_ID = Env.getContextAsInt(ctx, WindowNo, "C_Invoice_ID"); + // New Payment + if (Env.getContextAsInt(ctx, WindowNo, "C_Payment_ID") == 0 + && Env.getContextAsInt(ctx, WindowNo, "C_BPartner_ID") == 0 + && C_Invoice_ID == 0) + return ""; + setCalloutActive(true); + + // Changed Column + String colName = mField.getColumnName(); + if (colName.equals("IsOverUnderPayment") // Set Over/Under Amt to Zero + || !"Y".equals(Env.getContext(ctx, WindowNo, "IsOverUnderPayment"))) + mTab.setValue("OverUnderAmt", Env.ZERO); + + int C_InvoicePaySchedule_ID = 0; + if (Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_Invoice_ID") == C_Invoice_ID + && Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_InvoicePaySchedule_ID") != 0) + C_InvoicePaySchedule_ID = Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_InvoicePaySchedule_ID"); + + // Get Open Amount & Invoice Currency + BigDecimal InvoiceOpenAmt = Env.ZERO; + int C_Currency_Invoice_ID = 0; + if (C_Invoice_ID != 0) + { + Timestamp ts = (Timestamp)mTab.getValue("DateTrx"); + if (ts == null) + ts = new Timestamp(System.currentTimeMillis()); + String sql = "SELECT C_BPartner_ID,C_Currency_ID," // 1..2 + + " invoiceOpen(C_Invoice_ID,?)," // 3 #1 + + " invoiceDiscount(C_Invoice_ID,?,?), IsSOTrx " // 4..5 #2/3 + + "FROM C_Invoice WHERE C_Invoice_ID=?"; // #4 + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_InvoicePaySchedule_ID); + pstmt.setTimestamp(2, ts); + pstmt.setInt(3, C_InvoicePaySchedule_ID); + pstmt.setInt(4, C_Invoice_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + C_Currency_Invoice_ID= rs.getInt(2); + InvoiceOpenAmt = rs.getBigDecimal(3); // Set Invoice Open Amount + if (InvoiceOpenAmt == null) + InvoiceOpenAmt = Env.ZERO; + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + setCalloutActive(false); + return e.getLocalizedMessage(); + } + } // get Invoice Info + log.fine("Open=" + InvoiceOpenAmt + ", C_Invoice_ID=" + C_Invoice_ID + + ", C_Currency_ID=" + C_Currency_Invoice_ID); + + // Get Info from Tab + BigDecimal PayAmt = (BigDecimal)mTab.getValue("PayAmt"); + BigDecimal DiscountAmt = (BigDecimal)mTab.getValue("DiscountAmt"); + BigDecimal WriteOffAmt = (BigDecimal)mTab.getValue("WriteOffAmt"); + BigDecimal OverUnderAmt = (BigDecimal)mTab.getValue("OverUnderAmt"); + log.fine("Pay=" + PayAmt + ", Discount=" + DiscountAmt + + ", WriteOff=" + WriteOffAmt + ", OverUnderAmt=" + OverUnderAmt); + // Get Currency Info + int C_Currency_ID = ((Integer)mTab.getValue("C_Currency_ID")).intValue(); + MCurrency currency = MCurrency.get(ctx, C_Currency_ID); + Timestamp ConvDate = (Timestamp)mTab.getValue("DateTrx"); + int C_ConversionType_ID = 0; + Integer ii = (Integer)mTab.getValue("C_ConversionType_ID"); + if (ii != null) + C_ConversionType_ID = ii.intValue(); + int AD_Client_ID = Env.getContextAsInt(ctx, WindowNo, "AD_Client_ID"); + int AD_Org_ID = Env.getContextAsInt(ctx, WindowNo, "AD_Org_ID"); + // Get Currency Rate + BigDecimal CurrencyRate = Env.ONE; + if ((C_Currency_ID > 0 && C_Currency_Invoice_ID > 0 && + C_Currency_ID != C_Currency_Invoice_ID) + || colName.equals("C_Currency_ID") || colName.equals("C_ConversionType_ID")) + { + log.fine("InvCurrency=" + C_Currency_Invoice_ID + + ", PayCurrency=" + C_Currency_ID + + ", Date=" + ConvDate + ", Type=" + C_ConversionType_ID); + CurrencyRate = MConversionRate.getRate (C_Currency_Invoice_ID, C_Currency_ID, + ConvDate, C_ConversionType_ID, AD_Client_ID, AD_Org_ID); + if (CurrencyRate == null || CurrencyRate.compareTo(Env.ZERO) == 0) + { + // mTab.setValue("C_Currency_ID", new Integer(C_Currency_Invoice_ID)); // does not work + setCalloutActive(false); + if (C_Currency_Invoice_ID == 0) + return ""; // no error message when no invoice is selected + return "NoCurrencyConversion"; + } + // + InvoiceOpenAmt = InvoiceOpenAmt.multiply(CurrencyRate) + .setScale(currency.getStdPrecision(), BigDecimal.ROUND_HALF_UP); + log.fine("Rate=" + CurrencyRate + ", InvoiceOpenAmt=" + InvoiceOpenAmt); + } + + // Currency Changed - convert all + if (colName.equals("C_Currency_ID") || colName.equals("C_ConversionType_ID")) + { + PayAmt = PayAmt.multiply(CurrencyRate) + .setScale(currency.getStdPrecision(), BigDecimal.ROUND_HALF_UP); + mTab.setValue("PayAmt", PayAmt); + DiscountAmt = DiscountAmt.multiply(CurrencyRate) + .setScale(currency.getStdPrecision(), BigDecimal.ROUND_HALF_UP); + mTab.setValue("DiscountAmt", DiscountAmt); + WriteOffAmt = WriteOffAmt.multiply(CurrencyRate) + .setScale(currency.getStdPrecision(), BigDecimal.ROUND_HALF_UP); + mTab.setValue("WriteOffAmt", WriteOffAmt); + OverUnderAmt = OverUnderAmt.multiply(CurrencyRate) + .setScale(currency.getStdPrecision(), BigDecimal.ROUND_HALF_UP); + mTab.setValue("OverUnderAmt", OverUnderAmt); + } + + // No Invoice - Set Discount, Witeoff, Under/Over to 0 + else if (C_Invoice_ID == 0) + { + if (Env.ZERO.compareTo(DiscountAmt) != 0) + mTab.setValue("DiscountAmt", Env.ZERO); + if (Env.ZERO.compareTo(WriteOffAmt) != 0) + mTab.setValue("WriteOffAmt", Env.ZERO); + if (Env.ZERO.compareTo(OverUnderAmt) != 0) + mTab.setValue("OverUnderAmt", Env.ZERO); + } + // PayAmt - calculate write off + else if (colName.equals("PayAmt")) + { + WriteOffAmt = InvoiceOpenAmt.subtract(PayAmt).subtract(DiscountAmt).subtract(OverUnderAmt); + mTab.setValue("WriteOffAmt", WriteOffAmt); + } + else // calculate PayAmt + { + PayAmt = InvoiceOpenAmt.subtract(DiscountAmt).subtract(WriteOffAmt).subtract(OverUnderAmt); + mTab.setValue("PayAmt", PayAmt); + } + + setCalloutActive(false); + return ""; + } // amounts + +} // CalloutPayment diff --git a/base/src/org/compiere/model/CalloutPaymentAllocate.java b/base/src/org/compiere/model/CalloutPaymentAllocate.java new file mode 100644 index 0000000000..86e44254fe --- /dev/null +++ b/base/src/org/compiere/model/CalloutPaymentAllocate.java @@ -0,0 +1,174 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Callout for Allocate Payments + * + * @author Jorg Janke + * @version $Id: CalloutPaymentAllocate.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class CalloutPaymentAllocate extends CalloutEngine +{ + /** + * Payment_Invoice. + * when Invoice selected + * - set InvoiceAmt = invoiceOpen + * - DiscountAmt = C_Invoice_Discount (ID, DateTrx) + * - Amount = invoiceOpen (ID) - Discount + * - WriteOffAmt,OverUnderAmt = 0 + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String invoice (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer C_Invoice_ID = (Integer)value; + if (isCalloutActive() // assuming it is resetting value + || C_Invoice_ID == null || C_Invoice_ID.intValue() == 0) + return ""; + + // Check Payment + int C_Payment_ID = Env.getContextAsInt(ctx, WindowNo, "C_Payment_ID"); + MPayment payment = new MPayment (ctx, C_Payment_ID, null); + if (payment.getC_Charge_ID() != 0 || payment.getC_Invoice_ID() != 0 + || payment.getC_Order_ID() != 0) + return Msg.getMsg(ctx, "PaymentIsAllocated"); + + setCalloutActive(true); + // + mTab.setValue("DiscountAmt", Env.ZERO); + mTab.setValue("WriteOffAmt", Env.ZERO); + mTab.setValue("OverUnderAmt", Env.ZERO); + + int C_InvoicePaySchedule_ID = 0; + if (Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_Invoice_ID") == C_Invoice_ID.intValue() + && Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_InvoicePaySchedule_ID") != 0) + C_InvoicePaySchedule_ID = Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "C_InvoicePaySchedule_ID"); + + // Payment Date + Timestamp ts = Env.getContextAsDate(ctx, WindowNo, "DateTrx"); + // + String sql = "SELECT C_BPartner_ID,C_Currency_ID," // 1..2 + + " invoiceOpen(C_Invoice_ID, ?)," // 3 #1 + + " invoiceDiscount(C_Invoice_ID,?,?), IsSOTrx " // 4..5 #2/3 + + "FROM C_Invoice WHERE C_Invoice_ID=?"; // #4 + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_InvoicePaySchedule_ID); + pstmt.setTimestamp(2, ts); + pstmt.setInt(3, C_InvoicePaySchedule_ID); + pstmt.setInt(4, C_Invoice_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + // mTab.setValue("C_BPartner_ID", new Integer(rs.getInt(1))); + // int C_Currency_ID = rs.getInt(2); // Set Invoice Currency + // mTab.setValue("C_Currency_ID", new Integer(C_Currency_ID)); + // + BigDecimal InvoiceOpen = rs.getBigDecimal(3); // Set Invoice OPen Amount + if (InvoiceOpen == null) + InvoiceOpen = Env.ZERO; + BigDecimal DiscountAmt = rs.getBigDecimal(4); // Set Discount Amt + if (DiscountAmt == null) + DiscountAmt = Env.ZERO; + mTab.setValue("InvoiceAmt", InvoiceOpen); + mTab.setValue("Amount", InvoiceOpen.subtract(DiscountAmt)); + mTab.setValue("DiscountAmt", DiscountAmt); + // reset as dependent fields get reset + Env.setContext(ctx, WindowNo, "C_Invoice_ID", C_Invoice_ID.toString()); + mTab.setValue("C_Invoice_ID", C_Invoice_ID); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + setCalloutActive(false); + return e.getLocalizedMessage(); + } + + setCalloutActive(false); + return ""; + } // invoice + + /** + * Payment_Amounts. + * Change of: + * - IsOverUnderPayment -> set OverUnderAmt to 0 + * - C_Currency_ID, C_ConvesionRate_ID -> convert all + * - PayAmt, DiscountAmt, WriteOffAmt, OverUnderAmt -> PayAmt + * make sure that add up to InvoiceOpenAmt + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @param oldValue Old Value + * @return null or error message + */ + public String amounts (Properties ctx, int WindowNo, GridTab mTab, GridField mField, + Object value, Object oldValue) + { + if (isCalloutActive()) // assuming it is resetting value + return ""; + // No Invoice + int C_Invoice_ID = Env.getContextAsInt(ctx, WindowNo, "C_Invoice_ID"); + if (C_Invoice_ID == 0) + return ""; + setCalloutActive(true); + // Get Info from Tab + BigDecimal Amount = (BigDecimal)mTab.getValue("Amount"); + BigDecimal DiscountAmt = (BigDecimal)mTab.getValue("DiscountAmt"); + BigDecimal WriteOffAmt = (BigDecimal)mTab.getValue("WriteOffAmt"); + BigDecimal OverUnderAmt = (BigDecimal)mTab.getValue("OverUnderAmt"); + BigDecimal InvoiceAmt = (BigDecimal)mTab.getValue("InvoiceAmt"); + log.fine("Amt=" + Amount + ", Discount=" + DiscountAmt + + ", WriteOff=" + WriteOffAmt + ", OverUnder=" + OverUnderAmt + + ", Invoice=" + InvoiceAmt); + + // Changed Column + String colName = mField.getColumnName(); + // PayAmt - calculate write off + if (colName.equals("Amount")) + { + WriteOffAmt = InvoiceAmt.subtract(Amount).subtract(DiscountAmt).subtract(OverUnderAmt); + mTab.setValue("WriteOffAmt", WriteOffAmt); + } + else // calculate Amount + { + Amount = InvoiceAmt.subtract(DiscountAmt).subtract(WriteOffAmt).subtract(OverUnderAmt); + mTab.setValue("Amount", Amount); + } + + setCalloutActive(false); + return ""; + } // amounts + + +} // CalloutPaymentAllocate diff --git a/base/src/org/compiere/model/CalloutProduction.java b/base/src/org/compiere/model/CalloutProduction.java new file mode 100644 index 0000000000..90cd1b70cd --- /dev/null +++ b/base/src/org/compiere/model/CalloutProduction.java @@ -0,0 +1,55 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.util.*; +import org.compiere.util.*; + +/** + * Production Callouts + * + * @author Jorg Janke + * @version $Id: CalloutProduction.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class CalloutProduction extends CalloutEngine +{ + /** + * Product modified + * Set Attribute Set Instance + * + * @param ctx Context + * @param WindowNo current Window No + * @param mTab Model Tab + * @param mField Model Field + * @param value The new value + * @return Error message or "" + */ + public String product (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer M_Product_ID = (Integer)value; + if (M_Product_ID == null || M_Product_ID.intValue() == 0) + return ""; + // Set Attribute + if (Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_Product_ID") == M_Product_ID.intValue() + && Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_AttributeSetInstance_ID") != 0) + mTab.setValue("M_AttributeSetInstance_ID", new Integer(Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_AttributeSetInstance_ID"))); + else + mTab.setValue("M_AttributeSetInstance_ID", null); + return ""; + } // product + +} // CalloutProduction diff --git a/base/src/org/compiere/model/CalloutProject.java b/base/src/org/compiere/model/CalloutProject.java new file mode 100644 index 0000000000..fe61d9e463 --- /dev/null +++ b/base/src/org/compiere/model/CalloutProject.java @@ -0,0 +1,71 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.util.*; +import org.compiere.util.*; + + +/** + * Project Callouts + * + * @author Jorg Janke + * @version $Id: CalloutProject.java,v 1.3 2006/07/30 00:51:04 jjanke Exp $ + */ +public class CalloutProject extends CalloutEngine +{ + /** + * Project Planned - Price + Qty. + * - called from PlannedPrice, PlannedQty + * - calculates PlannedAmt (same as Trigger) + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String planned (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive() || value == null) + return ""; + setCalloutActive(true); + + BigDecimal PlannedQty, PlannedPrice; + int StdPrecision = Env.getContextAsInt(ctx, WindowNo, "StdPrecision"); + + + // get values + PlannedQty = (BigDecimal)mTab.getValue("PlannedQty"); + if (PlannedQty == null) + PlannedQty = Env.ONE; + PlannedPrice = ((BigDecimal)mTab.getValue("PlannedPrice")); + if (PlannedPrice == null) + PlannedPrice = Env.ZERO; + // + BigDecimal PlannedAmt = PlannedQty.multiply(PlannedPrice); + if (PlannedAmt.scale() > StdPrecision) + PlannedAmt = PlannedAmt.setScale(StdPrecision, BigDecimal.ROUND_HALF_UP); + // + log.fine("PlannedQty=" + PlannedQty + " * PlannedPrice=" + PlannedPrice + " -> PlannedAmt=" + PlannedAmt + " (Precision=" + StdPrecision+ ")"); + mTab.setValue("PlannedAmt", PlannedAmt); + setCalloutActive(false); + return ""; + } // planned + +} // CalloutProject diff --git a/base/src/org/compiere/model/CalloutRequest.java b/base/src/org/compiere/model/CalloutRequest.java new file mode 100644 index 0000000000..da28d7371d --- /dev/null +++ b/base/src/org/compiere/model/CalloutRequest.java @@ -0,0 +1,142 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Request Callouts + * + * @author Jorg Janke + * @version $Id: CalloutRequest.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class CalloutRequest extends CalloutEngine +{ + /** + * Request - Copy Mail Text - Callout + * + * @param ctx Context + * @param WindowNo current Window No + * @param mTab Model Tab + * @param mField Model Field + * @param value The new value + * @return Error message or "" + */ + public String copyMail (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + String colName = mField.getColumnName(); + log.info(colName + "=" + value); + if (value == null) + return ""; + + Integer R_MailText_ID = (Integer)value; + String sql = "SELECT MailHeader, MailText FROM R_MailText " + + "WHERE R_MailText_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, R_MailText_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + String txt = rs.getString(2); + txt = Env.parseContext(ctx, WindowNo, txt, false, true); + mTab.setValue("Result", txt); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + return ""; + } // copyText + + + /** + * Request - Copy Response Text - Callout + * + * @param ctx Context + * @param WindowNo current Window No + * @param mTab Model Tab + * @param mField Model Field + * @param value The new value + * @return Error message or "" + */ + public String copyResponse (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + String colName = mField.getColumnName(); + log.info(colName + "=" + value); + if (value == null) + return ""; + + Integer R_StandardResponse_ID = (Integer)value; + String sql = "SELECT Name, ResponseText FROM R_StandardResponse " + + "WHERE R_StandardResponse_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, R_StandardResponse_ID.intValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + String txt = rs.getString(2); + txt = Env.parseContext(ctx, WindowNo, txt, false, true); + mTab.setValue("Result", txt); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + return ""; + } // copyResponse + + /** + * Request - Chane of Request Type - Callout + * + * @param ctx Context + * @param WindowNo current Window No + * @param mTab Model Tab + * @param mField Model Field + * @param value The new value + * @return Error message or "" + */ + public String type (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + String colName = mField.getColumnName(); + log.info(colName + "=" + value); + mTab.setValue("R_Status_ID", null); + if (value == null) + return ""; + int R_RequestType_ID = ((Integer)value).intValue(); + if (R_RequestType_ID == 0) + return ""; + MRequestType rt = MRequestType.get(ctx, R_RequestType_ID); + int R_Status_ID = rt.getDefaultR_Status_ID(); + if (R_Status_ID != 0) + mTab.setValue("R_Status_ID", new Integer(R_Status_ID)); + + return ""; + } // type +} // CalloutRequest diff --git a/base/src/org/compiere/model/CalloutRequisition.java b/base/src/org/compiere/model/CalloutRequisition.java new file mode 100644 index 0000000000..1d16a78320 --- /dev/null +++ b/base/src/org/compiere/model/CalloutRequisition.java @@ -0,0 +1,134 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Requisition Callouts + * + * @author Jorg Janke + * @version $Id: CalloutRequisition.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class CalloutRequisition extends CalloutEngine +{ + /** + * Requisition Line - Product. + * - PriceStd + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String product (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer M_Product_ID = (Integer)value; + if (M_Product_ID == null || M_Product_ID.intValue() == 0) + return ""; + // setCalloutActive(true); + // + /** Set Attribute + if (Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_Product_ID") == M_Product_ID.intValue() + && Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_AttributeSetInstance_ID") != 0) + mTab.setValue("M_AttributeSetInstance_ID", new Integer(Env.getContextAsInt(ctx, Env.WINDOW_INFO, Env.TAB_INFO, "M_AttributeSetInstance_ID"))); + else + mTab.setValue("M_AttributeSetInstance_ID", null); + **/ + int C_BPartner_ID = Env.getContextAsInt(ctx, WindowNo, WindowNo, "C_BPartner_ID"); + BigDecimal Qty = (BigDecimal)mTab.getValue("Qty"); + boolean isSOTrx = false; + MProductPricing pp = new MProductPricing (M_Product_ID.intValue(), + C_BPartner_ID, Qty, isSOTrx); + // + int M_PriceList_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_ID"); + pp.setM_PriceList_ID(M_PriceList_ID); + int M_PriceList_Version_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_Version_ID"); + pp.setM_PriceList_Version_ID(M_PriceList_Version_ID); + Timestamp orderDate = (Timestamp)mTab.getValue("DateRequired"); + pp.setPriceDate(orderDate); + // + mTab.setValue("PriceActual", pp.getPriceStd()); + Env.setContext(ctx, WindowNo, "EnforcePriceLimit", pp.isEnforcePriceLimit() ? "Y" : "N"); // not used + Env.setContext(ctx, WindowNo, "DiscountSchema", pp.isDiscountSchema() ? "Y" : "N"); + + // setCalloutActive(false); + return ""; + } // product + + /** + * Order Line - Amount. + * - called from Qty, PriceActual + * - calculates LineNetAmt + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String amt (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive() || value == null) + return ""; + setCalloutActive(true); + + // Qty changed - recalc price + if (mField.getColumnName().equals("Qty") + && "Y".equals(Env.getContext(ctx, WindowNo, "DiscountSchema"))) + { + int M_Product_ID = Env.getContextAsInt(ctx, WindowNo, WindowNo, "M_Product_ID"); + int C_BPartner_ID = Env.getContextAsInt(ctx, WindowNo, WindowNo, "C_BPartner_ID"); + BigDecimal Qty = (BigDecimal)value; + boolean isSOTrx = false; + MProductPricing pp = new MProductPricing (M_Product_ID, + C_BPartner_ID, Qty, isSOTrx); + // + int M_PriceList_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_ID"); + pp.setM_PriceList_ID(M_PriceList_ID); + int M_PriceList_Version_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_Version_ID"); + pp.setM_PriceList_Version_ID(M_PriceList_Version_ID); + Timestamp orderDate = (Timestamp)mTab.getValue("DateInvoiced"); + pp.setPriceDate(orderDate); + // + mTab.setValue("PriceActual", pp.getPriceStd()); + } + + int StdPrecision = Env.getContextAsInt(ctx, WindowNo, "StdPrecision"); + BigDecimal Qty = (BigDecimal)mTab.getValue("Qty"); + BigDecimal PriceActual = (BigDecimal)mTab.getValue("PriceActual"); + + // get values + log.fine("amt - Qty=" + Qty + ", Price=" + PriceActual + ", Precision=" + StdPrecision); + + // Multiply + BigDecimal LineNetAmt = Qty.multiply(PriceActual); + if (LineNetAmt.scale() > StdPrecision) + LineNetAmt = LineNetAmt.setScale(StdPrecision, BigDecimal.ROUND_HALF_UP); + mTab.setValue("LineNetAmt", LineNetAmt); + log.info("amt - LineNetAmt=" + LineNetAmt); + // + setCalloutActive(false); + return ""; + } // amt + + +} // CalloutRequisition diff --git a/base/src/org/compiere/model/CalloutTimeExpense.java b/base/src/org/compiere/model/CalloutTimeExpense.java new file mode 100644 index 0000000000..063785b109 --- /dev/null +++ b/base/src/org/compiere/model/CalloutTimeExpense.java @@ -0,0 +1,206 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Time & Expense Report Callout + * + * @author Jorg Janke + * @version $Id: CalloutTimeExpense.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class CalloutTimeExpense extends CalloutEngine +{ + /** + * Expense Report Line + * - called from M_Product_ID, S_ResourceAssignment_ID + * - set ExpenseAmt + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String product (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + Integer M_Product_ID = (Integer)value; + if (M_Product_ID == null || M_Product_ID.intValue() == 0) + return ""; + setCalloutActive(true); + BigDecimal priceActual = null; + + // get expense date - or default to today's date + Timestamp DateExpense = Env.getContextAsDate(ctx, WindowNo, "DateExpense"); + if (DateExpense == null) + DateExpense = new Timestamp(System.currentTimeMillis()); + + String sql = null; + try + { + boolean noPrice = true; + + // Search Pricelist for current version + sql = "SELECT bomPriceStd(p.M_Product_ID,pv.M_PriceList_Version_ID) AS PriceStd," + + "bomPriceList(p.M_Product_ID,pv.M_PriceList_Version_ID) AS PriceList," + + "bomPriceLimit(p.M_Product_ID,pv.M_PriceList_Version_ID) AS PriceLimit," + + "p.C_UOM_ID,pv.ValidFrom,pl.C_Currency_ID " + + "FROM M_Product p, M_ProductPrice pp, M_Pricelist pl, M_PriceList_Version pv " + + "WHERE p.M_Product_ID=pp.M_Product_ID" + + " AND pp.M_PriceList_Version_ID=pv.M_PriceList_Version_ID" + + " AND pv.M_PriceList_ID=pl.M_PriceList_ID" + + " AND pv.IsActive='Y'" + + " AND p.M_Product_ID=?" // 1 + + " AND pl.M_PriceList_ID=?" // 2 + + " ORDER BY pv.ValidFrom DESC"; + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, M_Product_ID.intValue()); + pstmt.setInt(2, Env.getContextAsInt(ctx, WindowNo, "M_PriceList_ID")); + ResultSet rs = pstmt.executeQuery(); + while (rs.next() && noPrice) + { + java.sql.Date plDate = rs.getDate("ValidFrom"); + // we have the price list + // if order date is after or equal PriceList validFrom + if (plDate == null || !DateExpense.before(plDate)) + { + noPrice = false; + // Price + priceActual = rs.getBigDecimal("PriceStd"); + if (priceActual == null) + priceActual = rs.getBigDecimal("PriceList"); + if (priceActual == null) + priceActual = rs.getBigDecimal("PriceLimit"); + // Currency + Integer ii = new Integer(rs.getInt("C_Currency_ID")); + if (!rs.wasNull()) + mTab.setValue("C_Currency_ID", ii); + } + } + rs.close(); + pstmt.close(); + + // no prices yet - look base pricelist + if (noPrice) + { + // Find if via Base Pricelist + sql = "SELECT bomPriceStd(p.M_Product_ID,pv.M_PriceList_Version_ID) AS PriceStd," + + "bomPriceList(p.M_Product_ID,pv.M_PriceList_Version_ID) AS PriceList," + + "bomPriceLimit(p.M_Product_ID,pv.M_PriceList_Version_ID) AS PriceLimit," + + "p.C_UOM_ID,pv.ValidFrom,pl.C_Currency_ID " + + "FROM M_Product p, M_ProductPrice pp, M_Pricelist pl, M_Pricelist bpl, M_PriceList_Version pv " + + "WHERE p.M_Product_ID=pp.M_Product_ID" + + " AND pp.M_PriceList_Version_ID=pv.M_PriceList_Version_ID" + + " AND pv.M_PriceList_ID=bpl.M_PriceList_ID" + + " AND pv.IsActive='Y'" + + " AND bpl.M_PriceList_ID=pl.BasePriceList_ID" // Base + + " AND p.M_Product_ID=?" // 1 + + " AND pl.M_PriceList_ID=?" // 2 + + " ORDER BY pv.ValidFrom DESC"; + + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, M_Product_ID.intValue()); + pstmt.setInt(2, Env.getContextAsInt(ctx, WindowNo, "M_PriceList_ID")); + rs = pstmt.executeQuery(); + while (rs.next() && noPrice) + { + java.sql.Date plDate = rs.getDate("ValidFrom"); + // we have the price list + // if order date is after or equal PriceList validFrom + if (plDate == null || !DateExpense.before(plDate)) + { + noPrice = false; + // Price + priceActual = rs.getBigDecimal("PriceStd"); + if (priceActual == null) + priceActual = rs.getBigDecimal("PriceList"); + if (priceActual == null) + priceActual = rs.getBigDecimal("PriceLimit"); + // Currency + Integer ii = new Integer(rs.getInt("C_Currency_ID")); + if (!rs.wasNull()) + mTab.setValue("C_Currency_ID", ii); + } + } + rs.close(); + pstmt.close(); + } + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + setCalloutActive(false); + return e.getLocalizedMessage(); + } + + // finish + setCalloutActive(false); // calculate amount + if (priceActual == null) + priceActual = Env.ZERO; + mTab.setValue("ExpenseAmt", priceActual); + return ""; + } // Expense_Product + + /** + * Expense - Amount. + * - called from ExpenseAmt, C_Currency_ID + * - calculates ConvertedAmt + * @param ctx context + * @param WindowNo current Window No + * @param mTab Grid Tab + * @param mField Grid Field + * @param value New Value + * @return null or error message + */ + public String amount (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) + { + if (isCalloutActive()) + return ""; + setCalloutActive(true); + + // get values + BigDecimal ExpenseAmt = (BigDecimal)mTab.getValue("ExpenseAmt"); + Integer C_Currency_From_ID = (Integer)mTab.getValue("C_Currency_ID"); + int C_Currency_To_ID = Env.getContextAsInt(ctx, "$C_Currency_ID"); + Timestamp DateExpense = Env.getContextAsDate(ctx, WindowNo, "DateExpense"); + // + log.fine("Amt=" + ExpenseAmt + ", C_Currency_ID=" + C_Currency_From_ID); + // Converted Amount = Unit price + BigDecimal ConvertedAmt = ExpenseAmt; + // convert if required + if (!ConvertedAmt.equals(Env.ZERO) && C_Currency_To_ID != C_Currency_From_ID.intValue()) + { + int AD_Client_ID = Env.getContextAsInt (ctx, WindowNo, "AD_Client_ID"); + int AD_Org_ID = Env.getContextAsInt (ctx, WindowNo, "AD_Org_ID"); + ConvertedAmt = MConversionRate.convert (ctx, + ConvertedAmt, C_Currency_From_ID.intValue(), C_Currency_To_ID, + DateExpense, 0, AD_Client_ID, AD_Org_ID); + } + mTab.setValue("ConvertedAmt", ConvertedAmt); + log.fine("= ConvertedAmt=" + ConvertedAmt); + + setCalloutActive(false); + return ""; + } // Expense_Amount + +} // CalloutTimeExpense diff --git a/base/src/org/compiere/model/DataStatusEvent.java b/base/src/org/compiere/model/DataStatusEvent.java new file mode 100644 index 0000000000..cb708fe8cc --- /dev/null +++ b/base/src/org/compiere/model/DataStatusEvent.java @@ -0,0 +1,335 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.sql.*; +import java.util.*; + +/** + * Data Status Event + *

+ * Indicates the current Status of the database + * + * @author Jorg Janke + * @version $Id: DataStatusEvent.java,v 1.4 2006/07/30 00:51:02 jjanke Exp $ + */ +public final class DataStatusEvent extends EventObject implements Serializable +{ + /** + * Constructor + * @param source1 source + * @param totalRows total rows + * @param changed changed + * @param autoSave auto save + * @param inserting inserting + */ + public DataStatusEvent (Object source1, int totalRows, boolean changed, + boolean autoSave, boolean inserting) + { + super(source1); + m_totalRows = totalRows; + m_changed = changed; + m_autoSave = autoSave; + m_inserting = inserting; + } // DataStatusEvent + + private int m_totalRows; + private boolean m_changed; + private boolean m_autoSave; + private boolean m_inserting; + // + private String m_AD_Message = null; + private String m_info = null; + private boolean m_isError = false; + private boolean m_isWarning = false; + private boolean m_confirmed = false; + // + private boolean m_allLoaded = true; + private int m_loadedRows = -1; + private int m_currentRow = -1; + // + private int m_changedColumn = 0; + private String m_columnName = null; + + /** Created */ + public Timestamp Created = null; + /** Created By */ + public Integer CreatedBy = null; + /** Updated */ + public Timestamp Updated = null; + /** Updated By */ + public Integer UpdatedBy = null; + /** Info */ + public String Info = null; + /** Table ID */ + public int AD_Table_ID = 0; + /** Record ID */ + public Object Record_ID = null; + + /** + * Set Loaded Info + * @param loadedRows loaded rows + */ + public void setLoading (int loadedRows) + { + m_allLoaded = false; + m_loadedRows = loadedRows; + } // setLoaded + + /** + * Is loading + * @return true if loading + */ + public boolean isLoading() + { + return !m_allLoaded; + } // isLoading + + /** + * Get loaded rows + * @return loaded rows + */ + public int getLoadedRows() + { + return m_loadedRows; + } // getLoadedRows + + /** + * Set current Row (zero based) + * @param currentRow current row + */ + public void setCurrentRow (int currentRow) + { + m_currentRow = currentRow; + } // setCurrentRow + + /** + * Get current row (zero based) + * @return current roe + */ + public int getCurrentRow() + { + return m_currentRow; + } // getCurrentRow + + /** + * Get total rows + * @return total rows + */ + public int getTotalRows() + { + return m_totalRows; + } // getTotalRows + + /** + * Set Message Info + * @param AD_Message message + * @param info info + * @param isError error + * @param isWarning true if warning + */ + public void setInfo (String AD_Message, String info, boolean isError, boolean isWarning) + { + m_AD_Message = AD_Message; + m_info = info; + m_isError = isError; + m_isWarning = isWarning; + } // setInfo + + /** + * Set Inserting + * @param inserting inserting + */ + public void setInserting (boolean inserting) + { + m_inserting = inserting; + } // setInserting + + /** + * Are we inserting + * @return true if inserting + */ + public boolean isInserting() + { + return m_inserting; + } // isInserting + + /** + * Get Message Info + * @return Message + */ + public String getAD_Message() + { + return m_AD_Message; + } // getAD_Message + + /** + * Get Message Info + * @return Info + */ + public String getInfo() + { + return m_info; + } // getInfo + + /** + * Is this an error + * @return true if error + */ + public boolean isError() + { + return m_isError; + } // isError + + /** + * Is this a warning + * @return true if warning + */ + public boolean isWarning() + { + return m_isWarning; + } // isWarning + + /** + * String representation of Status. + * @return Examples: +*1?/20 + * 1/256->2000 + */ + public String toString() + { + StringBuffer sb = new StringBuffer("DataStatusEvent - "); + if (m_AD_Message != null) + sb.append(m_AD_Message); + if (m_info != null) + sb.append(" ").append(m_info); + sb.append(" : ").append(getMessage()); + return sb.toString(); + } // toString + + /** + * String representation of Status. + *

+	 *		*1/20 		Change - automatic commit
+	 *		?1/20		Change - manual confirm
+	 *		 1/56->200	Loading
+	 *		 1/20		Normal
+	 *     +*1/20       Inserting, changed - automatic commit
+	 *  The row number is converted from zero based representation
+	 *  
+ * @return Status info + */ + public String getMessage() + { + StringBuffer retValue = new StringBuffer(); + if (m_inserting) + retValue.append("+"); + retValue.append(m_changed ? (m_autoSave ? "*" : "?") : " "); + // current row + if (m_totalRows == 0) + retValue.append(m_currentRow); + else + retValue.append(m_currentRow+1); + // of + retValue.append("/"); + if (m_allLoaded) + retValue.append(m_totalRows); + else + retValue.append(m_loadedRows).append("->").append(m_totalRows); + // + return retValue.toString(); + } // getMessage + + /** + * Is Data Changed + * @return true if changed + */ + public boolean isChanged() + { + return m_changed; + } // isChanged + + /** + * Is First Row - (zero based) + * @return true if first row + */ + public boolean isFirstRow() + { + if (m_totalRows == 0) + return true; + return m_currentRow == 0; + } // isFirstRow + + /** + * Is Last Row - (zero based) + * @return true if last row + */ + public boolean isLastRow() + { + if (m_totalRows == 0) + return true; + return m_currentRow == m_totalRows-1; + } // isLastRow + + /** + * Set Changed Column + * @param col column + * @param columnName column name + */ + public void setChangedColumn (int col, String columnName) + { + m_changedColumn = col; + m_columnName = columnName; + } // setChangedColumn + + /** + * Get Changed Column + * @return changed column + */ + public int getChangedColumn() + { + return m_changedColumn; + } // getChangedColumn + + /** + * Get Column Name + * @return column name + */ + public String getColumnName() + { + return m_columnName; + } // getColumnName + + /** + * Set Confirmed toggle + * @param confirmed confirmed + */ + public void setConfirmed (boolean confirmed) + { + m_confirmed = confirmed; + } // setConfirmed + + /** + * Is Confirmed (e.g. user has seen it) + * @return true if confirmed + */ + public boolean isConfirmed() + { + return m_confirmed; + } // isConfirmed + +} // DataStatusEvent diff --git a/base/src/org/compiere/model/DataStatusListener.java b/base/src/org/compiere/model/DataStatusListener.java new file mode 100644 index 0000000000..eacb88cc38 --- /dev/null +++ b/base/src/org/compiere/model/DataStatusListener.java @@ -0,0 +1,34 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.util.*; + +/** + * Data Status Interface + * + * @author Jorg Janke + * @version $Id: DataStatusListener.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public interface DataStatusListener extends EventListener +{ + /** + * Data Changed + * @param e event + */ + public void dataStatusChanged(DataStatusEvent e); +} // DataStatusListener diff --git a/base/src/org/compiere/model/GridField.java b/base/src/org/compiere/model/GridField.java new file mode 100644 index 0000000000..2df47f9596 --- /dev/null +++ b/base/src/org/compiere/model/GridField.java @@ -0,0 +1,1464 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.beans.*; +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Grid Field Model. + *

+ * Fields are a combination of AD_Field (the display attributes) + * and AD_Column (the storage attributes). + *

+ * The Field maintains the current edited value. If the value is changed, + * it fire PropertyChange "FieldValue". + * If the background is changed the PropertyChange "FieldAttribute" is fired. + *
+ * Usually editors listen to their fields. + * + * @author Jorg Janke + * @version $Id: GridField.java,v 1.5 2006/07/30 00:51:02 jjanke Exp $ + */ +public class GridField + implements Serializable, Evaluatee +{ + /** + * Field Constructor. + * requires initField for complete instatanciation + * @param vo ValueObjecy + */ + public GridField (GridFieldVO vo) + { + m_vo = vo; + // Set Attributes + loadLookup(); + setError(false); + } // MField + + /** Value Object */ + private GridFieldVO m_vo; + /** The Mnemonic */ + private char m_mnemonic = 0; + + /** + * Dispose + */ + protected void dispose() + { + // log.fine( "MField.dispose = " + m_vo.ColumnName); + m_propertyChangeListeners = null; + if (m_lookup != null) + m_lookup.dispose(); + m_lookup = null; + m_vo.lookupInfo = null; + m_vo = null; + } // dispose + + + /** Lookup for this field */ + private Lookup m_lookup = null; + /** New Row / inserting */ + private boolean m_inserting = false; + + + /** Max Display Length = 60 */ + public static final int MAXDISPLAY_LENGTH = 60; + + /** The current value */ + private Object m_value = null; + /** The old to force Property Change */ + private static Object s_oldValue = new Object(); + /** The old/previous value */ + private Object m_oldValue = s_oldValue; + /** Only fire Property Change if old value really changed */ + private boolean m_valueNoFire = true; + /** Error Status */ + private boolean m_error = false; + /** Parent Check */ + private boolean m_parentChecked = false; + + /** Property Change */ + private PropertyChangeSupport m_propertyChangeListeners = new PropertyChangeSupport(this); + /** PropertyChange Name */ + public static final String PROPERTY = "FieldValue"; + /** Indicator for new Value */ + public static final String INSERTING = "FieldValueInserting"; + + /** Error Value for HTML interface */ + private String m_errorValue = null; + /** Error Value indicator for HTML interface */ + private boolean m_errorValueFlag = false; + + /** Logger */ + private static CLogger log = CLogger.getCLogger(GridField.class); + + + /************************************************************************** + * Set Lookup for columns with lookup + */ + public void loadLookup() + { + if (!isLookup()) + return; + log.config("(" + m_vo.ColumnName + ")"); + + if (DisplayType.isLookup(m_vo.displayType)) + { + if (m_vo.lookupInfo == null) + { + log.log(Level.SEVERE, "(" + m_vo.ColumnName + ") - No LookupInfo"); + return; + } + // Prevent loading of CreatedBy/UpdatedBy + if (m_vo.displayType == DisplayType.Table + && (m_vo.ColumnName.equals("CreatedBy") || m_vo.ColumnName.equals("UpdatedBy")) ) + { + m_vo.lookupInfo.IsCreadedUpdatedBy = true; + m_vo.lookupInfo.DisplayType = DisplayType.Search; + } + // + m_vo.lookupInfo.IsKey = isKey(); + MLookup ml = new MLookup (m_vo.lookupInfo, m_vo.TabNo); + m_lookup = ml; + } + else if (m_vo.displayType == DisplayType.Location) // not cached + { + MLocationLookup ml = new MLocationLookup (m_vo.ctx, m_vo.WindowNo); + m_lookup = ml; + } + else if (m_vo.displayType == DisplayType.Locator) + { + MLocatorLookup ml = new MLocatorLookup (m_vo.ctx, m_vo.WindowNo); + m_lookup = ml; + } + else if (m_vo.displayType == DisplayType.Account) // not cached + { + MAccountLookup ma = new MAccountLookup (m_vo.ctx, m_vo.WindowNo); + m_lookup = ma; + } + else if (m_vo.displayType == DisplayType.PAttribute) // not cached + { + MPAttributeLookup pa = new MPAttributeLookup (m_vo.ctx, m_vo.WindowNo); + m_lookup = pa; + } + } // m_lookup + + /** + * Wait until Load is complete + */ + public void lookupLoadComplete() + { + if (m_lookup == null) + return; + m_lookup.loadComplete(); + } // loadCompete + + /** + * Get Lookup, may return null + * @return lookup + */ + public Lookup getLookup() + { + return m_lookup; + } // getLookup + + /** + * Is this field a Lookup?. + * @return true if lookup field + */ + public boolean isLookup() + { + boolean retValue = false; + if (m_vo.IsKey) + retValue = false; + // else if (m_vo.ColumnName.equals("CreatedBy") || m_vo.ColumnName.equals("UpdatedBy")) + // retValue = false; + else if (DisplayType.isLookup(m_vo.displayType)) + retValue = true; + else if (m_vo.displayType == DisplayType.Location + || m_vo.displayType == DisplayType.Locator + || m_vo.displayType == DisplayType.Account + || m_vo.displayType == DisplayType.PAttribute) + retValue = true; + + return retValue; + } // isLookup + + /** + * Refresh Lookup if the lookup is unstable + * @return true if lookup is validated + */ + public boolean refreshLookup() + { + // if there is a validation string, the lookup is unstable + if (m_lookup == null || m_lookup.getValidation().length() == 0) + return true; + // + log.fine("(" + m_vo.ColumnName + ")"); + m_lookup.refresh(); + return m_lookup.isValidated(); + } // refreshLookup + + /** + * Get a list of variables, this field is dependent on. + * - for display purposes or + * - for lookup purposes + * @return ArrayList + */ + public ArrayList getDependentOn() + { + ArrayList list = new ArrayList(); + // Display + Evaluator.parseDepends(list, m_vo.DisplayLogic); + Evaluator.parseDepends(list, m_vo.ReadOnlyLogic); + // Lookup + if (m_lookup != null) + Evaluator.parseDepends(list, m_lookup.getValidation()); + // + if (list.size() > 0 && CLogMgt.isLevelFiner()) + { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < list.size(); i++) + sb.append(list.get(i)).append(" "); + log.finer("(" + m_vo.ColumnName + ") " + sb.toString()); + } + return list; + } // getDependentOn + + + /************************************************************************** + * Set Error. + * Used by editors to set the color + * @param error true if error + */ + public void setError (boolean error) + { + m_error = error; + } // setBackground + + /** + * Get Background Error. + * @return error + */ + public boolean isError() + { + return m_error; + } // isError + + + /** + * Is it Mandatory to enter for user? + * Mandatory checking is dome in MTable.getMandatory + * @param checkContext - check environment (requires correct row position) + * @return true if mandatory + */ + public boolean isMandatory (boolean checkContext) + { + // Not mandatory + if (!m_vo.IsMandatory || isVirtualColumn()) + return false; + + // Numeric Keys and Created/Updated as well as + // DocumentNo/Value/ASI ars not mandatory (persistency layer manages them) + if ((m_vo.IsKey && m_vo.ColumnName.endsWith("_ID")) + || m_vo.ColumnName.startsWith("Created") || m_vo.ColumnName.startsWith("Updated") + || m_vo.ColumnName.equals("Value") + || m_vo.ColumnName.equals("DocumentNo") + || m_vo.ColumnName.equals("M_AttributeSetInstance_ID")) // 0 is valid + return false; + + // Mandatory if displayed + return isDisplayed (checkContext); + } // isMandatory + + /** + * Is it Editable - checks IsActive, IsUpdateable, and isDisplayed + * @param checkContext if true checks Context for Active, IsProcessed, LinkColumn + * @return true, if editable + */ + public boolean isEditable (boolean checkContext) + { + if (isVirtualColumn()) + return false; + // Fields always enabled (are usually not updateable) + if (m_vo.ColumnName.equals("Posted") + || (m_vo.ColumnName.equals("Record_ID") && m_vo.displayType == DisplayType.Button)) // Zoom + return true; + + // Fields always updareable + if (m_vo.IsAlwaysUpdateable) // Zoom + return true; + + // Tab or field is R/O + if (m_vo.tabReadOnly || m_vo.IsReadOnly) + { + log.finest(m_vo.ColumnName + " NO - TabRO=" + m_vo.tabReadOnly + ", FieldRO=" + m_vo.IsReadOnly); + return false; + } + + // Not Updateable - only editable if new updateable row + if (!m_vo.IsUpdateable && !m_inserting) + { + log.finest(m_vo.ColumnName + " NO - FieldUpdateable=" + m_vo.IsUpdateable); + return false; + } + + // Field is the Link Column of the tab + if (m_vo.ColumnName.equals(Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "LinkColumnName"))) + { + log.finest(m_vo.ColumnName + " NO - LinkColumn"); + return false; + } + + // Role Access & Column Access + if (checkContext) + { + int AD_Client_ID = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "AD_Client_ID"); + int AD_Org_ID = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "AD_Org_ID"); + String keyColumn = Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "KeyColumnName"); + int Record_ID = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, keyColumn); + int AD_Table_ID = m_vo.AD_Table_ID; + if (!MRole.getDefault(m_vo.ctx, false).canUpdate( + AD_Client_ID, AD_Org_ID, AD_Table_ID, Record_ID, false)) + return false; + if (!MRole.getDefault(m_vo.ctx, false).isColumnAccess(AD_Table_ID, m_vo.AD_Column_ID, false)) + return false; + } + + // Do we have a readonly rule + if (checkContext && m_vo.ReadOnlyLogic.length() > 0) + { + boolean retValue = !Evaluator.evaluateLogic(this, m_vo.ReadOnlyLogic); + log.finest(m_vo.ColumnName + " R/O(" + m_vo.ReadOnlyLogic + ") => R/W-" + retValue); + if (!retValue) + return false; + } + + // Always editable if Active + if (m_vo.ColumnName.equals("Processing") + || m_vo.ColumnName.equals("PaymentRule") + || m_vo.ColumnName.equals("DocAction") + || m_vo.ColumnName.equals("GenerateTo")) + return true; + + // Record is Processed *** + if (checkContext + && (Env.getContext(m_vo.ctx, m_vo.WindowNo, "Processed").equals("Y") + || Env.getContext(m_vo.ctx, m_vo.WindowNo, "Processing").equals("Y"))) + return false; + + // IsActive field is editable, if record not processed + if (m_vo.ColumnName.equals("IsActive")) + return true; + + // Record is not Active + if (checkContext && !Env.getContext(m_vo.ctx, m_vo.WindowNo, "IsActive").equals("Y")) + return false; + + // ultimately visibily decides + return isDisplayed (checkContext); + } // isEditable + + /** + * Set Inserting (allows to enter not updateable fields). + * Reset when setting the Field Value + * @param inserting true if inserting + */ + public void setInserting (boolean inserting) + { + m_inserting = inserting; + } // setInserting + + + /************************************************************************** + * Create default value. + *

+	 *		(a) Key/Parent/IsActive/SystemAccess
+	 *      (b) SQL Default
+	 *		(c) Column Default		//	system integrity
+	 *      (d) User Preference
+	 *		(e) System Preference
+	 *		(f) DataType Defaults
+	 *
+	 *  Don't default from Context => use explicit defaultValue
+	 *  (would otherwise copy previous record)
+	 *  
+ * @return default value or null + */ + public Object getDefault() + { + /** + * (a) Key/Parent/IsActive/SystemAccess + */ + + // No defaults for these fields + if (m_vo.IsKey || m_vo.displayType == DisplayType.RowID + || DisplayType.isLOB(m_vo.displayType)) + return null; + // Set Parent to context if not explitly set + if (isParentValue() + && (m_vo.DefaultValue == null || m_vo.DefaultValue.length() == 0)) + { + String parent = Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.ColumnName); + log.fine("[Parent] " + m_vo.ColumnName + "=" + parent); + return createDefault(parent); + } + // Always Active + if (m_vo.ColumnName.equals("IsActive")) + { + log.fine("[IsActive] " + m_vo.ColumnName + "=Y"); + return "Y"; + } + + // Set Client & Org to System, if System access + if (X_AD_Table.ACCESSLEVEL_SystemOnly.equals(Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "AccessLevel")) + && (m_vo.ColumnName.equals("AD_Client_ID") || m_vo.ColumnName.equals("AD_Org_ID"))) + { + log.fine("[SystemAccess] " + m_vo.ColumnName + "=0"); + return new Integer(0); + } + // Set Org to System, if Client access + else if (X_AD_Table.ACCESSLEVEL_SystemPlusClient.equals(Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "AccessLevel")) + && m_vo.ColumnName.equals("AD_Org_ID")) + { + log.fine("[ClientAccess] " + m_vo.ColumnName + "=0"); + return new Integer(0); + } + + /** + * (b) SQL Statement (for data integity & consistency) + */ + String defStr = ""; + if (m_vo.DefaultValue.startsWith("@SQL=")) + { + String sql = m_vo.DefaultValue.substring(5); // w/o tag + sql = Env.parseContext(m_vo.ctx, m_vo.WindowNo, sql, false, true); // replace variables + if (sql.equals("")) + { + log.log(Level.WARNING, "(" + m_vo.ColumnName + ") - Default SQL variable parse failed: " + + m_vo.DefaultValue); + } + else + { + try + { + PreparedStatement stmt = DB.prepareStatement(sql, null); + ResultSet rs = stmt.executeQuery(); + if (rs.next()) + defStr = rs.getString(1); + else + log.log(Level.WARNING, "(" + m_vo.ColumnName + ") - no Result: " + sql); + rs.close(); + stmt.close(); + } + catch (SQLException e) + { + log.log(Level.WARNING, "(" + m_vo.ColumnName + ") " + sql, e); + } + } + if (!defStr.equals("")) + { + log.fine("[SQL] " + m_vo.ColumnName + "=" + defStr); + return createDefault(defStr); + } + } // SQL Statement + + /** + * (c) Field DefaultValue === similar code in AStartRPDialog.getDefault === + */ + if (!m_vo.DefaultValue.equals("") && !m_vo.DefaultValue.startsWith("@SQL=")) + { + defStr = ""; // problem is with texts like 'sss;sss' + // It is one or more variables/constants + StringTokenizer st = new StringTokenizer(m_vo.DefaultValue, ",;", false); + while (st.hasMoreTokens()) + { + defStr = st.nextToken().trim(); + if (defStr.equals("@SysDate@")) // System Time + return new Timestamp (System.currentTimeMillis()); + else if (defStr.indexOf('@') != -1) // it is a variable + defStr = Env.getContext(m_vo.ctx, m_vo.WindowNo, defStr.replace('@',' ').trim()); + else if (defStr.indexOf("'") != -1) // it is a 'String' + defStr = defStr.replace('\'', ' ').trim(); + + if (!defStr.equals("")) + { + log.fine("[DefaultValue] " + m_vo.ColumnName + "=" + defStr); + return createDefault(defStr); + } + } // while more Tokens + } // Default value + + /** + * (d) Preference (user) - P| + */ + defStr = Env.getPreference (m_vo.ctx, m_vo.AD_Window_ID, m_vo.ColumnName, false); + if (!defStr.equals("")) + { + log.fine("[UserPreference] " + m_vo.ColumnName + "=" + defStr); + return createDefault(defStr); + } + + /** + * (e) Preference (System) - # $ + */ + defStr = Env.getPreference (m_vo.ctx, m_vo.AD_Window_ID, m_vo.ColumnName, true); + if (!defStr.equals("")) + { + log.fine("[SystemPreference] " + m_vo.ColumnName + "=" + defStr); + return createDefault(defStr); + } + + /** + * (f) DataType defaults + */ + + // Button to N + if (m_vo.displayType == DisplayType.Button && !m_vo.ColumnName.endsWith("_ID")) + { + log.fine("[Button=N] " + m_vo.ColumnName); + return "N"; + } + // CheckBoxes default to No + if (m_vo.displayType == DisplayType.YesNo) + { + log.fine("[YesNo=N] " + m_vo.ColumnName); + return "N"; + } + // lookups with one value + // if (DisplayType.isLookup(m_vo.displayType) && m_lookup.getSize() == 1) + // { + // /** @todo default if only one lookup value */ + // } + // IDs remain null + if (m_vo.ColumnName.endsWith("_ID")) + { + log.fine("[ID=null] " + m_vo.ColumnName); + return null; + } + // actual Numbers default to zero + if (DisplayType.isNumeric(m_vo.displayType)) + { + log.fine("[Number=0] " + m_vo.ColumnName); + return createDefault("0"); + } + + /** + * No resolution + */ + log.fine("[NONE] " + m_vo.ColumnName); + return null; + } // getDefault + + /** + * Create Default Object type. + *
+	 *		Integer 	(IDs, Integer)
+	 *		BigDecimal 	(Numbers)
+	 *		Timestamp	(Dates)
+	 *		Boolean		(YesNo)
+	 *		default: String
+	 *  
+ * @param value string + * @return type dependent converted object + */ + private Object createDefault (String value) + { + // true NULL + if (value == null || value.toString().length() == 0) + return null; + // see also MTable.readData + try + { + // IDs & Integer & CreatedBy/UpdatedBy + if (m_vo.ColumnName.endsWith("atedBy") + || m_vo.ColumnName.endsWith("_ID")) + { + try // defaults -1 => null + { + int ii = Integer.parseInt(value); + if (ii < 0) + return null; + return new Integer(ii); + } + catch (Exception e) + { + log.warning("Cannot parse: " + value + " - " + e.getMessage()); + } + return new Integer(0); + } + // Integer + if (m_vo.displayType == DisplayType.Integer) + return new Integer(value); + + // Number + if (DisplayType.isNumeric(m_vo.displayType)) + return new BigDecimal(value); + + // Timestamps + if (DisplayType.isDate(m_vo.displayType)) + { + java.util.Date date = DisplayType.getDateFormat_JDBC().parse (value); + return new Timestamp (date.getTime()); + } + + // Boolean + if (m_vo.displayType == DisplayType.YesNo) + return new Boolean ("Y".equals(value)); + + // Default + return value; + } + catch (Exception e) + { + log.log(Level.SEVERE, m_vo.ColumnName + " - " + e.getMessage()); + } + return null; + } // createDefault + + /** + * Validate initial Field Value. + * Called from MTab.dataNew and MTab.setCurrentRow when inserting + * @return true if valid + */ + public boolean validateValue() + { + // null + if (m_value == null || m_value.toString().length() == 0) + { + if (isMandatory(true)) + { + m_error = true; + return false; + } + else + return true; + } + + // Search not cached + if (getDisplayType() == DisplayType.Search && m_lookup != null) + { + // need to re-set invalid values - OK BPartner in PO Line - not OK SalesRep in Invoice + if (m_lookup.getDirect(m_value, false, true) == null) + { + log.finest(m_vo.ColumnName + " Serach not valid - set to null"); + setValue(null, m_inserting); + m_error = true; + return false; + } + return true; + } + + // cannot be validated + if (!isLookup() + || m_lookup.containsKey(m_value)) + return true; + // it's not null, a lookup and does not have the key + if (isKey() || isParentValue()) // parents/ket are not validated + return true; + + log.finest(m_vo.ColumnName + " - set to null"); + setValue(null, m_inserting); + m_error = true; + return false; + } // validateValue + + + /************************************************************************** + * Is the Column Visible ? + * @param checkContext - check environment (requires correct row position) + * @return true, if visible + */ + public boolean isDisplayed (boolean checkContext) + { + // ** static content ** + // not displayed + if (!m_vo.IsDisplayed) + return false; + // no restrictions + if (m_vo.DisplayLogic.equals("")) + return true; + + // ** dynamic content ** + if (checkContext) + { + boolean retValue = Evaluator.evaluateLogic(this, m_vo.DisplayLogic); + log.finest(m_vo.ColumnName + + " (" + m_vo.DisplayLogic + ") => " + retValue); + return retValue; + } + return true; + } // isDisplayed + + /** + * Get Variable Value (Evaluatee) + * @param variableName name + * @return value + */ + public String get_ValueAsString (String variableName) + { + return Env.getContext (m_vo.ctx, m_vo.WindowNo, variableName, true); + } // get_ValueAsString + + + /** + * Add Display Dependencies to given List. + * Source: DisplayLogic + * @param list list to be added to + */ + public void addDependencies (ArrayList list) + { + // nothing to parse + if (!m_vo.IsDisplayed || m_vo.DisplayLogic.equals("")) + return; + + StringTokenizer logic = new StringTokenizer(m_vo.DisplayLogic.trim(), "&|", false); + + while (logic.hasMoreTokens()) + { + StringTokenizer st = new StringTokenizer(logic.nextToken().trim(), "!=^", false); + while (st.hasMoreTokens()) + { + String tag = st.nextToken().trim(); // get '@tag@' + // Do we have a @variable@ ? + if (tag.indexOf('@') != -1) + { + tag = tag.replace('@', ' ').trim(); // strip 'tag' + // Add columns (they might not be a column, but then it is static) + if (!list.contains(tag)) + list.add(tag); + } + } + } + } // addDependencies + + + /************************************************************************** + * Get Column Name + * @return column name + */ + public String getColumnName() + { + return m_vo.ColumnName; + } // getColumnName + + /** + * Get Column Name or SQL .. with/without AS + * @param withAS include AS ColumnName for virtual columns in select statements + * @return column name + */ + public String getColumnSQL(boolean withAS) + { + if (m_vo.ColumnSQL != null && m_vo.ColumnSQL.length() > 0) + { + if (withAS) + return m_vo.ColumnSQL + " AS " + m_vo.ColumnName; + else + return m_vo.ColumnSQL; + } + return m_vo.ColumnName; + } // getColumnSQL + + /** + * Is Virtual Column + * @return column is virtual + */ + public boolean isVirtualColumn() + { + if (m_vo.ColumnSQL != null && m_vo.ColumnSQL.length() > 0) + return true; + return false; + } // isColumnVirtual + + /** + * Get Header + * @return header + */ + public String getHeader() + { + return m_vo.Header; + } + /** + * Get Display Type + * @return dt + */ + public int getDisplayType() + { + return m_vo.displayType; + } + /** + * Get AD_Reference_Value_ID + * @return reference value + */ + public int getAD_Reference_Value_ID() + { + return m_vo.AD_Reference_Value_ID; + } + /** + * Get AD_Window_ID + * @return window + */ + public int getAD_Window_ID() + { + return m_vo.AD_Window_ID; + } + /** + * Get Window No + * @return window no + */ + public int getWindowNo() + { + return m_vo.WindowNo; + } + /** + * Get AD_Column_ID + * @return column + */ + public int getAD_Column_ID() + { + return m_vo.AD_Column_ID; + } + /** + * Get Display Length + * @return display + */ + public int getDisplayLength() + { + return m_vo.DisplayLength; + } + /** + * Is SameLine + * @return trie if same line + */ + public boolean isSameLine() + { + return m_vo.IsSameLine; + } + /** + * Is Displayed + * @return true if displayed + */ + public boolean isDisplayed() + { + return m_vo.IsDisplayed; + } + /** + * Get DisplayLogic + * @return display logic + */ + public String getDisplayLogic() + { + return m_vo.DisplayLogic; + } + /** + * Get Default Value + * @return default + */ + public String getDefaultValue() + { + return m_vo.DefaultValue; + } + /** + * Is ReadOnly + * @return true if read only + */ + public boolean isReadOnly() + { + if (isVirtualColumn()) + return true; + return m_vo.IsReadOnly; + } + /** + * Is Updateable + * @return true if updateable + */ + public boolean isUpdateable() + { + if (isVirtualColumn()) + return false; + return m_vo.IsUpdateable; + } + /** + * Is Always Updateable + * @return true if always updateable + */ + public boolean isAlwaysUpdateable() + { + if (isVirtualColumn() || !m_vo.IsUpdateable) + return false; + return m_vo.IsAlwaysUpdateable; + } + /** + * Is Heading + * @return heading + */ + public boolean isHeading() + { + return m_vo.IsHeading; + } + /** + * Is Field Only + * @return field only + */ + public boolean isFieldOnly() + { + return m_vo.IsFieldOnly; + } + /** + * Is Encrypted Field (display) + * @return encrypted field + */ + public boolean isEncryptedField() + { + return m_vo.IsEncryptedField; + } + /** + * Is Encrypted Column (data) + * @return encrypted column + */ + public boolean isEncryptedColumn() + { + return m_vo.IsEncryptedColumn; + } + /** + * Is Selection Column + * @return selection + */ + public boolean isSelectionColumn() + { + return m_vo.IsSelectionColumn; + } + /** + * Get Obscure Type + * @return obscure + */ + public String getObscureType() + { + return m_vo.ObscureType; + } + /** + * Get Sort No + * @return sort + */ + public int getSortNo() + { + return m_vo.SortNo; + } + /** + * Get Field Length + * @return field length + */ + public int getFieldLength() + { + return m_vo.FieldLength; + } + /** + * Get VFormat + * @return format + */ + public String getVFormat() + { + return m_vo.VFormat; + } + /** + * Get Value Min + * @return min + */ + public String getValueMin() + { + return m_vo.ValueMin; + } + /** + * Get Value Max + * @return max + */ + public String getValueMax() + { + return m_vo.ValueMax; + } + /** + * Get Field Group + * @return field group + */ + public String getFieldGroup() + { + return m_vo.FieldGroup; + } + /** + * Key + * @return key + */ + public boolean isKey() + { + return m_vo.IsKey; + } + /** + * Parent Column + * @return parent column + */ + public boolean isParentColumn() + { + return m_vo.IsParent; + } + /** + * Parent Value + * @return parent value + */ + public boolean isParentValue() + { + if (m_parentChecked) + return m_vo.IsParent; + if (!DisplayType.isID(m_vo.displayType) || m_vo.TabNo == 0) + m_vo.IsParent = false; + else + { + String LinkColumnName = Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "LinkColumnName"); + if (LinkColumnName.length() == 0) + ; + else + m_vo.IsParent = m_vo.ColumnName.equals(LinkColumnName); + if (m_vo.IsParent) + log.config(m_vo.IsParent + + " - Link(" + LinkColumnName + ", W=" + m_vo.WindowNo + ",T=" + m_vo.TabNo + + ") = " + m_vo.ColumnName); + } + m_parentChecked = true; + return m_vo.IsParent; + } + /** + * Get Callout + * @return callout + */ + public String getCallout() + { + return m_vo.Callout; + } + /** + * Get AD_Process_ID + * @return process + */ + public int getAD_Process_ID() + { + return m_vo.AD_Process_ID; + } + /** + * Get Description + * @return description + */ + public String getDescription() + { + return m_vo.Description; + } + /** + * Get Help + * @return help + */ + public String getHelp() + { + return m_vo.Help; + } + /** + * Get AD_Tab_ID + * @return tab + */ + public int getAD_Tab_ID() + { + return m_vo.AD_Tab_ID; + } + /** + * Get VO + * @return value object + */ + public GridFieldVO getVO() + { + return m_vo; + } + + /** + * Is this a long (string/text) field (over 60/2=30 characters) + * @return true if long field + */ + public boolean isLongField() + { + // if (m_vo.displayType == DisplayType.String + // || m_vo.displayType == DisplayType.Text + // || m_vo.displayType == DisplayType.Memo + // || m_vo.displayType == DisplayType.TextLong + // || m_vo.displayType == DisplayType.Image) + return (m_vo.DisplayLength >= MAXDISPLAY_LENGTH/2); + // return false; + } // isLongField + + /** + * Set Value to null. + *

+ * Do not update context - called from GridTab.setCurrentRow + * Send Bean PropertyChange if there is a change + */ + public void setValue () + { + // log.fine(ColumnName + "=" + newValue); + if (m_valueNoFire) // set the old value + m_oldValue = m_value; + m_value = null; + m_inserting = false; + m_error = false; // reset error + + // Does not fire, if same value + m_propertyChangeListeners.firePropertyChange(PROPERTY, m_oldValue, m_value); + // m_propertyChangeListeners.firePropertyChange(PROPERTY, s_oldValue, null); + } // setValue + + /** + * Set Value. + *

+ * Update context, if not text or RowID; + * Send Bean PropertyChange if there is a change + * @param newValue new value + * @param inserting true if inserting + */ + public void setValue (Object newValue, boolean inserting) + { + // log.fine(ColumnName + "=" + newValue); + if (m_valueNoFire) // set the old value + m_oldValue = m_value; + m_value = newValue; + m_inserting = inserting; + m_error = false; // reset error + + // Set Context + if (m_vo.displayType == DisplayType.Text + || m_vo.displayType == DisplayType.Memo + || m_vo.displayType == DisplayType.TextLong + || m_vo.displayType == DisplayType.Binary + || m_vo.displayType == DisplayType.RowID) + ; // ignore + else if (newValue instanceof Boolean) + Env.setContext(m_vo.ctx, m_vo.WindowNo, m_vo.ColumnName, + ((Boolean)newValue).booleanValue()); + else if (newValue instanceof Timestamp) + Env.setContext(m_vo.ctx, m_vo.WindowNo, m_vo.ColumnName, (Timestamp)m_value); + else + Env.setContext(m_vo.ctx, m_vo.WindowNo, m_vo.ColumnName, + m_value==null ? null : m_value.toString()); + + // Does not fire, if same value + Object oldValue = m_oldValue; + if (inserting) + oldValue = INSERTING; + m_propertyChangeListeners.firePropertyChange(PROPERTY, oldValue, m_value); + } // setValue + + /** + * Set Value and Validate + * @param newValue value + * @param inserting insert + * @return null or error message + */ + public String setValueValidate (String newValue, boolean inserting) + { + if (newValue == null) + setValue(); + + // Data Type Test + int dt = getDisplayType(); + try + { + // Return Integer + if (dt == DisplayType.Integer + || (DisplayType.isID(dt) && getColumnName().endsWith("_ID"))) + { + int i = Integer.parseInt(newValue); + setValue (new Integer(i), inserting); + } + // Return BigDecimal + else if (DisplayType.isNumeric(dt)) + { + BigDecimal value = (BigDecimal)DisplayType.getNumberFormat(dt).parse(newValue); + setValue (value, inserting); + return null; + } + // Return Timestamp + else if (DisplayType.isDate(dt)) + { + long time = DisplayType.getDateFormat_JDBC().parse(newValue).getTime(); + setValue (new Timestamp(time), inserting); + return null; + } + // Return Boolean + else if (dt == DisplayType.YesNo) + { + Boolean value = null; + if (newValue.equals("Y")) + value = Boolean.TRUE; + else if (newValue.equals("N")) + value = Boolean.FALSE; + else + return getColumnName() + " = " + newValue + " - Must be Y/N"; + setValue (value, inserting); + return null; + } + else if (DisplayType.isText(dt)) + { + setValue (newValue, inserting); + return null; + } + else + return getColumnName() + " not mapped " + + DisplayType.getDescription(dt); + } + catch (Exception ex) + { + log.log(Level.SEVERE, "Value=" + newValue, ex); + + String error = ex.getLocalizedMessage(); + if (error == null || error.length() == 0) + error = ex.toString(); + return getColumnName() + " = " + newValue + " - " + error; + } + + // ID - test ID + if (!DisplayType.isID(dt)) + return null; + + //TODO: setValueValidate + + return null; + } // setValueValidate + + /** + * Get Value + * @return current value + */ + public Object getValue() + { + return m_value; + } // getValue + + /** + * Set old/previous Value. + * (i.e. don't fire Property change) + * Used by VColor.setField + * @param value if false property change will always be fires + */ + public void setValueNoFire (boolean value) + { + m_valueNoFire = value; + } // setOldValue + + /** + * Get old/previous Value. + * Called from MTab.processCallout + * @return old value + */ + public Object getOldValue() + { + return m_oldValue; + } // getOldValue + + /** + * Set Error Value (the value, which cuased some Error) + * @param errorValue error message + */ + public void setErrorValue (String errorValue) + { + m_errorValue = errorValue; + m_errorValueFlag = true; + } // setErrorValue + + /** + * Get Error Value (the value, which cuased some Error) AND reset it to null + * @return error value + */ + public String getErrorValue () + { + String s = m_errorValue; + m_errorValue = null; + m_errorValueFlag = false; + return s; + } // getErrorValue + + /** + * Return true, if value has Error (for HTML interface) AND reset it to false + * @return has error + */ + public boolean isErrorValue() + { + boolean b = m_errorValueFlag; + m_errorValueFlag = false; + return b; + } // isErrorValue + + /** + * Overwrite default DisplayLength + * @param length new length + */ + public void setDisplayLength (int length) + { + m_vo.DisplayLength = length; + } // setDisplayLength + + /** + * Overwrite Displayed + * @param displayed trie if displayed + */ + public void setDisplayed (boolean displayed) + { + m_vo.IsDisplayed = displayed; + } // setDisplayed + + + /** + * Create Mnemonic for field + * @return no for r/o, client, org, document no + */ + public boolean isCreateMnemonic() + { + if (isReadOnly() + || m_vo.ColumnName.equals("AD_Client_ID") + || m_vo.ColumnName.equals("AD_Org_ID") + || m_vo.ColumnName.equals("DocumentNo")) + return false; + return true; + } + + /** + * Get Label Mnemonic + * @return Mnemonic + */ + public char getMnemonic() + { + return m_mnemonic; + } // getMnemonic + + /** + * Set Label Mnemonic + * @param mnemonic Mnemonic + */ + public void setMnemonic (char mnemonic) + { + m_mnemonic = mnemonic; + } // setMnemonic + + + /** + * String representation + * @return string representation + */ + public String toString() + { + StringBuffer sb = new StringBuffer("MField["); + sb.append(m_vo.ColumnName).append("=").append(m_value).append("]"); + return sb.toString(); + } // toString + + /** + * Extended String representation + * @return string representation + */ + public String toStringX() + { + StringBuffer sb = new StringBuffer("MField["); + sb.append(m_vo.ColumnName).append("=").append(m_value) + .append(",DisplayType=").append(getDisplayType()) + .append("]"); + return sb.toString(); + } // toStringX + + + /************************************************************************* + * Remove Property Change Listener + * @param l listener + */ + public synchronized void removePropertyChangeListener(PropertyChangeListener l) + { + m_propertyChangeListeners.removePropertyChangeListener(l); + } + + /** + * Add Property Change Listener + * @param l listener + */ + public synchronized void addPropertyChangeListener(PropertyChangeListener l) + { + m_propertyChangeListeners.addPropertyChangeListener(l); + } + + + /************************************************************************** + * Create Fields. + * Used by APanel.cmd_find and Viewer.cmd_find + * @param ctx context + * @param WindowNo window + * @param TabNo tab no + * @param AD_Tab_ID tab + * @return array of all fields in display order + */ + public static GridField[] createFields (Properties ctx, int WindowNo, int TabNo, + int AD_Tab_ID) + { + ArrayList listVO = new ArrayList(); + int AD_Window_ID = 0; + boolean readOnly = false; + + String sql = GridFieldVO.getSQL(ctx); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Tab_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + GridFieldVO vo = GridFieldVO.create(ctx, WindowNo, TabNo, + AD_Window_ID, AD_Tab_ID, readOnly, rs); + listVO.add(vo); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + // + GridField[] retValue = new GridField[listVO.size()]; + for (int i = 0; i < listVO.size(); i++) + retValue[i] = new GridField ((GridFieldVO)listVO.get(i)); + return retValue; + } // createFields + + +} // MField diff --git a/base/src/org/compiere/model/GridTab.java b/base/src/org/compiere/model/GridTab.java new file mode 100644 index 0000000000..7b22b55c8b --- /dev/null +++ b/base/src/org/compiere/model/GridTab.java @@ -0,0 +1,2446 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.beans.*; +import java.io.*; +import java.sql.*; +import java.text.*; +import java.util.*; + +import java.util.logging.*; +import javax.swing.event.*; +import org.compiere.util.*; + +/** + * Tab Model. + * - a combination of AD_Tab (the display attributes) and AD_Table information. + *

+ * The Tab owns also it's Table model + * and listens to data changes to update the Field values. + * + *

+ * The Tab maintains the bound property: CurrentRow + * + *

+ *  Event Hierarchies:
+ *      - dataChanged (from MTable)
+ *          - setCurrentRow
+ *              - Update all Field Values
+ *
+ *      - setValue
+ *          - Update Field Value
+ *          - Callout
+ *  
+ * @author Jorg Janke + * @version $Id: GridTab.java,v 1.10 2006/10/02 05:18:39 jjanke Exp $ + */ +public class GridTab implements DataStatusListener, Evaluatee, Serializable +{ + /** + * Create Tab (Model) from Value Object. + *

+ * MTab provides a property listener for changed rows and a + * DataStatusListener for communicating changes of the underlying data + * @param vo Value Object + */ + public GridTab(GridTabVO vo) + { + m_vo = vo; + // Create MTable + m_mTable = new GridTable (m_vo.ctx, m_vo.AD_Table_ID, m_vo.TableName, m_vo.WindowNo, m_vo.TabNo, true); + m_mTable.setReadOnly(m_vo.IsReadOnly || m_vo.IsView); + m_mTable.setDeleteable(m_vo.IsDeleteable); + // Load Tab + // if (vo.TabNo == 0) + initTab(false); + // else + // { + // m_loader = new Loader(); + // m_loader.setPriority(Thread.MIN_PRIORITY); + // m_loader.start(); + // } + // waitLoadCompete(); + } // GridTab + + /** Value Object */ + private GridTabVO m_vo; + + /** The Table Model for Query */ + private GridTable m_mTable = null; + + private String m_keyColumnName = ""; + private String m_linkColumnName = ""; + private String m_extendedWhere; + /** Attachments */ + private HashMap m_Attachments = null; + /** Chats */ + private HashMap m_Chats = null; + /** Locks */ + private ArrayList m_Lock = null; + + /** Current Row */ + private int m_currentRow = -1; + + /** Property Change */ + private PropertyChangeSupport m_propertyChangeSupport = new PropertyChangeSupport(this); + /** Property Change Type */ + public static final String PROPERTY = "CurrentRow"; + /** A list of event listeners for this component. */ + protected EventListenerList m_listenerList = new EventListenerList(); + /** Current Data Status Event */ + private DataStatusEvent m_DataStatusEvent = null; + /** Query */ + private MQuery m_query = new MQuery(); + private String m_oldQuery = "0=9"; + private String m_linkValue = "999999"; + + /** Order By Array if SortNo 1..3 */ + private String[] m_OrderBys = new String[3]; + /** List of Key Parents */ + private ArrayList m_parents = new ArrayList(2); + + /** Map of ColumnName of source field (key) and the dependant field (value) */ + private MultiMap m_depOnField = new MultiMap(); + + /** Async Loader */ + private Loader m_loader = null; + /** Async Loading complete */ + private volatile boolean m_loadComplete = false; + /** Is Tab Included in other Tab */ + private boolean m_included = false; + + /** Logger */ + protected CLogger log = CLogger.getCLogger(getClass()); + + + /************************************************************************** + * Tab loader for Tabs > 0 + */ + class Loader extends Thread + { + /** + * Async Loading of Tab > 0 + */ + public void run() + { + initTab (true); + } // run + } // Loader + + /** + * Wait until load is complete + */ + private void waitLoadCompete() + { + if (m_loadComplete) + return; + // + m_loader.setPriority(Thread.NORM_PRIORITY); + log.config (""); + while (m_loader.isAlive()) + { + try + { + Thread.sleep(100); // 1/10 sec + } + catch (Exception e) + { + log.log(Level.SEVERE, "", e); + } + } + log.config ("fini"); + } // waitLoadComplete + + /** + * Initialize Tab with record from AD_Tab_v + * @param async async + * @return true, if correctly initialized (ignored) + */ + protected boolean initTab (boolean async) + { + log.fine("#" + m_vo.TabNo + " - Async=" + async + " - Where=" + m_vo.WhereClause); + + m_extendedWhere = m_vo.WhereClause; + + // Get Field Data + if (!loadFields()) + { + m_loadComplete = true; + return false; + } + + // Order By + m_mTable.setOrderClause(getOrderByClause(m_vo.onlyCurrentRows)); + + if (async) + log.fine("#" + m_vo.TabNo + " - Async=" + async + " - fini"); + m_loadComplete = true; + return true; + } // initTab + + /** + * Dispose - clean up resources + */ + protected void dispose() + { + log.fine("#" + m_vo.TabNo); + m_OrderBys = null; + // + m_parents.clear(); + m_parents = null; + // + m_mTable.close (true); // also disposes Fields + m_mTable = null; + // + m_depOnField.clear(); + m_depOnField = null; + if (m_Attachments != null) + m_Attachments.clear(); + m_Attachments = null; + if (m_Chats != null) + m_Chats.clear(); + m_Chats = null; + // + m_vo.Fields.clear(); + m_vo.Fields = null; + m_vo = null; + } // dispose + + + /** + * Get Field data and add to MTable, if it's required or displayed. + * Reqiored fields are keys, parents, or standard Columns + * @return true if fields loaded + */ + private boolean loadFields() + { + log.fine("#" + m_vo.TabNo); + + if (m_vo.Fields == null) + return false; + + // Add Fields + for (int f = 0; f < m_vo.Fields.size(); f++) + { + GridFieldVO voF = (GridFieldVO)m_vo.Fields.get(f); + // Add Fields to Table + if (voF != null) + { + GridField field = new GridField (voF); + String columnName = field.getColumnName(); + // Record Info + if (field.isKey()) + m_keyColumnName = columnName; + // Parent Column(s) + if (field.isParentColumn()) + m_parents.add(columnName); + // Order By + int sortNo = field.getSortNo(); + if (sortNo == 0) + ; + else if (Math.abs(sortNo) == 1) + { + m_OrderBys[0] = columnName; + if (sortNo < 0) + m_OrderBys[0] += " DESC"; + } + else if (Math.abs(sortNo) == 2) + { + m_OrderBys[1] = columnName; + if (sortNo < 0) + m_OrderBys[1] += " DESC"; + } + else if (Math.abs(sortNo) == 3) + { + m_OrderBys[2] = columnName; + if (sortNo < 0) + m_OrderBys[2] += " DESC"; + } + // Add field + m_mTable.addField(field); + + // List of ColumnNames, this field is dependent on + ArrayList list = field.getDependentOn(); + for (int i = 0; i < list.size(); i++) + m_depOnField.put(list.get(i), field); // ColumnName, Field + // Add fields all fields are dependent on + if (columnName.equals("IsActive") + || columnName.equals("Processed") + || columnName.equals("Processing")) + m_depOnField.put(columnName, null); + } + } // for all fields + + // Add Standard Fields + if (m_mTable.getField("Created") == null) + { + GridField created = new GridField (GridFieldVO.createStdField(m_vo.ctx, + m_vo.WindowNo, m_vo.TabNo, + m_vo.AD_Window_ID, m_vo.AD_Tab_ID, false, true, true)); + m_mTable.addField(created); + } + if (m_mTable.getField("CreatedBy") == null) + { + GridField createdBy = new GridField (GridFieldVO.createStdField(m_vo.ctx, + m_vo.WindowNo, m_vo.TabNo, + m_vo.AD_Window_ID, m_vo.AD_Tab_ID, false, true, false)); + m_mTable.addField(createdBy); + } + if (m_mTable.getField("Updated") == null) + { + GridField updated = new GridField (GridFieldVO.createStdField(m_vo.ctx, + m_vo.WindowNo, m_vo.TabNo, + m_vo.AD_Window_ID, m_vo.AD_Tab_ID, false, false, true)); + m_mTable.addField(updated); + } + if (m_mTable.getField("UpdatedBy") == null) + { + GridField updatedBy = new GridField (GridFieldVO.createStdField(m_vo.ctx, + m_vo.WindowNo, m_vo.TabNo, + m_vo.AD_Window_ID, m_vo.AD_Tab_ID, false, false, false)); + m_mTable.addField(updatedBy); + } + return true; + } // loadFields + + /** + * Get a list of variables, this tab is dependent on. + * - for display purposes + * @return ArrayList + */ + public ArrayList getDependentOn() + { + ArrayList list = new ArrayList(); + // Display + Evaluator.parseDepends(list, m_vo.DisplayLogic); + // + if (list.size() > 0 && CLogMgt.isLevelFiner()) + { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < list.size(); i++) + sb.append(list.get(i)).append(" "); + log.finer("(" + m_vo.Name + ") " + sb.toString()); + } + return list; + } // getDependentOn + + /** + * Get Display Logic + * @return display logic + */ + public String getDisplayLogic() + { + return m_vo.DisplayLogic; + } // getDisplayLogic + + /** + * Get TableModel. + * Do not directly communicate with the table model, + * but through the methods of this class + * @return Table Model + */ + public GridTable getTableModel() + { + return m_mTable; + } // getTableModel + + /** + * Get Tab Icon + * @return Icon + */ + public javax.swing.Icon getIcon() + { + if (m_vo.AD_Image_ID == 0) + return null; + // + /** @todo Load Image */ + return null; + } // getIcon + + + /************************************************************************** + * Has this field dependents ? + * @param columnName column name + * @return true if column has dependent + */ + public boolean hasDependants (String columnName) + { + // m_depOnField.printToLog(); + return m_depOnField.containsKey(columnName); + } // isDependentOn + + /** + * Get dependents fields of columnName + * @param columnName column name + * @return ArrayList with GridFields dependent on columnName + */ + public ArrayList getDependantFields (String columnName) + { + return m_depOnField.getValues(columnName); + } // getDependentFields + + + /************************************************************************** + * Set Query + * @param query query + */ + public void setQuery(MQuery query) + { + if (query == null) + m_query = new MQuery(); + else + m_query = query; + } // setQuery + + /** + * Get Query + * @return query + */ + public MQuery getQuery() + { + return m_query; + } // getQuery + + /** + * Is Query Active + * @return true if query active + */ + public boolean isQueryActive() + { + if (m_query != null) + return m_query.isActive(); + return false; + } // isQueryActive + + /** + * Is Query New Record + * @return true if query active + */ + public boolean isQueryNewRecord() + { + if (m_query != null) + return m_query.isNewRecordQuery(); + return false; + } // isQueryNewRecord + + /** + * Enable Events - enable data events of tabs (add listeners) + */ + public void enableEvents() + { + // Setup Events + m_mTable.addDataStatusListener(this); + // m_mTable.addTableModelListener(this); + } // enableEvents + + /** + * Assemble whereClause and query MTable and position to row 0. + *

+	 *		Scenarios:
+	 *		- Never opened 					(full query)
+	 *		- query changed 				(full query)
+	 *		- Detail link value changed		(full query)
+	 *		- otherwise 					(refreshAll)
+	 *  
+ * @param onlyCurrentRows only current rows (1 day) + */ + public void query (boolean onlyCurrentRows) + { + query (onlyCurrentRows, 0, 0); + } // query + + /** + * Assemble whereClause and query MTable and position to row 0. + *
+	 *		Scenarios:
+	 *		- Never opened 					(full query)
+	 *		- query changed 				(full query)
+	 *		- Detail link value changed		(full query)
+	 *		- otherwise 					(refreshAll)
+	 *  
+ * @param onlyCurrentRows only current rows + * @param onlyCurrentDays if only current row, how many days back + * @param maxRows maximim rows or 0 for all + */ + public void query (boolean onlyCurrentRows, int onlyCurrentDays, int maxRows) + { + log.fine("#" + m_vo.TabNo + + " - Only Current Rows=" + onlyCurrentRows + + ", Days=" + onlyCurrentDays + ", Detail=" + isDetail()); + // is it same query? + boolean refresh = m_oldQuery.equals(m_query.getWhereClause()) + && m_vo.onlyCurrentRows == onlyCurrentRows && m_vo.onlyCurrentDays == onlyCurrentDays; + m_oldQuery = m_query.getWhereClause(); + m_vo.onlyCurrentRows = onlyCurrentRows; + m_vo.onlyCurrentDays = onlyCurrentDays; + + /** + * Set Where Clause + */ + // Tab Where Clause + StringBuffer where = new StringBuffer(m_vo.WhereClause); + if (m_vo.onlyCurrentDays > 0) + { + if (where.length() > 0) + where.append(" AND "); + where.append("Created >= "); + if (DB.isDerby()) + where.append("dateadd(dd,-").append(m_vo.onlyCurrentDays).append(",getdate())"); + else + where.append("SysDate-").append(m_vo.onlyCurrentDays); + } + // Detail Query + if (isDetail()) + { + String lc = getLinkColumnName(); + if (lc.equals("")) + log.severe ("No link column"); + else + { + String value = Env.getContext(m_vo.ctx, m_vo.WindowNo, lc); + // Same link value? + if (refresh) + refresh = m_linkValue.equals(value); + m_linkValue = value; + // Check validity + if (value.length() == 0) + log.severe ("No value for link column " + lc); + else + { + // we have column and value + if (where.length() != 0) + where.append(" AND "); + where.append(lc).append("="); + if (lc.endsWith("_ID")) + where.append(value); + else + where.append("'").append(value).append("'"); + } + } + } // isDetail + + m_extendedWhere = where.toString(); + + // Final Query + if (m_query.isActive()) + { + String q = validateQuery(m_query); + if (q != null) + { + if (where.length() > 0 ) + where.append(" AND "); + where.append(q); + } + } + + /** + * Query + */ + log.fine("#" + m_vo.TabNo + " - " + where); + if (m_mTable.isOpen()) + { + if (refresh) + m_mTable.dataRefreshAll(); + else + m_mTable.dataRequery(where.toString(), m_vo.onlyCurrentRows && !isDetail(), onlyCurrentDays); + } + else + { + m_mTable.setSelectWhereClause(where.toString(), m_vo.onlyCurrentRows && !isDetail(), onlyCurrentDays); + m_mTable.open(maxRows); + } + // Go to Record 0 + setCurrentRow(0, true); + } // query + + /** + * Validate Query. + * If query column is not a tab column create EXISTS query + * @param query query + * @return where clause + */ + private String validateQuery (MQuery query) + { + if (query == null || query.getRestrictionCount() == 0) + return null; + + // Check: only one restriction + if (query.getRestrictionCount() != 1) + { + log.fine("Ignored(More than 1 Restriction): " + query); + return query.getWhereClause(); + } + + String colName = query.getColumnName(0); + if (colName == null) + { + log.fine("Ignored(No Column): " + query); + return query.getWhereClause(); + } + // a '(' in the name = function - don't try to resolve + if (colName.indexOf('(') != -1) + { + log.fine("Ignored(Function): " + colName); + return query.getWhereClause(); + } + // OK - Query is valid + + // Zooms to the same Window (Parents, ..) + String refColName = null; + if (colName.equals("R_RequestRelated_ID")) + refColName = "R_Request_ID"; + else if (colName.startsWith("C_DocType")) + refColName = "C_DocType_ID"; + if (refColName != null) + { + query.setColumnName(0, refColName); + if (getField(refColName) != null) + { + log.fine("Column " + colName + " replaced with synonym " + refColName); + return query.getWhereClause(); + } + refColName = null; + } + + // Simple Query. + if (getField(colName) != null) + { + log.fine("Field Found: " + colName); + return query.getWhereClause(); + } + + // Find Refernce Column e.g. BillTo_ID -> C_BPartner_Location_ID + String sql = "SELECT cc.ColumnName " + + "FROM AD_Column c" + + " INNER JOIN AD_Ref_Table r ON (c.AD_Reference_Value_ID=r.AD_Reference_ID)" + + " INNER JOIN AD_Column cc ON (r.AD_Key=cc.AD_Column_ID) " + + "WHERE c.AD_Reference_ID IN (18,30)" // Table/Search + + " AND c.ColumnName=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setString(1, colName); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + refColName = rs.getString(1); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "(ref) - Column=" + colName, e); + return query.getWhereClause(); + } + // Reference Column found + if (refColName != null) + { + query.setColumnName(0, refColName); + if (getField(refColName) != null) + { + log.fine("Column " + colName + " replaced with " + refColName); + return query.getWhereClause(); + } + colName = refColName; + } + + // Column NOT in Tab - create EXISTS subquery + String tableName = null; + String tabKeyColumn = getKeyColumnName(); + // Column=SalesRep_ID, Key=AD_User_ID, Query=SalesRep_ID=101 + + sql = "SELECT t.TableName " + + "FROM AD_Column c" + + " INNER JOIN AD_Table t ON (c.AD_Table_ID=t.AD_Table_ID) " + + "WHERE c.ColumnName=? AND IsKey='Y'" // #1 Link Column + + " AND EXISTS (SELECT * FROM AD_Column cc" + + " WHERE cc.AD_Table_ID=t.AD_Table_ID AND cc.ColumnName=?)"; // #2 Tab Key Column + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setString(1, colName); + pstmt.setString(2, tabKeyColumn); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + tableName = rs.getString(1); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "Column=" + colName + ", Key=" + tabKeyColumn, e); + return null; + } + + // Special Reference Handling + if (tabKeyColumn.equals("AD_Reference_ID")) + { + // Column=AccessLevel, Key=AD_Reference_ID, Query=AccessLevel='6' + sql = "SELECT AD_Reference_ID FROM AD_Column WHERE ColumnName=?"; + int AD_Reference_ID = DB.getSQLValue(null, sql, colName); + return "AD_Reference_ID=" + AD_Reference_ID; + } + + // Causes could be functions in query + // e.g. Column=UPPER(Name), Key=AD_Element_ID, Query=UPPER(AD_Element.Name) LIKE '%CUSTOMER%' + if (tableName == null) + { + log.info ("Not successfull - Column=" + + colName + ", Key=" + tabKeyColumn + + ", Query=" + query); + return query.getWhereClause(); + } + + query.setTableName("xx"); + StringBuffer result = new StringBuffer ("EXISTS (SELECT * FROM ") + .append(tableName).append(" xx WHERE ") + .append(query.getWhereClause(true)) + .append(" AND xx.").append(tabKeyColumn).append("=") + .append(getTableName()).append(".").append(tabKeyColumn).append(")"); + log.fine(result.toString()); + return result.toString(); + } // validateQuery + + + /************************************************************************** + * Refresh all data + */ + public void dataRefreshAll () + { + log.fine("#" + m_vo.TabNo); + /** @todo does not work with alpha key */ + int keyNo = m_mTable.getKeyID(m_currentRow); + m_mTable.dataRefreshAll(); + // Should use RowID - not working for tables with multiple keys + if (keyNo != -1) + { + if (keyNo != m_mTable.getKeyID(m_currentRow)) // something changed + { + int size = getRowCount(); + for (int i = 0; i < size; i++) + { + if (keyNo == m_mTable.getKeyID(i)) + { + m_currentRow = i; + break; + } + } + } + } + setCurrentRow(m_currentRow, true); + } // dataRefreshAll + + /** + * Refresh current row data + */ + public void dataRefresh () + { + dataRefresh (m_currentRow); + } // dataRefresh + + /** + * Refresh row data + * @param row index + */ + public void dataRefresh (int row) + { + log.fine("#" + m_vo.TabNo + " - row=" + row); + m_mTable.dataRefresh(row); + setCurrentRow(row, true); + } // dataRefresh + + + /************************************************************************** + * Uncoditionally Save data + * @param manualCmd if true, no vetoable PropertyChange will be fired for save confirmation from MTable + * @return true if save complete (or nor required) + */ + public boolean dataSave(boolean manualCmd) + { + log.fine("#" + m_vo.TabNo + " - row=" + m_currentRow); + try + { + boolean retValue = (m_mTable.dataSave(manualCmd) == GridTable.SAVE_OK); + if (manualCmd) + setCurrentRow(m_currentRow, false); + return retValue; + } + catch (Exception e) + { + log.log(Level.SEVERE, "#" + m_vo.TabNo + " - row=" + m_currentRow, e); + } + return false; + } // dataSave + + + /** + * Do we need to Save? + * @param rowChange row change + * @param onlyRealChange if true the value of a field was actually changed + * (e.g. for new records, which have not been changed) - default false + * @return true it needs to be saved + */ + public boolean needSave (boolean rowChange, boolean onlyRealChange) + { + if (rowChange) + { + return m_mTable.needSave(-2, onlyRealChange); + } + else + { + if (onlyRealChange) + return m_mTable.needSave(); + else + return m_mTable.needSave(onlyRealChange); + } + } // isDataChanged + + /** + * Ignore data changes + */ + public void dataIgnore() + { + log.fine("#" + m_vo.TabNo); + m_mTable.dataIgnore(); + setCurrentRow(m_currentRow, false); // re-load data + log.fine("#" + m_vo.TabNo + "- fini"); + } // dataIgnore + + + /** + * Create (copy) new Row + * and process Callouts + * @param copy copy + * @return true if copied/new + */ + public boolean dataNew (boolean copy) + { + log.fine("#" + m_vo.TabNo); + if (!isInsertRecord()) + { + log.warning ("Inset Not allowed in TabNo=" + m_vo.TabNo); + return false; + } + // Prevent New Where Main Record is processed + if (m_vo.TabNo > 0) + { + boolean processed = "Y".equals(Env.getContext(m_vo.ctx, m_vo.WindowNo, "Processed")); + // boolean active = "Y".equals(Env.getContext(m_vo.ctx, m_vo.WindowNo, "IsActive")); + if (processed) + { + log.warning ("Not allowed in TabNo=" + m_vo.TabNo + " -> Processed=" + processed); + return false; + } + log.finest("Processed=" + processed); + } + boolean retValue = m_mTable.dataNew (m_currentRow, copy); + if (!retValue) + return retValue; + setCurrentRow(m_currentRow + 1, true); + // process all Callouts (no dependency check - assumed that settings are valid) + for (int i = 0; i < getFieldCount(); i++) + processCallout(getField(i)); + // check validity of defaults + for (int i = 0; i < getFieldCount(); i++) + { + getField(i).refreshLookup(); + getField(i).validateValue(); + } + m_mTable.setChanged(false); + return retValue; + } // dataNew + + /** + * Delete current Row + * @return true if deleted + */ + public boolean dataDelete() + { + log.fine("#" + m_vo.TabNo + " - row=" + m_currentRow); + boolean retValue = m_mTable.dataDelete(m_currentRow); + setCurrentRow(m_currentRow, true); + return retValue; + } // dataDelete + + + /** + * Get Name of Tab + * @return name + */ + public String getName() + { + return m_vo.Name; + } // getName + + /** + * Get Description of Tab + * @return description + */ + public String getDescription() + { + return m_vo.Description; + } // getDescription + + /** + * Get Help of Tab + * @return help + */ + public String getHelp() + { + return m_vo.Help; + } // getHelp + + /** + * Get Tab Level + * @return tab level + */ + public int getTabLevel() + { + return m_vo.TabLevel; + } // getTabLevel + + /** + * Get Commit Warning + * @return commit warning + */ + public String getCommitWarning() + { + return m_vo.CommitWarning; + } // getCommitWarning + + /** + * Return Table Model + * @return MTable + */ + protected GridTable getMTable() + { + return m_mTable; + } // getMTable + + /** + * Return the name of the key column - may be "" + * @return key column name + */ + public String getKeyColumnName() + { + return m_keyColumnName; + } // getKeyColumnName + + /** + * Return Name of link column + * @return link column name + */ + public String getLinkColumnName() + { + return m_linkColumnName; + } // getLinkColumnName + + /** + * Set Name of link column. + * Set from MWindow.loadTabData + * Used in MTab.isCurreny, (.setCurrentRow) .query - APanel.cmd_report + * and MField.isEditable and .isDefault via context + * @param linkColumnName name of column - or sets name to AD_Column_ID, if exists + */ + public void setLinkColumnName (String linkColumnName) + { + if (linkColumnName != null) + m_linkColumnName = linkColumnName; + else + { + if (m_vo.AD_Column_ID == 0) + return; + // we have a link column identified (primary parent column) + else + { + String SQL = "SELECT ColumnName FROM AD_Column WHERE AD_Column_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(SQL, null); + pstmt.setInt(1, m_vo.AD_Column_ID); // Parent Link Column + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + m_linkColumnName = rs.getString(1); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "", e); + } + log.fine("AD_Column_ID=" + m_vo.AD_Column_ID + " - " + m_linkColumnName); + } + } + Env.setContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "LinkColumnName", m_linkColumnName); + } // setLinkColumnName + + /** + * Is the tab current?. + *
+	 *	Yes 	- Table must be open
+	 *			- Query String is the same
+	 *			- Not Detail
+	 *			- Old link column value is same as current one
+	 *  
+ * @return true if current + */ + public boolean isCurrent() + { + // Open? + if (!m_mTable.isOpen()) + return false; + // Same Query + if (!m_oldQuery.equals(m_query.getWhereClause())) + return false; + // Detail? + if (!isDetail()) + return true; + // Same link column value + String value = Env.getContext(m_vo.ctx, m_vo.WindowNo, getLinkColumnName()); + return m_linkValue.equals(value); + } // isCurrent + + /** + * Is the tab/table currently open + * @return true if open + */ + public boolean isOpen() + { + // Open? + if (m_mTable != null) + return m_mTable.isOpen(); + return false; + } // isCurrent + + + /** + * Is Tab Incluced in other Tab + * @return true if included + */ + public boolean isIncluded() + { + return m_included; + } // isIncluded + + /** + * Is Tab Incluced in other Tab + * @param isIncluded true if included + */ + public void setIncluded(boolean isIncluded) + { + m_included = isIncluded; + } // setIncluded + + /** + * Are Only Current Rows displayed + * @return true if no history + */ + public boolean isOnlyCurrentRows() + { + return m_vo.onlyCurrentRows; + } // isOnlyCurrentRows + /** + * Return Parent ArrayList + * @return parent column names + */ + public ArrayList getParentColumnNames() + { + return m_parents; + } // getParentColumnNames + + /** + * Get Tree ID of this tab + * @return ID + */ + private int getTreeID() + { + log.fine(m_vo.TableName); + String SQL = "SELECT * FROM AD_ClientInfo WHERE AD_Client=" + + Env.getContext(m_vo.ctx, m_vo.WindowNo, "AD_Client_ID") + + " ORDER BY AD_Org DESC"; + // + if (m_vo.TableName.equals("AD_Menu")) + return 10; // MM + else if (m_vo.TableName.equals("C_ElementValue")) + return 20; // EV + else if (m_vo.TableName.equals("M_Product")) + return 30; // PR + else if (m_vo.TableName.equals("C_BPartner")) + return 40; // BP + else if (m_vo.TableName.equals("AD_Org")) + return 50; // OO + else if (m_vo.TableName.equals("C_Project")) + return 60; // PJ + return 0; + } // getTreeID + + /** + * Returns true if this is a detail record + * @return true if not parent tab + */ + public boolean isDetail() + { + // We have IsParent columns and/or a link column + if (m_parents.size() > 0 || m_vo.AD_Column_ID != 0) + return true; + return false; + } // isDetail + + /** + * Is Printed (Document can be printed) + * @return true if printing + */ + public boolean isPrinted() + { + return m_vo.AD_Process_ID != 0; + } // isPrinted + + /** + * Get WindowNo + * @return window no + */ + public int getWindowNo() + { + return m_vo.WindowNo; + } // getWindowNo + + /** + * Get TabNo + * @return tab no + */ + public int getTabNo() + { + return m_vo.TabNo; + } // getTabNo + + /** + * Get Process ID + * @return Process ID + */ + public int getAD_Process_ID() + { + return m_vo.AD_Process_ID; + } // getAD_Process_ID + + /** + * Is High Volume? + * @return true if high volumen table + */ + public boolean isHighVolume() + { + return m_vo.IsHighVolume; + } // isHighVolume + + /** + * Is Read Only? + * @return true if read only + */ + public boolean isReadOnly() + { + if (m_vo.IsReadOnly) + return true; + + // no restrictions + if (m_vo.ReadOnlyLogic == null || m_vo.ReadOnlyLogic.equals("")) + return m_vo.IsReadOnly; + + // ** dynamic content ** uses get_ValueAsString + boolean retValue = Evaluator.evaluateLogic(this, m_vo.ReadOnlyLogic); + log.finest(m_vo.Name + + " (" + m_vo.ReadOnlyLogic + ") => " + retValue); + return retValue; + } // isReadOnly + + /** + * Tab contains Always Update Field + * @return true if field with always updateable + */ + public boolean isAlwaysUpdateField() + { + for (int i = 0; i < m_mTable.getColumnCount(); i++) + { + GridField field = m_mTable.getField(i); + if (field.isAlwaysUpdateable()) + return true; + } + return false; + } // isAlwaysUpdateField + + /** + * Can we Insert Records? + * @return true not read only and allowed + */ + public boolean isInsertRecord() + { + if (isReadOnly()) + return false; + return m_vo.IsInsertRecord; + } // isInsertRecord + + /** + * Is the Tab Visible. + * Called when constructing the window. + * @return true, if displayed + */ + public boolean isDisplayed () + { + // no restrictions + String dl = m_vo.DisplayLogic; + if (dl == null || dl.equals("")) + return true; + + // ** dynamic content ** + String parsed = Env.parseContext (m_vo.ctx, 0, dl, false, false).trim(); + if (parsed.length() == 0) + return true; + boolean retValue = Evaluator.evaluateLogic(this, dl); + log.config(m_vo.Name + " (" + dl + ") => " + retValue); + return retValue; + } // isDisplayed + + /** + * Get Variable Value (Evaluatee) + * @param variableName name + * @return value + */ + public String get_ValueAsString (String variableName) + { + return Env.getContext (m_vo.ctx, m_vo.WindowNo, variableName, true); + } // get_ValueAsString + + /** + * Is Single Row + * @return true if single row + */ + public boolean isSingleRow() + { + return m_vo.IsSingleRow; + } // isSingleRow; + + /** + * Set Single Row. + * Temporary store of current value + * @param isSingleRow toggle + */ + public void setSingleRow (boolean isSingleRow) + { + m_vo.IsSingleRow = isSingleRow; + } // setSingleRow + + + /** + * Has Tree + * @return true if tree exists + */ + public boolean isTreeTab() + { + return m_vo.HasTree; + } // isTreeTab + + /** + * Get Tab ID + * @return Tab ID + */ + public int getAD_Tab_ID() + { + return m_vo.AD_Tab_ID; + } // getAD_Tab_ID + + /** + * Get Table ID + * @return Table ID + */ + public int getAD_Table_ID() + { + return m_vo.AD_Table_ID; + } // getAD_Table_ID + + /** + * Get Window ID + * @return Window ID + */ + public int getAD_Window_ID() + { + return m_vo.AD_Window_ID; + } // getAD_Window_ID + + /** + * Get Included Tab ID + * @return Included_Tab_ID + */ + public int getIncluded_Tab_ID() + { + return m_vo.Included_Tab_ID; + } // getIncluded_Tab_ID + + /** + * Get TableName + * @return Table Name + */ + public String getTableName() + { + return m_vo.TableName; + } // getTableName + + /** + * Get Tab Where Clause + * @return where clause + */ + public String getWhereClause() + { + return m_vo.WhereClause; + } // getWhereClause + + /** + * Is Sort Tab + * @return true if sort tab + */ + public boolean isSortTab() + { + return m_vo.IsSortTab; + } // isSortTab + + /** + * Get Order column for sort tab + * @return AD_Column_ID + */ + public int getAD_ColumnSortOrder_ID() + { + return m_vo.AD_ColumnSortOrder_ID; + } // getAD_ColumnSortOrder_ID + + /** + * Get Yes/No column for sort tab + * @return AD_Column_ID + */ + public int getAD_ColumnSortYesNo_ID() + { + return m_vo.AD_ColumnSortYesNo_ID; + } // getAD_ColumnSortYesNo_ID + + + /************************************************************************** + * Get extended Where Clause (parent link) + * @return parent link + */ + public String getWhereExtended() + { + return m_extendedWhere; + } // getWhereExtended + + /** + * Get Order By Clause + * @param onlyCurrentRows only current rows + * @return Order By Clause + */ + private String getOrderByClause(boolean onlyCurrentRows) + { + // First Prio: Tab Order By + if (m_vo.OrderByClause.length() > 0) + return m_vo.OrderByClause; + + // Second Prio: Fields (save it) + m_vo.OrderByClause = ""; + for (int i = 0; i < 3; i++) + { + String order = m_OrderBys[i]; + if (order != null && order.length() > 0) + { + if (m_vo.OrderByClause.length() > 0) + m_vo.OrderByClause += ","; + m_vo.OrderByClause += order; + } + } + if (m_vo.OrderByClause.length() > 0) + return m_vo.OrderByClause; + + // Third Prio: onlyCurrentRows + m_vo.OrderByClause = "Created"; + if (onlyCurrentRows && !isDetail()) // first tab only + m_vo.OrderByClause += " DESC"; + return m_vo.OrderByClause; + } // getOrderByClause + + + /************************************************************************** + * Transaction support. + * Depending on Table returns transaction info + * @return info + */ + public String getTrxInfo() + { + // InvoiceBatch + if (m_vo.TableName.startsWith("C_InvoiceBatch")) + { + int Record_ID = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, "C_InvoiceBatch_ID"); + log.fine(m_vo.TableName + " - " + Record_ID); + MessageFormat mf = null; + try + { + mf = new MessageFormat(Msg.getMsg(Env.getAD_Language(m_vo.ctx), "InvoiceBatchSummary")); + } + catch (Exception e) + { + log.log(Level.SEVERE, "InvoiceBatchSummary=" + Msg.getMsg(Env.getAD_Language(m_vo.ctx), "InvoiceBatchSummary"), e); + } + if (mf == null) + return " "; + /********************************************************************** + * ** Message: ExpenseSummary ** + * {0} Line(s) {1,number,#,##0.00} - Total: {2,number,#,##0.00} + * + * {0} - Number of lines + * {1} - Toral + * {2} - Currency + */ + Object[] arguments = new Object[3]; + boolean filled = false; + // + String sql = "SELECT COUNT(*), NVL(SUM(LineNetAmt),0), NVL(SUM(LineTotalAmt),0) " + + "FROM C_InvoiceBatchLine " + + "WHERE C_InvoiceBatch_ID=? AND IsActive='Y'"; + // + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, Record_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + // {0} - Number of lines + Integer lines = new Integer(rs.getInt(1)); + arguments[0] = lines; + // {1} - Line net + Double net = new Double(rs.getDouble(2)); + arguments[1] = net; + // {2} - Line net + Double total = new Double(rs.getDouble(3)); + arguments[2] = total; + filled = true; + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, m_vo.TableName + "\nSQL=" + sql, e); + } + if (filled) + return mf.format (arguments); + return " "; + } // InvoiceBatch + + // Order || Invoice + else if (m_vo.TableName.startsWith("C_Order") || m_vo.TableName.startsWith("C_Invoice")) + { + int Record_ID; + boolean isOrder = m_vo.TableName.startsWith("C_Order"); + // + StringBuffer sql = new StringBuffer("SELECT COUNT(*) AS Lines,c.ISO_Code,o.TotalLines,o.GrandTotal," + + "currencyBase(o.GrandTotal,o.C_Currency_ID,o.DateAcct, o.AD_Client_ID,o.AD_Org_ID) AS ConvAmt "); + if (isOrder) + { + Record_ID = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, "C_Order_ID"); + sql.append("FROM C_Order o" + + " INNER JOIN C_Currency c ON (o.C_Currency_ID=c.C_Currency_ID)" + + " INNER JOIN C_OrderLine l ON (o.C_Order_ID=l.C_Order_ID) " + + "WHERE o.C_Order_ID=? "); + } + else + { + Record_ID = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, "C_Invoice_ID"); + sql.append("FROM C_Invoice o" + + " INNER JOIN C_Currency c ON (o.C_Currency_ID=c.C_Currency_ID)" + + " INNER JOIN C_InvoiceLine l ON (o.C_Invoice_ID=l.C_Invoice_ID) " + + "WHERE o.C_Invoice_ID=? "); + } + sql.append("GROUP BY o.C_Currency_ID, c.ISO_Code, o.TotalLines, o.GrandTotal, o.DateAcct, o.AD_Client_ID, o.AD_Org_ID"); + + log.fine(m_vo.TableName + " - " + Record_ID); + MessageFormat mf = null; + try + { + mf = new MessageFormat(Msg.getMsg(Env.getAD_Language(m_vo.ctx), "OrderSummary")); + } + catch (Exception e) + { + log.log(Level.SEVERE, "OrderSummary=" + Msg.getMsg(Env.getAD_Language(m_vo.ctx), "OrderSummary"), e); + } + if (mf == null) + return " "; + /********************************************************************** + * ** Message: OrderSummary ** + * {0} Line(s) - {1,number,#,##0.00} - Toral: {2,number,#,##0.00} {3} = {4,number,#,##0.00} + * + * {0} - Number of lines + * {1} - Line toral + * {2} - Grand total (including tax, etc.) + * {3} - Currency + * (4) - Grand total converted to local currency + */ + Object[] arguments = new Object[5]; + boolean filled = false; + // + try + { + PreparedStatement pstmt = DB.prepareStatement(sql.toString(), null); + pstmt.setInt(1, Record_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + // {0} - Number of lines + Integer lines = new Integer(rs.getInt(1)); + arguments[0] = lines; + // {1} - Line toral + Double lineTotal = new Double(rs.getDouble(3)); + arguments[1] = lineTotal; + // {2} - Grand total (including tax, etc.) + Double grandTotal = new Double(rs.getDouble(4)); + arguments[2] = grandTotal; + // {3} - Currency + String currency = rs.getString(2); + arguments[3] = currency; + // (4) - Grand total converted to Euro + Double grandEuro = new Double(rs.getDouble(5)); + arguments[4] = grandEuro; + filled = true; + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, m_vo.TableName + "\nSQL=" + sql, e); + } + if (filled) + return mf.format (arguments); + return " "; + } // Order || Invoice + + // Expense Report + else if (m_vo.TableName.startsWith("S_TimeExpense") && m_vo.TabNo == 0) + { + int Record_ID = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, "S_TimeExpense_ID"); + log.fine(m_vo.TableName + " - " + Record_ID); + MessageFormat mf = null; + try + { + mf = new MessageFormat(Msg.getMsg(Env.getAD_Language(m_vo.ctx), "ExpenseSummary")); + } + catch (Exception e) + { + log.log(Level.SEVERE, "ExpenseSummary=" + Msg.getMsg(Env.getAD_Language(m_vo.ctx), "ExpenseSummary"), e); + } + if (mf == null) + return " "; + /********************************************************************** + * ** Message: ExpenseSummary ** + * {0} Line(s) - Total: {1,number,#,##0.00} {2} + * + * {0} - Number of lines + * {1} - Toral + * {2} - Currency + */ + Object[] arguments = new Object[3]; + boolean filled = false; + // + String SQL = "SELECT COUNT(*) AS Lines, SUM(ConvertedAmt*Qty) " + + "FROM S_TimeExpenseLine " + + "WHERE S_TimeExpense_ID=?"; + + // + try + { + PreparedStatement pstmt = DB.prepareStatement(SQL, null); + pstmt.setInt(1, Record_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + // {0} - Number of lines + Integer lines = new Integer(rs.getInt(1)); + arguments[0] = lines; + // {1} - Line toral + Double total = new Double(rs.getDouble(2)); + arguments[1] = total; + // {3} - Currency + arguments[2] = " "; + filled = true; + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, m_vo.TableName + "\nSQL=" + SQL, e); + } + if (filled) + return mf.format (arguments); + return " "; + } // S_TimeExpense + + + // Default - No Trx Info + return null; + } // getTrxInfo + + /** + * Load Dependant Information + */ + private void loadDependentInfo() + { + /** + * Load Order Type from C_DocTypeTarget_ID + */ + if (m_vo.TableName.equals("C_Order")) + { + int C_DocTyp_ID = 0; + Integer target = (Integer)getValue("C_DocTypeTarget_ID"); + if (target != null) + C_DocTyp_ID = target.intValue(); + if (C_DocTyp_ID == 0) + return; + + String sql = "SELECT DocSubTypeSO FROM C_DocType WHERE C_DocType_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_DocTyp_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + Env.setContext(m_vo.ctx, m_vo.WindowNo, "OrderType", rs.getString(1)); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + } // loadOrderInfo + } // loadDependentInfo + + + /************************************************************************** + * Load Attachments for this table + */ + public void loadAttachments() + { + log.fine("#" + m_vo.TabNo); + if (!canHaveAttachment()) + return; + + String SQL = "SELECT AD_Attachment_ID, Record_ID FROM AD_Attachment " + + "WHERE AD_Table_ID=?"; + try + { + if (m_Attachments == null) + m_Attachments = new HashMap(); + else + m_Attachments.clear(); + PreparedStatement pstmt = DB.prepareStatement(SQL, null); + pstmt.setInt(1, m_vo.AD_Table_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + Integer key = new Integer(rs.getInt(2)); + Integer value = new Integer(rs.getInt(1)); + m_Attachments.put(key, value); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "loadAttachments", e); + } + log.config("#" + m_Attachments.size()); + } // loadAttachment + + /** + * Can this tab have Attachments?. + *

+ * It can have an attachment if it has a key column ending with _ID. + * The key column is empty, if there is no single identifying key. + * @return true if record can have attachment + */ + public boolean canHaveAttachment() + { + if (getKeyColumnName().endsWith("_ID")) + return true; + return false; + } // canHaveAttachment + + /** + * Returns true, if current row has an Attachment + * @return true if record has attchment + */ + public boolean hasAttachment() + { + if (m_Attachments == null) + loadAttachments(); + if (m_Attachments == null || m_Attachments.isEmpty()) + return false; + // + Integer key = new Integer(m_mTable.getKeyID (m_currentRow)); + return m_Attachments.containsKey(key); + } // hasAttachment + + /** + * Get Attachment_ID for current record. + * @return ID or 0, if not found + */ + public int getAD_AttachmentID() + { + if (m_Attachments == null) + loadAttachments(); + if (m_Attachments.isEmpty()) + return 0; + // + Integer key = new Integer(m_mTable.getKeyID (m_currentRow)); + Integer value = (Integer)m_Attachments.get(key); + if (value == null) + return 0; + else + return value.intValue(); + } // getAttachmentID + + /************************************************************************** + * Load Chats for this table + */ + public void loadChats() + { + log.fine("#" + m_vo.TabNo); + if (!canHaveAttachment()) + return; + + String sql = "SELECT CM_Chat_ID, Record_ID FROM CM_Chat " + + "WHERE AD_Table_ID=?"; + try + { + if (m_Chats == null) + m_Chats = new HashMap(); + else + m_Chats.clear(); + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, m_vo.AD_Table_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + Integer key = new Integer(rs.getInt(2)); // Record_ID + Integer value = new Integer(rs.getInt(1)); // CM_Chat_ID + m_Chats.put(key, value); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + log.config("#" + m_Chats.size()); + } // loadChats + + /** + * Returns true, if current row has a Chat + * @return true if record has chat + */ + public boolean hasChat() + { + if (m_Chats == null) + loadChats(); + if (m_Chats == null || m_Chats.isEmpty()) + return false; + // + Integer key = new Integer(m_mTable.getKeyID (m_currentRow)); + return m_Chats.containsKey(key); + } // hasChat + + /** + * Get Chat_ID for this record. + * @return ID or 0, if not found + */ + public int getCM_ChatID() + { + if (m_Chats == null) + loadChats(); + if (m_Chats.isEmpty()) + return 0; + // + Integer key = new Integer(m_mTable.getKeyID (m_currentRow)); + Integer value = (Integer)m_Chats.get(key); + if (value == null) + return 0; + else + return value.intValue(); + } // getCM_ChatID + + + /************************************************************************** + * Load Locks for Table and User + */ + public void loadLocks() + { + int AD_User_ID = Env.getContextAsInt(Env.getCtx(), "#AD_User_ID"); + log.fine("#" + m_vo.TabNo + " - AD_User_ID=" + AD_User_ID); + if (!canHaveAttachment()) + return; + + String sql = "SELECT Record_ID " + + "FROM AD_Private_Access " + + "WHERE AD_User_ID=? AND AD_Table_ID=? AND IsActive='Y' " + + "ORDER BY Record_ID"; + try + { + if (m_Lock == null) + m_Lock = new ArrayList(); + else + m_Lock.clear(); + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_User_ID); + pstmt.setInt(2, m_vo.AD_Table_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + Integer key = new Integer(rs.getInt(1)); + m_Lock.add(key); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + log.fine("#" + m_Lock.size()); + } // loadLooks + + /** + * Record Is Locked + * @return true if locked + */ + public boolean isLocked() + { + if (!MRole.getDefault(m_vo.ctx, false).isPersonalLock()) + return false; + if (m_Lock == null) + loadLocks(); + if (m_Lock == null || m_Lock.isEmpty()) + return false; + // + Integer key = new Integer(m_mTable.getKeyID (m_currentRow)); + return m_Lock.contains(key); + } // isLocked + + /** + * Lock Record + * @param ctx context + * @param Record_ID id + * @param lock true if lock, otherwise unlock + */ + public void lock (Properties ctx, int Record_ID, boolean lock) + { + int AD_User_ID = Env.getContextAsInt(ctx, "#AD_User_ID"); + log.fine("Lock=" + lock + ", AD_User_ID=" + AD_User_ID + + ", AD_Table_ID=" + m_vo.AD_Table_ID + ", Record_ID=" + Record_ID); + MPrivateAccess access = MPrivateAccess.get (ctx, AD_User_ID, m_vo.AD_Table_ID, Record_ID); + if (access == null) + access = new MPrivateAccess (ctx, AD_User_ID, m_vo.AD_Table_ID, Record_ID); + access.setIsActive(lock); + access.save(); + // + loadLocks(); + } // lock + + + /************************************************************************** + * Data Status Listener from MTable. + * - get raw info and add current row information + * - update the current row + * - redistribute (fire) Data Status event + * @param e event + */ + public void dataStatusChanged (DataStatusEvent e) + { + log.fine("#" + m_vo.TabNo + " - " + e.toString()); + int oldCurrentRow = e.getCurrentRow(); + m_DataStatusEvent = e; // save it + // when sorted set current row to 0 + String msg = m_DataStatusEvent.getAD_Message(); + if (msg != null && msg.equals("Sorted")) + setCurrentRow(0, true); + // set current row + m_DataStatusEvent.setCurrentRow(m_currentRow); + // Same row - update value + if (oldCurrentRow == m_currentRow) + { + GridField field = m_mTable.getField(e.getChangedColumn()); + if (field != null) + { + Object value = m_mTable.getValueAt(m_currentRow, e.getChangedColumn()); + field.setValue(value, m_mTable.isInserting()); + } + } + else // Redistribute Info with current row info + fireDataStatusChanged(m_DataStatusEvent); + // log.fine("dataStatusChanged #" + m_vo.TabNo + "- fini", e.toString()); + } // dataStatusChanged + + /** + * Inform Listeners and build WHO info + * @param e event + */ + private void fireDataStatusChanged (DataStatusEvent e) + { + DataStatusListener[] listeners = m_listenerList.getListeners(DataStatusListener.class); + if (listeners.length == 0) + return; + log.fine(e.toString()); + // WHO Info + if (e.getCurrentRow() >= 0) + { + e.Created = (Timestamp)getValue("Created"); + e.CreatedBy = (Integer)getValue("CreatedBy"); + e.Updated = (Timestamp)getValue("Updated"); + e.UpdatedBy = (Integer)getValue("UpdatedBy"); + e.Record_ID = getValue(m_keyColumnName); + // Info + StringBuffer info = new StringBuffer(getTableName()); + // We have a key column + if (m_keyColumnName != null && m_keyColumnName.length() > 0) + { + info.append(" - ") + .append(m_keyColumnName).append("=").append(e.Record_ID); + } + else // we have multiple parents + { + for (int i = 0; i < m_parents.size(); i++) + { + String keyCol = (String)m_parents.get(i); + info.append(" - ") + .append(keyCol).append("=").append(getValue(keyCol)); + } + } + e.Info = info.toString(); + } + e.setInserting(m_mTable.isInserting()); + // Distribute/fire it + for (int i = 0; i < listeners.length; i++) + listeners[i].dataStatusChanged(e); + // log.fine("fini - " + e.toString()); + } // fireDataStatusChanged + + /** + * Create and fire Data Status Error Event + * @param AD_Message message + * @param info info + * @param isError if not true, it is a Warning + */ + protected void fireDataStatusEEvent(String AD_Message, String info, boolean isError) + { + m_mTable.fireDataStatusEEvent(AD_Message, info, isError); + } // fireDataStatusEvent + + /** + * Create and fire Data Status Error Event (from Error Log) + * @param errorLog log + */ + protected void fireDataStatusEEvent (ValueNamePair errorLog) + { + if (errorLog != null) + m_mTable.fireDataStatusEEvent(errorLog); + } // fireDataStatusEvent + + /** + * Get Current Row + * @return current row + */ + public int getCurrentRow() + { + if (m_currentRow != verifyRow(m_currentRow)) + setCurrentRow(m_mTable.getRowCount()-1, true); + return m_currentRow; + } // getCurrentRow + + /** + * Get Current Table Key ID + * @return Record_ID + */ + public int getRecord_ID() + { + return m_mTable.getKeyID(m_currentRow); + } // getRecord_ID + + /** + * Get Key ID of row + * @param row row number + * @return The Key ID of the row or -1 if not found + */ + public int getKeyID (int row) + { + return m_mTable.getKeyID (row); + } // getCurrentKeyID + + /** + * Navigate absolute - goto Row - (zero based). + * - does nothing, if in current row + * - saves old row if required + * @param targetRow target row + * @return current row + */ + public int navigate (int targetRow) + { + // nothing to do + if (targetRow == m_currentRow) + return m_currentRow; + log.info ("Row=" + targetRow); + + // Row range check + int newRow = verifyRow(targetRow); + + // Check, if we have old uncommitted data + m_mTable.dataSave(newRow, false); + + // new position + return setCurrentRow(newRow, true); + } // navigate + + /** + * Navigate relatively - i.e. plus/minus from current position + * @param rowChange row change + * @return current row + */ + public int navigateRelative (int rowChange) + { + return navigate (m_currentRow + rowChange); + } // navigateRelative + + /** + * Navigate to current now (reload) + * @return current row + */ + public int navigateCurrent() + { + log.info("Row=" + m_currentRow); + return setCurrentRow(m_currentRow, true); + } // navigateCurrent + + /** + * Row Range check + * @param targetRow target row + * @return checked row + */ + private int verifyRow (int targetRow) + { + int newRow = targetRow; + // Table Open? + if (!m_mTable.isOpen()) + { + log.severe ("Table not open"); + return -1; + } + // Row Count + int rows = getRowCount(); + if (rows == 0) + { + log.fine("No Rows"); + return -1; + } + if (newRow >= rows) + { + newRow = rows-1; + log.fine("Set to max Row: " + newRow); + } + else if (newRow < 0) + { + newRow = 0; + log.fine("Set to first Row"); + } + return newRow; + } // verifyRow + + /** + * Set current row and load data into fields. + * If there is no row - load nulls + * @param newCurrentRow new current row + * @param fireEvents fire events + * @return current row + */ + private int setCurrentRow (int newCurrentRow, boolean fireEvents) + { + int oldCurrentRow = m_currentRow; + m_currentRow = verifyRow (newCurrentRow); + log.fine("Row=" + m_currentRow + " - fire=" + fireEvents); + + // Update Field Values + int size = m_mTable.getColumnCount(); + for (int i = 0; i < size; i++) + { + GridField mField = m_mTable.getField(i); + // get Value from Table + if (m_currentRow >= 0) + { + Object value = m_mTable.getValueAt(m_currentRow, i); + mField.setValue(value, m_mTable.isInserting()); + if (m_mTable.isInserting()) // set invalid values to null + mField.validateValue(); + } + else + { // no rows - set to a reasonable value - not updateable +// Object value = null; +// if (mField.isKey() || mField.isParent() || mField.getColumnName().equals(m_linkColumnName)) +// value = mField.getDefault(); + mField.setValue(); + } + } + loadDependentInfo(); + + if (!fireEvents) // prevents informing twice + return m_currentRow; + + // inform VTable/.. -> rowChanged + m_propertyChangeSupport.firePropertyChange(PROPERTY, oldCurrentRow, m_currentRow); + + // inform APanel/.. -> dataStatus with row updated + if (m_DataStatusEvent == null) + m_DataStatusEvent = new DataStatusEvent(this, getRowCount(), + m_mTable.isInserting(), // changed + Env.isAutoCommit(Env.getCtx(), m_vo.WindowNo), m_mTable.isInserting()); + // + m_DataStatusEvent.setCurrentRow(m_currentRow); + String status = m_DataStatusEvent.getAD_Message(); + if (status == null || status.length() == 0) + m_DataStatusEvent.setInfo("NavigateOrUpdate", null, false,false); + fireDataStatusChanged(m_DataStatusEvent); + return m_currentRow; + } // setCurrentRow + + + /************************************************************************** + * Get RowCount + * @return row count + */ + public int getRowCount() + { + int count = m_mTable.getRowCount(); + // Wait a bit if currently loading + if (count == 0 && m_mTable.isLoading()) + { + try + { + Thread.sleep(100); // .1 sec + } + catch (Exception e) {} + count = m_mTable.getRowCount(); + } + return count; + } // getRowCount + + /** + * Get Column/Field Count + * @return field count + */ + public int getFieldCount() + { + return m_mTable.getColumnCount(); + } // getFieldCount + + /** + * Get Field by index + * @param index index + * @return MField + */ + public GridField getField (int index) + { + return m_mTable.getField(index); + } // getField + + /** + * Get Field by DB column name + * @param columnName column name + * @return MField + */ + public GridField getField (String columnName) + { + return m_mTable.getField(columnName); + } // getField + + /** + * Get all Fields + * @return MFields + */ + public GridField[] getFields () + { + return m_mTable.getFields(); + } // getField + + /** + * Set New Value & call Callout + * @param columnName database column name + * @param value value + * @return error message or "" + */ + public String setValue (String columnName, Object value) + { + if (columnName == null) + return "NoColumn"; + return setValue(m_mTable.getField(columnName), value); + } // setValue + + /** + * Set New Value & call Callout + * @param field field + * @param value value + * @return error message or "" + */ + public String setValue (GridField field, Object value) + { + if (field == null) + return "NoField"; + + log.fine(field.getColumnName() + "=" + value + " - Row=" + m_currentRow); + + int col = m_mTable.findColumn(field.getColumnName()); + m_mTable.setValueAt(value, m_currentRow, col, false); + // + return processFieldChange (field); + } // setValue + + /** + * Is Processed + * @return true if current record is processed + */ + public boolean isProcessed() + { + int index = m_mTable.findColumn("Processed"); + if (index != -1) + { + Object oo = m_mTable.getValueAt(m_currentRow, index); + if (oo instanceof String) + return "Y".equals(oo); + if (oo instanceof Boolean) + return ((Boolean)oo).booleanValue(); + } + return "Y".equals(Env.getContext(m_vo.ctx, m_vo.WindowNo, "Processed")); + } // isProcessed + + /** + * Process Field Change - evaluate Dependencies and process Callouts. + * + * called from MTab.setValue or GridController.dataStatusChanged + * @param changedField changed field + * @return error message or "" + */ + public String processFieldChange (GridField changedField) + { + processDependencies (changedField); + return processCallout (changedField); + } // processFieldChange + + /** + * Evaluate Dependencies + * @param changedField changed field + */ + private void processDependencies (GridField changedField) + { + String columnName = changedField.getColumnName(); + // log.trace(log.l4_Data, "Changed Column", columnName); + + // when column name is not in list of DependentOn fields - fini + if (!hasDependants(columnName)) + return; + + // Get dependent MFields (may be because of display or dynamic lookup) + ArrayList list = getDependantFields(columnName); + for (int i = 0; i < list.size(); i++) + { + GridField dependentField = (GridField)list.get(i); + // log.trace(log.l5_DData, "Dependent Field", dependentField==null ? "null" : dependentField.getColumnName()); + // if the field has a lookup + if (dependentField != null && dependentField.getLookup() instanceof MLookup) + { + MLookup mLookup = (MLookup)dependentField.getLookup(); + // log.trace(log.l6_Database, "Lookup Validation", mLookup.getValidation()); + // if the lookup is dynamic (i.e. contains this columnName as variable) + if (mLookup.getValidation().indexOf("@"+columnName+"@") != -1) + { + log.fine(columnName + " changed - " + + dependentField.getColumnName() + " set to null"); + // invalidate current selection + setValue(dependentField, null); + } + } + } // for all dependent fields + } // processDependencies + + + /************************************************************************** + * Process Callout(s). + *

+ * The Callout is in the string of + * "class.method;class.method;" + * If there is no class name, i.e. only a method name, the class is regarded + * as CalloutSystem. + * The class needs to comply with the Interface Callout. + * + * For a limited time, the old notation of Sx_matheod / Ux_menthod is maintained. + * + * @param field field + * @return error message or "" + * @see org.compiere.model.Callout + */ + private String processCallout (GridField field) + { + String callout = field.getCallout(); + if (callout.length() == 0) + return ""; + // + if (isProcessed()) // only active records + return ""; // "DocProcessed"; + + Object value = field.getValue(); + Object oldValue = field.getOldValue(); + log.fine(field.getColumnName() + "=" + value + + " (" + callout + ") - old=" + oldValue); + + StringTokenizer st = new StringTokenizer(callout, ";,", false); + while (st.hasMoreTokens()) // for each callout + { + String cmd = st.nextToken().trim(); + Callout call = null; + String method = null; + int methodStart = cmd.lastIndexOf("."); + try + { + if (methodStart != -1) // no class + { + Class cClass = Class.forName(cmd.substring(0,methodStart)); + call = (Callout)cClass.newInstance(); + method = cmd.substring(methodStart+1); + } + } + catch (Exception e) + { + log.log(Level.SEVERE, "class", e); + return "Callout Invalid: " + cmd + " (" + e.toString() + ")"; + } + + if (call == null || method == null || method.length() == 0) + return "Callout Invalid: " + method; + + String retValue = ""; + try + { + retValue = call.start(m_vo.ctx, method, m_vo.WindowNo, this, field, value, oldValue); + } + catch (Exception e) + { + log.log(Level.SEVERE, "start", e); + retValue = "Callout Invalid: " + e.toString(); + return retValue; + } + if (!retValue.equals("")) // interrupt on first error + { + log.severe (retValue); + return retValue; + } + } // for each callout + return ""; + } // processCallout + + + /** + * Get Value of Field with columnName + * @param columnName column name + * @return value + */ + public Object getValue (String columnName) + { + if (columnName == null) + return null; + GridField field = m_mTable.getField(columnName); + return getValue(field); + } // getValue + + /** + * Get Value of Field + * @param field field + * @return value + */ + public Object getValue (GridField field) + { + if (field == null) + return null; + return field.getValue(); + } // getValue + + /** + * Get Value of Field in row + * @param row row + * @param columnName column name + * @return value + */ + public Object getValue (int row, String columnName) + { + int col = m_mTable.findColumn(columnName); + if (col == -1) + return null; + return m_mTable.getValueAt(row, col); + } // getValue + + /** + * toString + * @return String representation + */ + public String toString() + { + String retValue = "MTab #" + m_vo.TabNo; + if (m_vo != null) + retValue += " " + m_vo.Name + " (" + m_vo.AD_Tab_ID + ")"; + return retValue; + } // toString + + + /************************************************************************** + * @param l listener + */ + public synchronized void removePropertyChangeListener(PropertyChangeListener l) + { + m_propertyChangeSupport.removePropertyChangeListener(l); + } + /** + * @param l listener + */ + public synchronized void addPropertyChangeListener(PropertyChangeListener l) + { + m_propertyChangeSupport.addPropertyChangeListener(l); + } + + /** + * @param l listener + */ + public synchronized void removeDataStatusListener(DataStatusListener l) + { + m_listenerList.remove(DataStatusListener.class, l); + } + /** + * @param l listener + */ + public synchronized void addDataStatusListener(DataStatusListener l) + { + m_listenerList.add(DataStatusListener.class, l); + } + +} // MTab diff --git a/base/src/org/compiere/model/GridTable.java b/base/src/org/compiere/model/GridTable.java new file mode 100644 index 0000000000..70f8077149 --- /dev/null +++ b/base/src/org/compiere/model/GridTable.java @@ -0,0 +1,3076 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.beans.*; +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import javax.swing.event.*; +import javax.swing.table.*; + +import org.compiere.util.*; + +/** + * Grid Table Model for JDBC access including buffering. + *

+ *		The following data types are handeled
+ *			Integer		for all IDs
+ *			BigDecimal	for all Numbers
+ *			Timestamp	for all Dates
+ *			String		for all others
+ *  The data is read via r/o resultset and cached in m_buffer. Writes/updates
+ *  are via dynamically constructed SQL INSERT/UPDATE statements. The record
+ *  is re-read via the resultset to get results of triggers.
+ *
+ *  
+ * The model maintains and fires the requires TableModelEvent changes, + * the DataChanged events (loading, changed, etc.) + * as well as Vetoable Change event "RowChange" + * (for row changes initiated by moving the row in the table grid). + * + * @author Jorg Janke + * @version $Id: GridTable.java,v 1.9 2006/08/09 16:38:25 jjanke Exp $ + */ +public class GridTable extends AbstractTableModel + implements Serializable +{ + /** + * JDBC Based Buffered Table + * + * @param ctx Properties + * @param AD_Table_ID table id + * @param TableName table name + * @param WindowNo window no + * @param TabNo tab no + * @param withAccessControl if true adds AD_Client/Org restrictuins + */ + public GridTable(Properties ctx, int AD_Table_ID, String TableName, int WindowNo, int TabNo, + boolean withAccessControl) + { + super(); + log.info(TableName); + m_ctx = ctx; + m_AD_Table_ID = AD_Table_ID; + setTableName(TableName); + m_WindowNo = WindowNo; + m_TabNo = TabNo; + m_withAccessControl = withAccessControl; + } // MTable + + private static CLogger log = CLogger.getCLogger(GridTable.class.getName()); + private Properties m_ctx; + private int m_AD_Table_ID; + private String m_tableName = ""; + private int m_WindowNo; + /** Tab No 0.. */ + private int m_TabNo; + private boolean m_withAccessControl; + private boolean m_readOnly = true; + private boolean m_deleteable = true; + // + + /** Rowcount */ + private int m_rowCount = 0; + /** Has Data changed? */ + private boolean m_changed = false; + /** Index of changed row via SetValueAt */ + private int m_rowChanged = -1; + /** Insert mode active */ + private boolean m_inserting = false; + /** Inserted Row number */ + private int m_newRow = -1; + /** Is the Resultset open? */ + private boolean m_open = false; + /** Compare to DB before save */ + private boolean m_compareDB = true; // set to true after every save + + // The buffer for all data + private volatile ArrayList m_buffer = new ArrayList(100); + private volatile ArrayList m_sort = new ArrayList(100); + /** Original row data */ + private Object[] m_rowData = null; + /** Original data [row,col,data] */ + private Object[] m_oldValue = null; + // + private Loader m_loader = null; + + /** Columns */ + private ArrayList m_fields = new ArrayList(30); + private ArrayList m_parameterSELECT = new ArrayList(5); + private ArrayList m_parameterWHERE = new ArrayList(5); + + /** Complete SQL statement */ + private String m_SQL; + /** SQL Statement for Row Count */ + private String m_SQL_Count; + /** The SELECT clause with FROM */ + private String m_SQL_Select; + /** The static where clause */ + private String m_whereClause = ""; + /** Show only Processed='N' and last 24h records */ + private boolean m_onlyCurrentRows = false; + /** Show only Not processed and x days */ + private int m_onlyCurrentDays = 1; + /** Static ORDER BY clause */ + private String m_orderClause = ""; + /** Max Rows to query or 0 for all */ + private int m_maxRows = 0; + + /** Index of Key Column */ + private int m_indexKeyColumn = -1; + /** Index of Color Column */ + private int m_indexColorColumn = -1; + /** Index of Processed Column */ + private int m_indexProcessedColumn = -1; + /** Index of IsActive Column */ + private int m_indexActiveColumn = -1; + /** Index of AD_Client_ID Column */ + private int m_indexClientColumn = -1; + /** Index of AD_Org_ID Column */ + private int m_indexOrgColumn = -1; + + /** Vetoable Change Bean support */ + private VetoableChangeSupport m_vetoableChangeSupport = new VetoableChangeSupport(this); + /** Property of Vetoable Bean support "RowChange" */ + public static final String PROPERTY = "MTable-RowSave"; + + /** + * Set Table Name + * @param newTableName table name + */ + public void setTableName(String newTableName) + { + if (m_open) + { + log.log(Level.SEVERE, "Table already open - ignored"); + return; + } + if (newTableName == null || newTableName.length() == 0) + return; + m_tableName = newTableName; + } // setTableName + + /** + * Get Table Name + * @return table name + */ + public String getTableName() + { + return m_tableName; + } // getTableName + + /** + * Set Where Clause (w/o the WHERE and w/o History). + * @param newWhereClause sql where clause + * @param onlyCurrentRows only current rows + * @param onlyCurrentDays how many days back for current + * @return true if where clase set + */ + public boolean setSelectWhereClause(String newWhereClause, boolean onlyCurrentRows, int onlyCurrentDays) + { + if (m_open) + { + log.log(Level.SEVERE, "Table already open - ignored"); + return false; + } + // + m_whereClause = newWhereClause; + m_onlyCurrentRows = onlyCurrentRows; + m_onlyCurrentDays = onlyCurrentDays; + if (m_whereClause == null) + m_whereClause = ""; + return true; + } // setWhereClause + + /** + * Get record set Where Clause (w/o the WHERE and w/o History) + * @return where clause + */ + public String getSelectWhereClause() + { + return m_whereClause; + } // getWhereClause + + /** + * Is History displayed + * @return true if history displayed + */ + public boolean isOnlyCurrentRowsDisplayed() + { + return !m_onlyCurrentRows; + } // isHistoryDisplayed + + /** + * Set Order Clause (w/o the ORDER BY) + * @param newOrderClause sql order by clause + */ + public void setOrderClause(String newOrderClause) + { + m_orderClause = newOrderClause; + if (m_orderClause == null) + m_orderClause = ""; + } // setOrderClause + + /** + * Get Order Clause (w/o the ORDER BY) + * @return order by clause + */ + public String getOrderClause() + { + return m_orderClause; + } // getOrderClause + + /** + * Assemble & store + * m_SQL and m_countSQL + * @return m_SQL + */ + private String createSelectSql() + { + if (m_fields.size() == 0 || m_tableName == null || m_tableName.equals("")) + return ""; + + // Create SELECT Part + StringBuffer select = new StringBuffer("SELECT "); + for (int i = 0; i < m_fields.size(); i++) + { + if (i > 0) + select.append(","); + GridField field = (GridField)m_fields.get(i); + select.append(field.getColumnSQL(true)); // ColumnName or Virtual Column + } + // + select.append(" FROM ").append(m_tableName); + m_SQL_Select = select.toString(); + m_SQL_Count = "SELECT COUNT(*) FROM " + m_tableName; + // + + StringBuffer where = new StringBuffer(""); + // WHERE + if (m_whereClause.length() > 0) + { + where.append(" WHERE "); + if (m_whereClause.indexOf("@") == -1) + where.append(m_whereClause); + else // replace variables + where.append(Env.parseContext(m_ctx, m_WindowNo, m_whereClause, false)); + } + if (m_onlyCurrentRows && m_TabNo == 0) + { + if (where.toString().indexOf(" WHERE ") == -1) + where.append(" WHERE "); + else + where.append(" AND "); + // Show only unprocessed or the one updated within x days + where.append("(Processed='N' OR Updated>"); + if (DB.isDerby()) + where.append("dateadd(dd,-1,getdate())"); + else + where.append("SysDate-1"); + where.append(")"); + } + + // RO/RW Access + m_SQL = m_SQL_Select + where.toString(); + m_SQL_Count += where.toString(); + if (m_withAccessControl) + { + boolean ro = MRole.SQL_RO; + // if (!m_readOnly) + // ro = MRole.SQL_RW; + m_SQL = MRole.getDefault(m_ctx, false).addAccessSQL(m_SQL, + m_tableName, MRole.SQL_FULLYQUALIFIED, MRole.SQL_RO); + m_SQL_Count = MRole.getDefault(m_ctx, false).addAccessSQL(m_SQL_Count, + m_tableName, MRole.SQL_FULLYQUALIFIED, MRole.SQL_RO); + } + + // ORDER BY + if (!m_orderClause.equals("")) + m_SQL += " ORDER BY " + m_orderClause; + // + log.fine(m_SQL_Count); + Env.setContext(m_ctx, m_WindowNo, m_TabNo, "SQL", m_SQL); + return m_SQL; + } // createSelectSql + + /** + * Add Field to Table + * @param field field + */ + public void addField (GridField field) + { + log.fine("(" + m_tableName + ") - " + field.getColumnName()); + if (m_open) + { + log.log(Level.SEVERE, "Table already open - ignored: " + field.getColumnName()); + return; + } + if (!MRole.getDefault(m_ctx, false).isColumnAccess (m_AD_Table_ID, field.getAD_Column_ID(), true)) + { + log.fine("No Column Access " + field.getColumnName()); + return; + } + // Set Index for Key column + if (field.isKey()) + m_indexKeyColumn = m_fields.size(); + else if (field.getColumnName().equals("IsActive")) + m_indexActiveColumn = m_fields.size(); + else if (field.getColumnName().equals("Processed")) + m_indexProcessedColumn = m_fields.size(); + else if (field.getColumnName().equals("AD_Client_ID")) + m_indexClientColumn = m_fields.size(); + else if (field.getColumnName().equals("AD_Org_ID")) + m_indexOrgColumn = m_fields.size(); + // + m_fields.add(field); + } // addColumn + + /** + * Returns database column name + * + * @param index the column being queried + * @return column name + */ + public String getColumnName (int index) + { + if (index < 0 || index > m_fields.size()) + { + log.log(Level.SEVERE, "Invalid index=" + index); + return ""; + } + // + GridField field = (GridField)m_fields.get(index); + return field.getColumnName(); + } // getColumnName + + /** + * Returns a column given its name. + * + * @param columnName string containing name of column to be located + * @return the column index with columnName, or -1 if not found + */ + public int findColumn (String columnName) + { + for (int i = 0; i < m_fields.size(); i++) + { + GridField field = (GridField)m_fields.get(i); + if (columnName.equals(field.getColumnName())) + return i; + } + return -1; + } // findColumn + + /** + * Returns Class of database column/field + * + * @param index the column being queried + * @return the class + */ + public Class getColumnClass (int index) + { + if (index < 0 || index >= m_fields.size()) + { + log.log(Level.SEVERE, "Invalid index=" + index); + return null; + } + GridField field = (GridField)m_fields.get(index); + return DisplayType.getClass(field.getDisplayType(), false); + } // getColumnClass + + /** + * Set Select Clause Parameter. + * Assumes that you set parameters starting from index zero + * @param index index + * @param parameter parameter + */ + public void setParameterSELECT (int index, Object parameter) + { + if (index >= m_parameterSELECT.size()) + m_parameterSELECT.add(parameter); + else + m_parameterSELECT.set(index, parameter); + } // setParameterSELECT + + /** + * Set Where Clause Parameter. + * Assumes that you set parameters starting from index zero + * @param index index + * @param parameter parameter + */ + public void setParameterWHERE (int index, Object parameter) + { + if (index >= m_parameterWHERE.size()) + m_parameterWHERE.add(parameter); + else + m_parameterWHERE.set(index, parameter); + } // setParameterWHERE + + + /** + * Get Column at index + * @param index index + * @return MField + */ + protected GridField getField (int index) + { + if (index < 0 || index >= m_fields.size()) + return null; + return (GridField)m_fields.get(index); + } // getColumn + + /** + * Return Columns with Indentifier (ColumnName) + * @param identifier column name + * @return MField + */ + protected GridField getField (String identifier) + { + if (identifier == null || identifier.length() == 0) + return null; + int cols = m_fields.size(); + for (int i = 0; i < cols; i++) + { + GridField field = (GridField)m_fields.get(i); + if (identifier.equalsIgnoreCase(field.getColumnName())) + return field; + } + // log.log(Level.WARNING, "Not found: '" + identifier + "'"); + return null; + } // getField + + /** + * Get all Fields + * @return MFields + */ + public GridField[] getFields () + { + GridField[] retValue = new GridField[m_fields.size()]; + m_fields.toArray(retValue); + return retValue; + } // getField + + + /************************************************************************** + * Open Database. + * if already opened, data is refreshed + * @param maxRows maximum number of rows or 0 for all + * @return true if success + */ + public boolean open (int maxRows) + { + log.info("MaxRows=" + maxRows); + m_maxRows = maxRows; + if (m_open) + { + log.fine("already open"); + dataRefreshAll(); + return true; + } + + // create m_SQL and m_countSQL + createSelectSql(); + if (m_SQL == null || m_SQL.equals("")) + { + log.log(Level.SEVERE, "No SQL"); + return false; + } + + // Start Loading + m_loader = new Loader(); + m_rowCount = m_loader.open(maxRows); + m_buffer = new ArrayList(m_rowCount+10); + m_sort = new ArrayList(m_rowCount+10); + if (m_rowCount > 0) + m_loader.start(); + else + m_loader.close(); + m_open = true; + // + m_changed = false; + m_rowChanged = -1; + return true; + } // open + + /** + * Wait until async loader of Table and Lookup Fields is complete + * Used for performance tests + */ + public void loadComplete() + { + // Wait for loader + if (m_loader != null) + { + if (m_loader.isAlive()) + { + try + { + m_loader.join(); + } + catch (InterruptedException ie) + { + log.log(Level.SEVERE, "Join interrupted", ie); + } + } + } + // wait for field lookup loaders + for (int i = 0; i < m_fields.size(); i++) + { + GridField field = (GridField)m_fields.get(i); + field.lookupLoadComplete(); + } + } // loadComplete + + /** + * Is Loading + * @return true if loading + */ + public boolean isLoading() + { + if (m_loader != null && m_loader.isAlive()) + return true; + return false; + } // isLoading + + /** + * Is it open? + * @return true if opened + */ + public boolean isOpen() + { + return m_open; + } // isOpen + + /** + * Close Resultset + * @param finalCall final call + */ + public void close (boolean finalCall) + { + if (!m_open) + return; + log.fine("final=" + finalCall); + + // remove listeners + if (finalCall) + { + DataStatusListener evl[] = (DataStatusListener[])listenerList.getListeners(DataStatusListener.class); + for (int i = 0; i < evl.length; i++) + listenerList.remove(DataStatusListener.class, evl[i]); + TableModelListener ev2[] = (TableModelListener[])listenerList.getListeners(TableModelListener.class); + for (int i = 0; i < ev2.length; i++) + listenerList.remove(TableModelListener.class, ev2[i]); + VetoableChangeListener vcl[] = m_vetoableChangeSupport.getVetoableChangeListeners(); + for (int i = 0; i < vcl.length; i++) + m_vetoableChangeSupport.removeVetoableChangeListener(vcl[i]); + } + + // Stop loader + while (m_loader != null && m_loader.isAlive()) + { + log.fine("Interrupting Loader ..."); + m_loader.interrupt(); + try + { + Thread.sleep(200); // .2 second + } + catch (InterruptedException ie) + {} + } + + if (!m_inserting) + dataSave(false); // not manual + + if (m_buffer != null) + m_buffer.clear(); + m_buffer = null; + if (m_sort != null) + m_sort.clear(); + m_sort = null; + + if (finalCall) + dispose(); + + // Fields are disposed from MTab + log.fine(""); + m_open = false; + } // close + + /** + * Dispose MTable. + * Called by close-final + */ + private void dispose() + { + // MFields + for (int i = 0; i < m_fields.size(); i++) + ((GridField)m_fields.get(i)).dispose(); + m_fields.clear(); + m_fields = null; + // + m_vetoableChangeSupport = null; + // + m_parameterSELECT.clear(); + m_parameterSELECT = null; + m_parameterWHERE.clear(); + m_parameterWHERE = null; + // clear data arrays + m_buffer = null; + m_sort = null; + m_rowData = null; + m_oldValue = null; + m_loader = null; + } // dispose + + /** + * Get total database column count (displayed and not displayed) + * @return column count + */ + public int getColumnCount() + { + return m_fields.size(); + } // getColumnCount + + /** + * Get (displayed) field count + * @return field count + */ + public int getFieldCount() + { + return m_fields.size(); + } // getFieldCount + + /** + * Return number of rows + * @return Number of rows or 0 if not opened + */ + public int getRowCount() + { + return m_rowCount; + } // getRowCount + + /** + * Set the Column to determine the color of the row + * @param columnName column name + */ + public void setColorColumn (String columnName) + { + m_indexColorColumn = findColumn(columnName); + } // setColorColumn + + /** + * Get ColorCode for Row. + *
+	 *	If numerical value in compare column is
+	 *		negative = -1,
+	 *      positive = 1,
+	 *      otherwise = 0
+	 *  
+ * @see #setColorColumn + * @param row row + * @return color code + */ + public int getColorCode (int row) + { + if (m_indexColorColumn == -1) + return 0; + Object data = getValueAt(row, m_indexColorColumn); + // We need to have a Number + if (data == null || !(data instanceof BigDecimal)) + return 0; + BigDecimal bd = (BigDecimal)data; + return bd.signum(); + } // getColorCode + + + /** + * Sort Entries by Column. + * actually the rows are not sorted, just the access pointer ArrayList + * with the same size as m_buffer with MSort entities + * @param col col + * @param ascending ascending + */ + @SuppressWarnings("unchecked") + public void sort (int col, boolean ascending) + { + log.info("#" + col + " " + ascending); + if (getRowCount() == 0) + return; + GridField field = getField (col); + // RowIDs are not sorted + if (field.getDisplayType() == DisplayType.RowID) + return; + boolean isLookup = DisplayType.isLookup(field.getDisplayType()); + boolean isASI = DisplayType.PAttribute == field.getDisplayType(); + + // fill MSort entities with data entity + for (int i = 0; i < m_sort.size(); i++) + { + MSort sort = (MSort)m_sort.get(i); + Object[] rowData = (Object[])m_buffer.get(sort.index); + if (rowData[col] == null) + sort.data = null; + else if (isLookup || isASI) + sort.data = field.getLookup().getDisplay(rowData[col]); // lookup + else + sort.data = rowData[col]; // data + } + log.info(field.toString() + " #" + m_sort.size()); + + // sort it + MSort sort = new MSort(0, null); + sort.setSortAsc(ascending); + Collections.sort(m_sort, sort); + // update UI + fireTableDataChanged(); + // Info detected by MTab.dataStatusChanged and current row set to 0 + fireDataStatusIEvent("Sorted", "#" + m_sort.size()); + } // sort + + /** + * Get Key ID or -1 of none + * @param row row + * @return ID or -1 + */ + public int getKeyID (int row) + { + // Log.info("MTable.getKeyID - row=" + row + ", keyColIdx=" + m_indexKeyColumn); + if (m_indexKeyColumn != -1) + { + try + { + Integer ii = (Integer)getValueAt(row, m_indexKeyColumn); + if (ii == null) + return -1; + return ii.intValue(); + } + catch (Exception e) // Alpha Key + { + return -1; + } + } + return -1; + } // getKeyID + + /** + * Get Key ColumnName + * @return key column name + */ + public String getKeyColumnName() + { + if (m_indexKeyColumn != -1) + return getColumnName(m_indexKeyColumn); + return ""; + } // getKeyColumnName + + + /************************************************************************** + * Get Value in Resultset + * @param row row + * @param col col + * @return Object of that row/column + */ + public Object getValueAt (int row, int col) + { + // log.config( "MTable.getValueAt r=" + row + " c=" + col); + if (!m_open || row < 0 || col < 0 || row >= m_rowCount) + { + // log.fine( "Out of bounds - Open=" + m_open + ", RowCount=" + m_rowCount); + return null; + } + + // need to wait for data read into buffer + int loops = 0; + while (row >= m_buffer.size() && m_loader.isAlive() && loops < 15) + { + log.fine("Waiting for loader row=" + row + ", size=" + m_buffer.size()); + try + { + Thread.sleep(500); // 1/2 second + } + catch (InterruptedException ie) + {} + loops++; + } + + // empty buffer + if (row >= m_buffer.size()) + { + // log.fine( "Empty buffer"); + return null; + } + + // return Data item + MSort sort = (MSort)m_sort.get(row); + Object[] rowData = (Object[])m_buffer.get(sort.index); + // out of bounds + if (rowData == null || col > rowData.length) + { + // log.fine( "No data or Column out of bounds"); + return null; + } + return rowData[col]; + } // getValueAt + + /** + * Indicate that there will be a change + * @param changed changed + */ + public void setChanged (boolean changed) + { + // Can we edit? + if (!m_open || m_readOnly) + return; + + // Indicate Change + m_changed = changed; + if (!changed) + m_rowChanged = -1; + if (changed) + fireDataStatusIEvent("", ""); + } // setChanged + + /** + * Set Value in data and update MField. + * (called directly or from JTable.editingStopped()) + * + * @param value value to assign to cell + * @param row row index of cell + * @param col column index of cell + */ + public final void setValueAt (Object value, int row, int col) + { + setValueAt (value, row, col, false); + } // setValueAt + + /** + * Set Value in data and update MField. + * (called directly or from JTable.editingStopped()) + * + * @param value value to assign to cell + * @param row row index of cell + * @param col column index of cell + * @param force force setting new value + */ + public final void setValueAt (Object value, int row, int col, boolean force) + { + // Can we edit? + if (!m_open || m_readOnly // not accessible + || row < 0 || col < 0 // invalid index + || m_rowCount == 0) // no rows + { + log.finest("r=" + row + " c=" + col + " - R/O=" + m_readOnly + ", Rows=" + m_rowCount + " - Ignored"); + return; + } + + dataSave(row, false); + + // Has anything changed? + Object oldValue = getValueAt(row, col); + if (!force && ( + (oldValue == null && value == null) + || (oldValue != null && oldValue.equals(value)) + || (oldValue != null && value != null && oldValue.toString().equals(value.toString())) + )) + { + log.finest("r=" + row + " c=" + col + " - New=" + value + "==Old=" + oldValue + " - Ignored"); + return; + } + + log.fine("r=" + row + " c=" + col + " = " + value + " (" + oldValue + ")"); + + // Save old value + m_oldValue = new Object[3]; + m_oldValue[0] = new Integer(row); + m_oldValue[1] = new Integer(col); + m_oldValue[2] = oldValue; + + // Set Data item + MSort sort = (MSort)m_sort.get(row); + Object[] rowData = (Object[])m_buffer.get(sort.index); + m_rowChanged = row; + + /** Selection + if (col == 0) + { + rowData[col] = value; + m_buffer.set(sort.index, rowData); + return; + } **/ + + // save original value - shallow copy + if (m_rowData == null) + { + int size = m_fields.size(); + m_rowData = new Object[size]; + for (int i = 0; i < size; i++) + m_rowData[i] = rowData[i]; + } + + // save & update + rowData[col] = value; + m_buffer.set(sort.index, rowData); + // update Table + fireTableCellUpdated(row, col); + // update MField + GridField field = getField(col); + field.setValue(value, m_inserting); + // inform + DataStatusEvent evt = createDSE(); + evt.setChangedColumn(col, field.getColumnName()); + fireDataStatusChanged(evt); + } // setValueAt + + /** + * Get Old Value + * @param row row + * @param col col + * @return old value + */ + public Object getOldValue (int row, int col) + { + if (m_oldValue == null) + return null; + if (((Integer)m_oldValue[0]).intValue() == row + && ((Integer)m_oldValue[1]).intValue() == col) + return m_oldValue[2]; + return null; + } // getOldValue + + /** + * Check if the current row needs to be saved. + * @param onlyRealChange if true the value of a field was actually changed + * (e.g. for new records, which have not been changed) - default false + * @return true it needs to be saved + */ + public boolean needSave(boolean onlyRealChange) + { + return needSave(m_rowChanged, onlyRealChange); + } // needSave + + /** + * Check if the row needs to be saved. + * - only if nothing was changed + * @return true it needs to be saved + */ + public boolean needSave() + { + return needSave(m_rowChanged, false); + } // needSave + + /** + * Check if the row needs to be saved. + * - only when row changed + * - only if nothing was changed + * @param newRow to check + * @return true it needs to be saved + */ + public boolean needSave(int newRow) + { + return needSave(newRow, false); + } // needSave + + /** + * Check if the row needs to be saved. + * - only when row changed + * - only if nothing was changed + * @param newRow to check + * @param onlyRealChange if true the value of a field was actually changed + * (e.g. for new records, which have not been changed) - default false + * @return true it needs to be saved + */ + public boolean needSave(int newRow, boolean onlyRealChange) + { + log.fine("Row=" + newRow + + ", Changed=" + m_rowChanged + "/" + m_changed); // m_rowChanged set in setValueAt + // nothing done + if (!m_changed && m_rowChanged == -1) + return false; + // E.g. New unchanged records + if (m_changed && m_rowChanged == -1 && onlyRealChange) + return false; + // same row + if (newRow == m_rowChanged) + return false; + + return true; + } // needSave + + /*************************************************************************/ + + /** Save OK - O */ + public static final char SAVE_OK = 'O'; // the only OK condition + /** Save Error - E */ + public static final char SAVE_ERROR = 'E'; + /** Save Access Error - A */ + public static final char SAVE_ACCESS = 'A'; + /** Save Mandatory Error - M */ + public static final char SAVE_MANDATORY = 'M'; + /** Save Abort Error - U */ + public static final char SAVE_ABORT = 'U'; + + /** + * Check if it needs to be saved and save it. + * @param newRow row + * @param manualCmd manual command to save + * @return true if not needed to be saved or successful saved + */ + public boolean dataSave (int newRow, boolean manualCmd) + { + log.fine("Row=" + newRow + + ", Changed=" + m_rowChanged + "/" + m_changed); // m_rowChanged set in setValueAt + // nothing done + if (!m_changed && m_rowChanged == -1) + return true; + // same row, don't save yet + if (newRow == m_rowChanged) + return true; + + return (dataSave(manualCmd) == SAVE_OK); + } // dataSave + + /** + * Save unconditional. + * @param manualCmd if true, no vetoable PropertyChange will be fired for save confirmation + * @return OK Or Error condition + * Error info (Access*, FillMandatory, SaveErrorNotUnique, + * SaveErrorRowNotFound, SaveErrorDataChanged) is saved in the log + */ + public char dataSave (boolean manualCmd) + { + // cannot save + if (!m_open) + { + log.warning ("Error - Open=" + m_open); + return SAVE_ERROR; + } + // no need - not changed - row not positioned - no Value changed + if (m_rowChanged == -1) + { + log.config("NoNeed - Changed=" + m_changed + ", Row=" + m_rowChanged); + // return SAVE_ERROR; + if (!manualCmd) + return SAVE_OK; + } + // Value not changed + if (m_rowData == null) + { + log.fine("No Changes"); + return SAVE_ERROR; + } + + if (m_readOnly) + // If Processed - not editable (Find always editable) -> ok for changing payment terms, etc. + { + log.warning("IsReadOnly - ignored"); + dataIgnore(); + return SAVE_ACCESS; + } + + // row not positioned - no Value changed + if (m_rowChanged == -1) + { + if (m_newRow != -1) // new row and nothing changed - might be OK + m_rowChanged = m_newRow; + else + { + fireDataStatusEEvent("SaveErrorNoChange", "", false); + return SAVE_ERROR; + } + } + + // Can we change? + int[] co = getClientOrg(m_rowChanged); + int AD_Client_ID = co[0]; + int AD_Org_ID = co[1]; + if (!MRole.getDefault(m_ctx, false).canUpdate(AD_Client_ID, AD_Org_ID, m_AD_Table_ID, 0, true)) + { + fireDataStatusEEvent(CLogger.retrieveError()); + dataIgnore(); + return SAVE_ACCESS; + } + + log.info("Row=" + m_rowChanged); + + // inform about data save action, if not manually initiated + try + { + if (!manualCmd) + m_vetoableChangeSupport.fireVetoableChange(PROPERTY, 0, m_rowChanged); + } + catch (PropertyVetoException pve) + { + log.warning(pve.getMessage()); + dataIgnore(); + return SAVE_ABORT; + } + + // get updated row data + MSort sort = (MSort)m_sort.get(m_rowChanged); + Object[] rowData = (Object[])m_buffer.get(sort.index); + + // Check Mandatory + String missingColumns = getMandatory(rowData); + if (missingColumns.length() != 0) + { + // Trace.printStack(false, false); + fireDataStatusEEvent("FillMandatory", missingColumns + "\n", true); + return SAVE_MANDATORY; + } + + /** + * Update row ***** + */ + int Record_ID = 0; + if (!m_inserting) + Record_ID = getKeyID(m_rowChanged); + try + { + if (!m_tableName.endsWith("_Trl")) // translation tables have no model + return dataSavePO (Record_ID); + } + catch (Exception e) + { + if (e instanceof ClassNotFoundException) + log.warning(m_tableName + " - " + e.getLocalizedMessage()); + else + { + log.log(Level.SEVERE, "Persistency Issue - " + + m_tableName + ": " + e.getLocalizedMessage(), e); + return SAVE_ERROR; + } + } + + /** Manual Update of Row (i.e. not via PO class) **/ + log.info("NonPO"); + + boolean error = false; + lobReset(); + // + String is = null; + final String ERROR = "ERROR: "; + final String INFO = "Info: "; + + // Update SQL with specific where clause + StringBuffer select = new StringBuffer("SELECT "); + for (int i = 0; i < m_fields.size(); i++) + { + GridField field = (GridField)m_fields.get(i); + if (m_inserting && field.isVirtualColumn()) + continue; + if (i > 0) + select.append(","); + select.append(field.getColumnSQL(true)); // ColumnName or Virtual Column + } + // + select.append(" FROM ").append(m_tableName); + StringBuffer singleRowWHERE = new StringBuffer(); + StringBuffer multiRowWHERE = new StringBuffer(); + // Create SQL & RowID + if (m_inserting) + select.append(" WHERE 1=2"); + else // FOR UPDATE causes - ORA-01002 fetch out of sequence + select.append(" WHERE ").append(getWhereClause(rowData)); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (select.toString(), + ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, null); + ResultSet rs = pstmt.executeQuery(); + // only one row + if (!(m_inserting || rs.next())) + { + rs.close(); + pstmt.close(); + fireDataStatusEEvent("SaveErrorRowNotFound", "", true); + dataRefresh(m_rowChanged); + return SAVE_ERROR; + } + + Object[] rowDataDB = null; + // Prepare + boolean manualUpdate = ResultSet.CONCUR_READ_ONLY == rs.getConcurrency(); + if (DB.isRemoteObjects()) + manualUpdate = true; + if (manualUpdate) + createUpdateSqlReset(); + if (m_inserting) + { + if (manualUpdate) + log.fine("Prepare inserting ... manual"); + else + { + log.fine("Prepare inserting ... RowSet"); + rs.moveToInsertRow (); + } + } + else + { + log.fine("Prepare updating ... manual=" + manualUpdate); + // get current Data in DB + rowDataDB = readData (rs); + } + + /** Data: + * m_rowData = original Data + * rowData = updated Data + * rowDataDB = current Data in DB + * 1) Difference between original & updated Data? N:next + * 2) Difference between original & current Data? Y:don't update + * 3) Update current Data + * 4) Refresh to get last Data (changed by trigger, ...) + */ + + // Constants for Created/Updated(By) + Timestamp now = new Timestamp(System.currentTimeMillis()); + int user = Env.getContextAsInt(m_ctx, "#AD_User_ID"); + + /** + * for every column + */ + int size = m_fields.size(); + int colRs = 1; + for (int col = 0; col < size; col++) + { + GridField field = (GridField)m_fields.get (col); + if (field.isVirtualColumn()) + { + if (!m_inserting) + colRs++; + continue; + } + String columnName = field.getColumnName (); + // log.fine(columnName + "= " + m_rowData[col] + " <> DB: " + rowDataDB[col] + " -> " + rowData[col]); + + // RowID, Virtual Column + if (field.getDisplayType () == DisplayType.RowID + || field.isVirtualColumn()) + ; // ignore + + // New Key + else if (field.isKey () && m_inserting) + { + if (columnName.endsWith ("_ID") || columnName.toUpperCase().endsWith ("_ID")) + { + int insertID = DB.getNextID (m_ctx, m_tableName, null); // no trx + if (manualUpdate) + createUpdateSql (columnName, String.valueOf (insertID)); + else + rs.updateInt (colRs, insertID); // *** + singleRowWHERE.append (columnName).append ("=").append (insertID); + // + is = INFO + columnName + " -> " + insertID + " (Key)"; + } + else // Key with String value + { + String str = rowData[col].toString (); + if (manualUpdate) + createUpdateSql (columnName, DB.TO_STRING (str)); + else + rs.updateString (colRs, str); // *** + singleRowWHERE = new StringBuffer(); // overwrite + singleRowWHERE.append (columnName).append ("=").append (DB.TO_STRING(str)); + // + is = INFO + columnName + " -> " + str + " (StringKey)"; + } + log.fine(is); + } // New Key + + // New DocumentNo + else if (columnName.equals ("DocumentNo")) + { + boolean newDocNo = false; + String docNo = (String)rowData[col]; + // we need to have a doc number + if (docNo == null || docNo.length () == 0) + newDocNo = true; + // Preliminary ID from CalloutSystem + else if (docNo.startsWith ("<") && docNo.endsWith (">")) + newDocNo = true; + + if (newDocNo || m_inserting) + { + String insertDoc = null; + // always overwrite if insering with mandatory DocType DocNo + if (m_inserting) + insertDoc = DB.getDocumentNo (m_ctx, m_WindowNo, + m_tableName, true, null); // only doc type - no trx + log.fine("DocumentNo entered=" + docNo + ", DocTypeInsert=" + insertDoc + ", newDocNo=" + newDocNo); + // can we use entered DocNo? + if (insertDoc == null || insertDoc.length () == 0) + { + if (!newDocNo && docNo != null && docNo.length () > 0) + insertDoc = docNo; + else // get a number from DocType or Table + insertDoc = DB.getDocumentNo (m_ctx, m_WindowNo, + m_tableName, false, null); // no trx + } + // There might not be an automatic document no for this document + if (insertDoc == null || insertDoc.length () == 0) + { + // in case DB function did not return a value + if (docNo != null && docNo.length () != 0) + insertDoc = (String)rowData[col]; + else + { + error = true; + is = ERROR + field.getColumnName () + "= " + rowData[col] + " NO DocumentNo"; + log.fine(is); + break; + } + } + // + if (manualUpdate) + createUpdateSql (columnName, DB.TO_STRING (insertDoc)); + else + rs.updateString (colRs, insertDoc); // *** + // + is = INFO + columnName + " -> " + insertDoc + " (DocNo)"; + log.fine(is); + } + } // New DocumentNo + + // New Value(key) + else if (columnName.equals ("Value") && m_inserting) + { + String value = (String)rowData[col]; + // Get from Sequence, if not entered + if (value == null || value.length () == 0) + { + value = DB.getDocumentNo (m_ctx, m_WindowNo, m_tableName, false, null); + // No Value + if (value == null || value.length () == 0) + { + error = true; + is = ERROR + field.getColumnName () + "= " + rowData[col] + + " No Value"; + log.fine(is); + break; + } + } + if (manualUpdate) + createUpdateSql (columnName, DB.TO_STRING (value)); + else + rs.updateString (colRs, value); // *** + // + is = INFO + columnName + " -> " + value + " (Value)"; + log.fine(is); + } // New Value(key) + + // Updated - check database + else if (columnName.equals ("Updated")) + { + if (m_compareDB && !m_inserting && !m_rowData[col].equals (rowDataDB[col])) // changed + { + error = true; + is = ERROR + field.getColumnName () + "= " + m_rowData[col] + + " != DB: " + rowDataDB[col]; + log.fine(is); + break; + } + if (manualUpdate) + createUpdateSql (columnName, DB.TO_DATE (now, false)); + else + rs.updateTimestamp (colRs, now); // *** + // + is = INFO + "Updated/By -> " + now + " - " + user; + log.fine(is); + } // Updated + + // UpdatedBy - update + else if (columnName.equals ("UpdatedBy")) + { + if (manualUpdate) + createUpdateSql (columnName, String.valueOf (user)); + else + rs.updateInt (colRs, user); // *** + } // UpdatedBy + + // Created + else if (m_inserting && columnName.equals ("Created")) + { + if (manualUpdate) + createUpdateSql (columnName, DB.TO_DATE (now, false)); + else + rs.updateTimestamp (colRs, now); // *** + } // Created + + // CreatedBy + else if (m_inserting && columnName.equals ("CreatedBy")) + { + if (manualUpdate) + createUpdateSql (columnName, String.valueOf (user)); + else + rs.updateInt (colRs, user); // *** + } // CreatedBy + + // Nothing changed & null + else if (m_rowData[col] == null && rowData[col] == null) + { + if (m_inserting) + { + if (manualUpdate) + createUpdateSql (columnName, "NULL"); + else + rs.updateNull (colRs); // *** + is = INFO + columnName + "= NULL"; + log.fine(is); + } + } + + // *** Data changed *** + else if (m_inserting + || (m_rowData[col] == null && rowData[col] != null) + || (m_rowData[col] != null && rowData[col] == null) + || !m_rowData[col].equals (rowData[col])) // changed + { + // Original == DB + if (m_inserting || !m_compareDB + || (m_rowData[col] == null && rowDataDB[col] == null) + || (m_rowData[col] != null && m_rowData[col].equals (rowDataDB[col]))) + { + if (CLogMgt.isLevelFinest()) + log.fine(columnName + "=" + rowData[col] + + " " + (rowData[col]==null ? "" : rowData[col].getClass().getName())); + // + boolean encrypted = field.isEncryptedColumn(); + // + String type = "String"; + if (rowData[col] == null) + { + if (manualUpdate) + createUpdateSql (columnName, "NULL"); + else + rs.updateNull (colRs); // *** + } + + // ID - int + else if (DisplayType.isID (field.getDisplayType()) + || field.getDisplayType() == DisplayType.Integer) + { + try + { + Object dd = rowData[col]; + Integer iii = null; + if (dd instanceof Integer) + iii = (Integer)dd; + else + iii = new Integer(dd.toString()); + if (encrypted) + iii = (Integer)encrypt(iii); + if (manualUpdate) + createUpdateSql (columnName, String.valueOf (iii)); + else + rs.updateInt (colRs, iii.intValue()); // *** + } + catch (Exception e) // could also be a String (AD_Language, AD_Message) + { + if (manualUpdate) + createUpdateSql (columnName, DB.TO_STRING (rowData[col].toString ())); + else + rs.updateString (colRs, rowData[col].toString ()); // *** + } + type = "Int"; + } + // Numeric - BigDecimal + else if (DisplayType.isNumeric (field.getDisplayType ())) + { + BigDecimal bd = (BigDecimal)rowData[col]; + if (encrypted) + bd = (BigDecimal)encrypt(bd); + if (manualUpdate) + createUpdateSql (columnName, bd.toString ()); + else + rs.updateBigDecimal (colRs, bd); // *** + type = "Number"; + } + // Date - Timestamp + else if (DisplayType.isDate (field.getDisplayType ())) + { + Timestamp ts = (Timestamp)rowData[col]; + if (encrypted) + ts = (Timestamp)encrypt(ts); + if (manualUpdate) + createUpdateSql (columnName, DB.TO_DATE (ts, false)); + else + rs.updateTimestamp (colRs, ts); // *** + type = "Date"; + } + // LOB + else if (field.getDisplayType() == DisplayType.TextLong) + { + PO_LOB lob = new PO_LOB (getTableName(), columnName, + null, field.getDisplayType(), rowData[col]); + lobAdd(lob); + type = "CLOB"; + } + // Boolean + else if (field.getDisplayType() == DisplayType.YesNo) + { + String yn = null; + if (rowData[col] instanceof Boolean) + { + Boolean bb = (Boolean)rowData[col]; + yn = bb.booleanValue() ? "Y" : "N"; + } + else + yn = "Y".equals(rowData[col]) ? "Y" : "N"; + if (encrypted) + yn = (String)yn; + if (manualUpdate) + createUpdateSql (columnName, DB.TO_STRING (yn)); + else + rs.updateString (colRs, yn); // *** + } + // String and others + else + { + String str = rowData[col].toString (); + if (encrypted) + str = (String)encrypt(str); + if (manualUpdate) + createUpdateSql (columnName, DB.TO_STRING (str)); + else + rs.updateString (colRs, str); // *** + } + // + is = INFO + columnName + "= " + m_rowData[col] + + " -> " + rowData[col] + " (" + type + ")"; + if (encrypted) + is += " encrypted"; + log.fine(is); + } + // Original != DB + else + { + error = true; + is = ERROR + field.getColumnName () + "= " + m_rowData[col] + + " != DB: " + rowDataDB[col] + " -> " + rowData[col]; + log.fine(is); + } + } // Data changed + + // Single Key - retrieval sql + if (field.isKey() && !m_inserting) + { + if (rowData[col] == null) + throw new RuntimeException("Key is NULL - " + columnName); + if (columnName.endsWith ("_ID")) + singleRowWHERE.append (columnName).append ("=").append (rowData[col]); + else + { + singleRowWHERE = new StringBuffer(); // overwrite + singleRowWHERE.append (columnName).append ("=").append (DB.TO_STRING(rowData[col].toString())); + } + } + // MultiKey Inserting - retrieval sql + if (field.isParentColumn()) + { + if (rowData[col] == null) + throw new RuntimeException("MultiKey Parent is NULL - " + columnName); + if (multiRowWHERE.length() != 0) + multiRowWHERE.append(" AND "); + if (columnName.endsWith ("_ID")) + multiRowWHERE.append (columnName).append ("=").append (rowData[col]); + else + multiRowWHERE.append (columnName).append ("=").append (DB.TO_STRING(rowData[col].toString())); + } + // + colRs++; + } // for every column + + if (error) + { + if (manualUpdate) + createUpdateSqlReset(); + else + rs.cancelRowUpdates(); + rs.close(); + pstmt.close(); + fireDataStatusEEvent("SaveErrorDataChanged", "", true); + dataRefresh(m_rowChanged); + return SAVE_ERROR; + } + + /** + * Save to Database + */ + // + String whereClause = singleRowWHERE.toString(); + if (whereClause.length() == 0) + whereClause = multiRowWHERE.toString(); + if (m_inserting) + { + log.fine("Inserting ..."); + if (manualUpdate) + { + String sql = createUpdateSql(true, null); + int no = DB.executeUpdateEx (sql, null); // no Trx + if (no != 1) + log.log(Level.SEVERE, "Insert #=" + no + " - " + sql); + } + else + rs.insertRow(); + } + else + { + log.fine("Updating ... " + whereClause); + if (manualUpdate) + { + String sql = createUpdateSql(false, whereClause); + int no = DB.executeUpdateEx (sql, null); // no Trx + if (no != 1) + log.log(Level.SEVERE, "Update #=" + no + " - " + sql); + } + else + rs.updateRow(); + } + + log.fine("Committing ..."); + DB.commit(true, null); // no Trx + // + lobSave(whereClause); + rs.close(); + pstmt.close(); + + // Need to re-read row to get ROWID, Key, DocumentNo, Trigger, virtual columns + log.fine("Reading ... " + whereClause); + StringBuffer refreshSQL = new StringBuffer(m_SQL_Select) + .append(" WHERE ").append(whereClause); + pstmt = DB.prepareStatement(refreshSQL.toString(), null); + rs = pstmt.executeQuery(); + if (rs.next()) + { + rowDataDB = readData(rs); + // update buffer + m_buffer.set(sort.index, rowDataDB); + fireTableRowsUpdated(m_rowChanged, m_rowChanged); + } + else + log.log(Level.SEVERE, "Inserted row not found"); + // + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException e) + { + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception ex) + { + } + + String msg = "SaveError"; + if (e.getErrorCode() == 1) // Unique Constraint + { + log.log(Level.SEVERE, "Key Not Unique", e); + msg = "SaveErrorNotUnique"; + } + else + log.log(Level.SEVERE, select.toString(), e); + fireDataStatusEEvent(msg, e.getLocalizedMessage(), true); + return SAVE_ERROR; + } + + // everything ok + m_rowData = null; + m_changed = false; + m_compareDB = true; + m_rowChanged = -1; + m_newRow = -1; + m_inserting = false; + fireDataStatusIEvent("Saved", ""); + // + log.info("fini"); + return SAVE_OK; + } // dataSave + + /** + * Save via PO + * @param Record_ID + * @return SAVE_ERROR or SAVE_OK + * @throws Exception + */ + private char dataSavePO (int Record_ID) throws Exception + { + log.fine("ID=" + Record_ID); + // + MSort sort = (MSort)m_sort.get(m_rowChanged); + Object[] rowData = (Object[])m_buffer.get(sort.index); + // + MTable table = MTable.get (m_ctx, m_AD_Table_ID); + PO po = null; + if (Record_ID != -1) + po = table.getPO(Record_ID, null); + else // Multi - Key + po = table.getPO(getWhereClause(rowData), null); + // No Persistent Object + if (po == null) + throw new ClassNotFoundException ("No Persistent Object"); + + int size = m_fields.size(); + for (int col = 0; col < size; col++) + { + GridField field = (GridField)m_fields.get (col); + if (field.isVirtualColumn()) + continue; + String columnName = field.getColumnName (); + Object value = rowData[col]; + Object oldValue = m_rowData[col]; + // RowID + if (field.getDisplayType() == DisplayType.RowID) + ; // ignore + + // Nothing changed & null + else if (oldValue == null && value == null) + ; // ignore + + // *** Data changed *** + else if (m_inserting + || (oldValue == null && value != null) + || (oldValue != null && value == null) + || !oldValue.equals (value)) // changed + { + // Check existence + int poIndex = po.get_ColumnIndex(columnName); + if (poIndex < 0) + { + // Custom Fields not in PO + po.set_CustomColumn(columnName, value); + // log.log(Level.SEVERE, "Column not found: " + columnName); + continue; + } + + Object dbValue = po.get_Value(poIndex); + if (m_inserting + || !m_compareDB + // Original == DB + || (oldValue == null && dbValue == null) + || (oldValue != null && oldValue.equals (dbValue)) + // Target == DB (changed by trigger to new value already) + || (value == null && dbValue == null) + || (value != null && value.equals (dbValue)) ) + { + po.set_ValueNoCheck (columnName, value); + } + // Original != DB + else + { + String msg = columnName + + "= " + oldValue + + (oldValue==null ? "" : "(" + oldValue.getClass().getName() + ")") + + " != DB: " + dbValue + + (dbValue==null ? "" : "(" + dbValue.getClass().getName() + ")") + + " -> New: " + value + + (value==null ? "" : "(" + value.getClass().getName() + ")"); + // CLogMgt.setLevel(Level.FINEST); + // po.dump(); + fireDataStatusEEvent("SaveErrorDataChanged", msg, true); + dataRefresh(m_rowChanged); + return SAVE_ERROR; + } + } // Data changed + + } // for every column + + if (!po.save()) + { + String msg = "SaveError"; + String info = ""; + ValueNamePair ppE = CLogger.retrieveError(); + if (ppE != null) + { + msg = ppE.getValue(); + info = ppE.getName(); + // Unique Constraint + Exception ex = CLogger.retrieveException(); + if (ex != null + && ex instanceof SQLException + && ((SQLException)ex).getErrorCode() == 1) + msg = "SaveErrorNotUnique"; + } + fireDataStatusEEvent(msg, info, true); + return SAVE_ERROR; + } + + // Refresh - update buffer + String whereClause = po.get_WhereClause(true); + log.fine("Reading ... " + whereClause); + StringBuffer refreshSQL = new StringBuffer(m_SQL_Select) + .append(" WHERE ").append(whereClause); + PreparedStatement pstmt = DB.prepareStatement(refreshSQL.toString(), null); + try + { + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + Object[] rowDataDB = readData(rs); + // update buffer + m_buffer.set(sort.index, rowDataDB); + fireTableRowsUpdated(m_rowChanged, m_rowChanged); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException e) + { + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception ex) + { + } + + String msg = "SaveError"; + log.log(Level.SEVERE, refreshSQL.toString(), e); + fireDataStatusEEvent(msg, e.getLocalizedMessage(), true); + return SAVE_ERROR; + } + + // everything ok + m_rowData = null; + m_changed = false; + m_compareDB = true; + m_rowChanged = -1; + m_newRow = -1; + m_inserting = false; + // + ValueNamePair pp = CLogger.retrieveWarning(); + if (pp != null) + { + String msg = pp.getValue(); + String info = pp.getName(); + fireDataStatusEEvent(msg, info, false); + } + else + { + pp = CLogger.retrieveInfo(); + String msg = "Saved"; + String info = ""; + if (pp != null) + { + msg = pp.getValue(); + info = pp.getName(); + } + fireDataStatusIEvent(msg, info); + } + // + log.config("fini"); + return SAVE_OK; + } // dataSavePO + + /** + * Get Record Where Clause from data (single key or multi-parent) + * @param rowData data + * @return where clause or null + */ + private String getWhereClause (Object[] rowData) + { + int size = m_fields.size(); + StringBuffer singleRowWHERE = null; + StringBuffer multiRowWHERE = null; + for (int col = 0; col < size; col++) + { + GridField field = (GridField)m_fields.get (col); + if (field.isKey()) + { + String columnName = field.getColumnName(); + Object value = rowData[col]; + if (value == null) + { + log.log(Level.WARNING, "PK data is null - " + columnName); + return null; + } + if (columnName.endsWith ("_ID")) + singleRowWHERE = new StringBuffer(columnName) + .append ("=").append (value); + else + singleRowWHERE = new StringBuffer(columnName) + .append ("=").append (DB.TO_STRING(value.toString())); + } + else if (field.isParentColumn()) + { + String columnName = field.getColumnName(); + Object value = rowData[col]; + if (value == null) + { + log.log(Level.INFO, "FK data is null - " + columnName); + continue; + } + if (multiRowWHERE == null) + multiRowWHERE = new StringBuffer(); + else + multiRowWHERE.append(" AND "); + if (columnName.endsWith ("_ID")) + multiRowWHERE.append (columnName) + .append ("=").append (value); + else + multiRowWHERE.append (columnName) + .append ("=").append (DB.TO_STRING(value.toString())); + } + } // for all columns + if (singleRowWHERE != null) + return singleRowWHERE.toString(); + if (multiRowWHERE != null) + return multiRowWHERE.toString(); + log.log(Level.WARNING, "No key Found"); + return null; + } // getWhereClause + + /*************************************************************************/ + + private ArrayList m_createSqlColumn = new ArrayList(); + private ArrayList m_createSqlValue = new ArrayList(); + + /** + * Prepare SQL creation + * @param columnName column name + * @param value value + */ + private void createUpdateSql (String columnName, String value) + { + m_createSqlColumn.add(columnName); + m_createSqlValue.add(value); + log.finest("#" + m_createSqlColumn.size() + + " - " + columnName + "=" + value); + } // createUpdateSQL + + /** + * Create update/insert SQL + * @param insert true if insert - update otherwise + * @param whereClause where clause for update + * @return sql statement + */ + private String createUpdateSql (boolean insert, String whereClause) + { + StringBuffer sb = new StringBuffer(); + if (insert) + { + sb.append("INSERT INTO ").append(m_tableName).append(" ("); + for (int i = 0; i < m_createSqlColumn.size(); i++) + { + if (i != 0) + sb.append(","); + sb.append(m_createSqlColumn.get(i)); + } + sb.append(") VALUES ( "); + for (int i = 0; i < m_createSqlValue.size(); i++) + { + if (i != 0) + sb.append(","); + sb.append(m_createSqlValue.get(i)); + } + sb.append(")"); + } + else + { + sb.append("UPDATE ").append(m_tableName).append(" SET "); + for (int i = 0; i < m_createSqlColumn.size(); i++) + { + if (i != 0) + sb.append(","); + sb.append(m_createSqlColumn.get(i)).append("=").append(m_createSqlValue.get(i)); + } + sb.append(" WHERE ").append(whereClause); + } + log.fine(sb.toString()); + // reset + createUpdateSqlReset(); + return sb.toString(); + } // createUpdateSql + + /** + * Reset Update Data + */ + private void createUpdateSqlReset() + { + m_createSqlColumn = new ArrayList(); + m_createSqlValue = new ArrayList(); + } // createUpdateSqlReset + + /** + * Get Mandatory empty columns + * @param rowData row data + * @return String with missing column headers/labels + */ + private String getMandatory(Object[] rowData) + { + // see also => ProcessParameter.saveParameter + StringBuffer sb = new StringBuffer(); + + // Check all columns + int size = m_fields.size(); + for (int i = 0; i < size; i++) + { + GridField field = (GridField)m_fields.get(i); + if (field.isMandatory(true)) // check context + { + if (rowData[i] == null || rowData[i].toString().length() == 0) + { + field.setInserting (true); // set editable otherwise deadlock + field.setError(true); + if (sb.length() > 0) + sb.append(", "); + sb.append(field.getHeader()); + } + else + field.setError(false); + } + } + + if (sb.length() == 0) + return ""; + return sb.toString(); + } // getMandatory + + /*************************************************************************/ + + /** LOB Info */ + private ArrayList m_lobInfo = null; + + /** + * Reset LOB info + */ + private void lobReset() + { + m_lobInfo = null; + } // resetLOB + + /** + * Prepare LOB save + * @param lob value + */ + private void lobAdd (PO_LOB lob) + { + log.fine("LOB=" + lob); + if (m_lobInfo == null) + m_lobInfo = new ArrayList(); + m_lobInfo.add(lob); + } // lobAdd + + /** + * Save LOB + * @param whereClause where clause + */ + private void lobSave (String whereClause) + { + if (m_lobInfo == null) + return; + for (int i = 0; i < m_lobInfo.size(); i++) + { + PO_LOB lob = (PO_LOB)m_lobInfo.get(i); + lob.save(whereClause, null); // no trx + } // for all LOBs + lobReset(); + } // lobSave + + + /************************************************************************** + * New Record after current Row + * @param currentRow row + * @param copyCurrent copy + * @return true if success - + * Error info (Access*, AccessCannotInsert) is saved in the log + */ + public boolean dataNew (int currentRow, boolean copyCurrent) + { + log.info("Current=" + currentRow + ", Copy=" + copyCurrent); + // Read only + if (m_readOnly) + { + fireDataStatusEEvent("AccessCannotInsert", "", true); + return false; + } + + /** @todo No TableLevel */ + // || !Access.canViewInsert(m_ctx, m_WindowNo, tableLevel, true, true)) + // fireDataStatusEvent(Log.retrieveError()); + + // see if we need to save + dataSave(-2, false); + + + m_inserting = true; + // Create default data + int size = m_fields.size(); + m_rowData = new Object[size]; // "original" data + Object[] rowData = new Object[size]; + // fill data + if (copyCurrent) + { + MSort sort = (MSort) m_sort.get(currentRow); + Object[] origData = (Object[])m_buffer.get(sort.index); + for (int i = 0; i < size; i++) + { + GridField field = (GridField)m_fields.get(i); + String columnName = field.getColumnName(); + if (field.isVirtualColumn()) + ; + else if (field.isKey() + || columnName.equals("AD_Client_ID") + // + || columnName.startsWith("Created") || columnName.startsWith("Updated") + || columnName.equals("EntityType") || columnName.equals("DocumentNo") + || columnName.equals("Processed") || columnName.equals("IsSelfService") + || columnName.equals("DocAction") || columnName.equals("DocStatus") + || columnName.startsWith("Ref_") + // Order/Invoice + || columnName.equals("GrandTotal") || columnName.equals("TotalLines") + || columnName.equals("C_CashLine_ID") || columnName.equals("C_Payment_ID") + || columnName.equals("IsPaid") || columnName.equals("IsAllocated") + ) + { + rowData[i] = field.getDefault(); + field.setValue(rowData[i], m_inserting); + } + else + rowData[i] = origData[i]; + } + } + else // new + { + for (int i = 0; i < size; i++) + { + GridField field = (GridField)m_fields.get(i); + rowData[i] = field.getDefault(); + field.setValue(rowData[i], m_inserting); + } + } + m_changed = true; + m_compareDB = true; + m_rowChanged = -1; // only changed in setValueAt + m_newRow = currentRow + 1; + // if there is no record, the current row could be 0 (and not -1) + if (m_buffer.size() < m_newRow) + m_newRow = m_buffer.size(); + + // add Data at end of buffer + MSort sort = new MSort(m_buffer.size(), null); // index + m_buffer.add(rowData); + // add Sort pointer + m_sort.add(m_newRow, sort); + m_rowCount++; + + // inform + log.fine("Current=" + currentRow + ", New=" + m_newRow); + fireTableRowsInserted(m_newRow, m_newRow); + fireDataStatusIEvent(copyCurrent ? "UpdateCopied" : "Inserted", ""); + log.fine("Current=" + currentRow + ", New=" + m_newRow + " - complete"); + return true; + } // dataNew + + + /************************************************************************** + * Delete Data + * @param row row + * @return true if success - + * Error info (Access*, AccessNotDeleteable, DeleteErrorDependent, + * DeleteError) is saved in the log + */ + public boolean dataDelete (int row) + { + log.info("Row=" + row); + if (row < 0) + return false; + + // Tab R/O + if (m_readOnly) + { + fireDataStatusEEvent("AccessCannotDelete", "", true); // previleges + return false; + } + + // Is this record deletable? + if (!m_deleteable) + { + fireDataStatusEEvent("AccessNotDeleteable", "", true); // audit + return false; + } + + // Processed Column and not an Import Table + if (m_indexProcessedColumn > 0 && !m_tableName.startsWith("I_")) + { + Boolean processed = (Boolean)getValueAt(row, m_indexProcessedColumn); + if (processed != null && processed.booleanValue()) + { + fireDataStatusEEvent("CannotDeleteTrx", "", true); + return false; + } + } + + + /** @todo check Access */ + // fireDataStatusEvent(Log.retrieveError()); + + MSort sort = (MSort)m_sort.get(row); + Object[] rowData = (Object[])m_buffer.get(sort.index); + // + MTable table = MTable.get (m_ctx, m_AD_Table_ID); + PO po = null; + int Record_ID = getKeyID(m_rowChanged); + if (Record_ID != -1) + po = table.getPO(Record_ID, null); + else // Multi - Key + po = table.getPO(getWhereClause(rowData), null); + + // Delete via PO + if (po != null) + { + boolean ok = false; + try + { + ok = po.delete(false); + } + catch (Throwable t) + { + log.log(Level.SEVERE, "Delete", t); + } + if (!ok) + { + ValueNamePair vp = CLogger.retrieveError(); + if (vp != null) + fireDataStatusEEvent(vp); + else + fireDataStatusEEvent("DeleteError", "", true); + return false; + } + } + else // Delete via SQL + { + StringBuffer sql = new StringBuffer("DELETE "); + sql.append(m_tableName).append(" WHERE ").append(getWhereClause(rowData)); + int no = 0; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql.toString(), null); + no = pstmt.executeUpdate(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql.toString(), e); + String msg = "DeleteError"; + if (e.getErrorCode() == 2292) // Child Record Found + msg = "DeleteErrorDependent"; + fireDataStatusEEvent(msg, e.getLocalizedMessage(), true); + return false; + } + // Check Result + if (no != 1) + { + log.log(Level.SEVERE, "Number of deleted rows = " + no); + return false; + } + } + + // Get Sort + int bufferRow = sort.index; + // Delete row in Buffer and shifts all below up + m_buffer.remove(bufferRow); + m_rowCount--; + + // Delete row in Sort + m_sort.remove(row); + // Correct pointer in Sort + for (int i = 0; i < m_sort.size(); i++) + { + MSort ptr = (MSort)m_sort.get(i); + if (ptr.index > bufferRow) + ptr.index--; // move up + } + + // inform + m_changed = false; + m_rowChanged = -1; + fireTableRowsDeleted(row, row); + fireDataStatusIEvent("Deleted", ""); + log.fine("Row=" + row + " complete"); + return true; + } // dataDelete + + + /************************************************************************** + * Ignore changes + */ + public void dataIgnore() + { + if (!m_inserting && !m_changed && m_rowChanged < 0) + { + log.fine("Nothing to ignore"); + return; + } + log.info("Inserting=" + m_inserting); + + // Inserting - delete new row + if (m_inserting) + { + // Get Sort + MSort sort = (MSort)m_sort.get(m_newRow); + int bufferRow = sort.index; + // Delete row in Buffer and shifts all below up + m_buffer.remove(bufferRow); + m_rowCount--; + // Delete row in Sort + m_sort.remove(m_newRow); // pintint to the last column, so no adjustment + // + m_changed = false; + m_rowData = null; + m_rowChanged = -1; + m_inserting = false; + // inform + fireTableRowsDeleted(m_newRow, m_newRow); + } + else + { + // update buffer + if (m_rowData != null) + { + MSort sort = (MSort)m_sort.get(m_rowChanged); + m_buffer.set(sort.index, m_rowData); + } + m_changed = false; + m_rowData = null; + m_rowChanged = -1; + m_inserting = false; + // inform + // fireTableRowsUpdated(m_rowChanged, m_rowChanged); >> messes up display?? (clearSelection) + } + m_newRow = -1; + fireDataStatusIEvent("Ignored", ""); + } // dataIgnore + + + /** + * Refresh Row - ignore changes + * @param row row + */ + public void dataRefresh (int row) + { + log.info("Row=" + row); + + if (row < 0 || m_sort.size() == 0 || m_inserting) + return; + + MSort sort = (MSort)m_sort.get(row); + Object[] rowData = (Object[])m_buffer.get(sort.index); + + // ignore + dataIgnore(); + + // Create SQL + String where = getWhereClause(rowData); + if (where == null || where.length() == 0) + where = "1=2"; + String sql = m_SQL_Select + " WHERE " + where; + sort = (MSort)m_sort.get(row); + Object[] rowDataDB = null; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + ResultSet rs = pstmt.executeQuery(); + // only one row + if (rs.next()) + rowDataDB = readData(rs); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + fireTableRowsUpdated(row, row); + fireDataStatusEEvent("RefreshError", sql, true); + return; + } + + // update buffer + m_buffer.set(sort.index, rowDataDB); + // info + m_rowData = null; + m_changed = false; + m_rowChanged = -1; + m_inserting = false; + fireTableRowsUpdated(row, row); + fireDataStatusIEvent("Refreshed", ""); + } // dataRefresh + + + /** + * Refresh all Rows - ignore changes + */ + public void dataRefreshAll() + { + log.info(""); + m_inserting = false; // should not happen + dataIgnore(); + close(false); + open(m_maxRows); + // Info + m_rowData = null; + m_changed = false; + m_rowChanged = -1; + m_inserting = false; + fireTableDataChanged(); + fireDataStatusIEvent("Refreshed", ""); + } // dataRefreshAll + + + /** + * Requery with new whereClause + * @param whereClause sql where clause + * @param onlyCurrentRows only current rows + * @param onlyCurrentDays how many days back + * @return true if success + */ + public boolean dataRequery (String whereClause, boolean onlyCurrentRows, int onlyCurrentDays) + { + log.info(whereClause + "; OnlyCurrent=" + onlyCurrentRows); + close(false); + m_onlyCurrentDays = onlyCurrentDays; + setSelectWhereClause(whereClause, onlyCurrentRows, m_onlyCurrentDays); + open(m_maxRows); + // Info + m_rowData = null; + m_changed = false; + m_rowChanged = -1; + m_inserting = false; + fireTableDataChanged(); + fireDataStatusIEvent("Refreshed", ""); + return true; + } // dataRequery + + + /************************************************************************** + * Is Cell Editable. + * Is queried from JTable before checking VCellEditor.isCellEditable + * @param row the row index being queried + * @param col the column index being queried + * @return true, if editable + */ + public boolean isCellEditable (int row, int col) + { + // log.fine( "MTable.isCellEditable - Row=" + row + ", Col=" + col); + // Make Rows selectable + // if (col == 0) + // return true; + + // Entire Table not editable + if (m_readOnly) + return false; + // Key not editable + if (col == m_indexKeyColumn) + return false; + /** @todo check link columns */ + + // Check column range + if (col < 0 && col >= m_fields.size()) + return false; + // IsActive Column always editable if no processed exists + if (col == m_indexActiveColumn && m_indexProcessedColumn == -1) + return true; + // Row + if (!isRowEditable(row)) + return false; + + // Column + return ((GridField)m_fields.get(col)).isEditable(false); + } // IsCellEditable + + + /** + * Is Current Row Editable + * @param row row + * @return true if editable + */ + public boolean isRowEditable (int row) + { + // log.fine( "MTable.isRowEditable - Row=" + row); + // Entire Table not editable or no row + if (m_readOnly || row < 0) + return false; + // If not Active - not editable + if (m_indexActiveColumn > 0) // && m_TabNo != Find.s_TabNo) + { + Object value = getValueAt(row, m_indexActiveColumn); + if (value instanceof Boolean) + { + if (!((Boolean)value).booleanValue()) + return false; + } + else if ("N".equals(value)) + return false; + } + // If Processed - not editable (Find always editable) + if (m_indexProcessedColumn > 0) // && m_TabNo != Find.s_TabNo) + { + Object processed = getValueAt(row, m_indexProcessedColumn); + if (processed instanceof Boolean) + { + if (((Boolean)processed).booleanValue()) + return false; + } + else if ("Y".equals(processed)) + return false; + } + // + int[] co = getClientOrg(row); + int AD_Client_ID = co[0]; + int AD_Org_ID = co[1]; + int Record_ID = getKeyID(row); + return MRole.getDefault(m_ctx, false).canUpdate + (AD_Client_ID, AD_Org_ID, m_AD_Table_ID, Record_ID, false); + } // isRowEditable + + /** + * Get Client Org for row + * @param row row + * @return array [0] = Client [1] = Org - a value of -1 is not defined/found + */ + private int[] getClientOrg (int row) + { + int AD_Client_ID = -1; + if (m_indexClientColumn != -1) + { + Integer ii = (Integer)getValueAt(row, m_indexClientColumn); + if (ii != null) + AD_Client_ID = ii.intValue(); + } + int AD_Org_ID = 0; + if (m_indexOrgColumn != -1) + { + Integer ii = (Integer)getValueAt(row, m_indexOrgColumn); + if (ii != null) + AD_Org_ID = ii.intValue(); + } + return new int[] {AD_Client_ID, AD_Org_ID}; + } // getClientOrg + + /** + * Set entire table as read only + * @param value new read only value + */ + public void setReadOnly (boolean value) + { + log.fine("ReadOnly=" + value); + m_readOnly = value; + } // setReadOnly + + /** + * Is entire Table Read/Only + * @return true if read only + */ + public boolean isReadOnly() + { + return m_readOnly; + } // isReadOnly + + /** + * Is inserting + * @return true if inserting + */ + public boolean isInserting() + { + return m_inserting; + } // isInserting + + /** + * Set Compare DB. + * If Set to false, save overwrites the record, regardless of DB changes. + * (When a payment is changed in Sales Order, the payment reversal clears the payment id) + * @param compareDB compare DB - false forces overwrite + */ + public void setCompareDB (boolean compareDB) + { + m_compareDB = compareDB; + } // setCompareDB + + /** + * Get Compare DB. + * @return false if save overwrites the record, regardless of DB changes + * (false forces overwrite). + */ + public boolean getCompareDB () + { + return m_compareDB; + } // getCompareDB + + + /** + * Can Table rows be deleted + * @param value new deleteable value + */ + public void setDeleteable (boolean value) + { + log.fine("Deleteable=" + value); + m_deleteable = value; + } // setDeleteable + + + /************************************************************************** + * Read Data from Recordset + * @param rs result set + * @return Data Array + */ + private Object[] readData (ResultSet rs) + { + int size = m_fields.size(); + Object[] rowData = new Object[size]; + String columnName = null; + int displayType = 0; + + // Types see also MField.createDefault + try + { + // get row data + for (int j = 0; j < size; j++) + { + // Column Info + GridField field = (GridField)m_fields.get(j); + columnName = field.getColumnName(); + displayType = field.getDisplayType(); + // Integer, ID, Lookup (UpdatedBy is a numeric column) + if (displayType == DisplayType.Integer + || (DisplayType.isID(displayType) + && (columnName.endsWith("_ID") || columnName.endsWith("_Acct") + || columnName.equals("AD_Key") || columnName.equals("AD_Display"))) + || columnName.endsWith("atedBy")) + { + rowData[j] = new Integer(rs.getInt(j+1)); // Integer + if (rs.wasNull()) + rowData[j] = null; + } + // Number + else if (DisplayType.isNumeric(displayType)) + rowData[j] = rs.getBigDecimal(j+1); // BigDecimal + // Date + else if (DisplayType.isDate(displayType)) + rowData[j] = rs.getTimestamp(j+1); // Timestamp + // RowID or Key (and Selection) + else if (displayType == DisplayType.RowID) + rowData[j] = null; + // YesNo + else if (displayType == DisplayType.YesNo) + { + String str = rs.getString(j+1); + if (field.isEncryptedColumn()) + str = (String)decrypt(str); + rowData[j] = new Boolean ("Y".equals(str)); // Boolean + } + // LOB + else if (DisplayType.isLOB(displayType)) + { + Object value = rs.getObject(j+1); + if (rs.wasNull()) + rowData[j] = null; + else if (value instanceof Clob) + { + Clob lob = (Clob)value; + long length = lob.length(); + rowData[j] = lob.getSubString(1, (int)length); + } + else if (value instanceof Blob) + { + Blob lob = (Blob)value; + long length = lob.length(); + rowData[j] = lob.getBytes(1, (int)length); + } + } + // String + else + rowData[j] = rs.getString(j+1); // String + // Encrypted + if (field.isEncryptedColumn() && displayType != DisplayType.YesNo) + rowData[j] = decrypt(rowData[j]); + } + } + catch (SQLException e) + { + log.log(Level.SEVERE, columnName + ", DT=" + displayType, e); + } + return rowData; + } // readData + + /** + * Encrypt + * @param xx clear data + * @return encrypted value + */ + private Object encrypt (Object xx) + { + if (xx == null) + return null; + return SecureEngine.encrypt(xx); + } // encrypt + + /** + * Decrypt + * @param yy encrypted data + * @return clear data + */ + private Object decrypt (Object yy) + { + if (yy == null) + return null; + return SecureEngine.decrypt(yy); + } // decrypt + + /************************************************************************** + * Remove Data Status Listener + * @param l listener + */ + public synchronized void removeDataStatusListener(DataStatusListener l) + { + listenerList.remove(DataStatusListener.class, l); + } // removeDataStatusListener + + /** + * Add Data Status Listener + * @param l listener + */ + public synchronized void addDataStatusListener(DataStatusListener l) + { + listenerList.add(DataStatusListener.class, l); + } // addDataStatusListener + + /** + * Inform Listeners + * @param e event + */ + private void fireDataStatusChanged (DataStatusEvent e) + { + DataStatusListener[] listeners = listenerList.getListeners(DataStatusListener.class); + for (int i = 0; i < listeners.length; i++) + listeners[i].dataStatusChanged(e); + } // fireDataStatusChanged + + /** + * Create Data Status Event + * @return data status event + */ + private DataStatusEvent createDSE() + { + boolean changed = m_changed; + if (m_rowChanged != -1) + changed = true; + DataStatusEvent dse = new DataStatusEvent(this, m_rowCount, changed, + Env.isAutoCommit(m_ctx, m_WindowNo), m_inserting); + dse.AD_Table_ID = m_AD_Table_ID; + dse.Record_ID = null; + return dse; + } // createDSE + + /** + * Create and fire Data Status Info Event + * @param AD_Message message + * @param info additional info + */ + protected void fireDataStatusIEvent (String AD_Message, String info) + { + DataStatusEvent e = createDSE(); + e.setInfo(AD_Message, info, false,false); + fireDataStatusChanged (e); + } // fireDataStatusEvent + + /** + * Create and fire Data Status Error Event + * @param AD_Message message + * @param info info + * @param isError error + */ + protected void fireDataStatusEEvent (String AD_Message, String info, boolean isError) + { + // org.compiere.util.Trace.printStack(); + // + DataStatusEvent e = createDSE(); + e.setInfo(AD_Message, info, isError, !isError); + if (isError) + log.saveWarning(AD_Message, info); + fireDataStatusChanged (e); + } // fireDataStatusEvent + + /** + * Create and fire Data Status Event (from Error Log) + * @param errorLog error log info + */ + protected void fireDataStatusEEvent (ValueNamePair errorLog) + { + if (errorLog != null) + fireDataStatusEEvent (errorLog.getValue(), errorLog.getName(), true); + } // fireDataStatusEvent + + + /************************************************************************** + * Remove Vetoable change listener for row changes + * @param l listener + */ + public synchronized void removeVetoableChangeListener(VetoableChangeListener l) + { + m_vetoableChangeSupport.removeVetoableChangeListener(l); + } // removeVetoableChangeListener + + /** + * Add Vetoable change listener for row changes + * @param l listener + */ + public synchronized void addVetoableChangeListener(VetoableChangeListener l) + { + m_vetoableChangeSupport.addVetoableChangeListener(l); + } // addVetoableChangeListener + + /** + * Fire Vetoable change listener for row changes + * @param e event + * @throws PropertyVetoException + */ + protected void fireVetoableChange(PropertyChangeEvent e) throws java.beans.PropertyVetoException + { + m_vetoableChangeSupport.fireVetoableChange(e); + } // fireVetoableChange + + /** + * toString + * @return String representation + */ + public String toString() + { + return new StringBuffer("MTable[").append(m_tableName) + .append(",WindowNo=").append(m_WindowNo) + .append(",Tab=").append(m_TabNo).append("]").toString(); + } // toString + + + + /************************************************************************** + * ASync Loader + */ + class Loader extends Thread implements Serializable + { + /** + * Construct Loader + */ + public Loader() + { + super("TLoader"); + } // Loader + + private PreparedStatement m_pstmt = null; + private ResultSet m_rs = null; + + /** + * Open ResultSet + * @param maxRows maximum number of rows or 0 for all + * @return number of records + */ + protected int open (int maxRows) + { + // log.config( "MTable Loader.open"); + // Get Number of Rows + int rows = 0; + try + { + PreparedStatement pstmt = DB.prepareStatement(m_SQL_Count, null); + setParameter (pstmt, true); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + rows = rs.getInt(1); + rs.close(); + pstmt.close(); + } + catch (SQLException e0) + { + // Zoom Query may have invalid where clause + if (e0.getErrorCode() == 904) // ORA-00904: "C_x_ID": invalid identifier + log.warning("Count - " + e0.getLocalizedMessage() + "\nSQL=" + m_SQL_Count); + else + log.log(Level.SEVERE, "Count SQL=" + m_SQL_Count, e0); + return 0; + } + StringBuffer info = new StringBuffer("Rows="); + info.append(rows); + if (rows == 0) + info.append(" - ").append(m_SQL_Count); + + // open Statement (closed by Loader.close) + try + { + m_pstmt = DB.prepareStatement(m_SQL, null); + if (maxRows > 0 && rows > maxRows) + { + m_pstmt.setMaxRows(maxRows); + info.append(" - MaxRows=").append(maxRows); + rows = maxRows; + } + // m_pstmt.setFetchSize(20); + setParameter (m_pstmt, false); + m_rs = m_pstmt.executeQuery(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, m_SQL, e); + return 0; + } + log.fine(info.toString()); + return rows; + } // open + + /** + * Close RS and Statement + */ + private void close() + { + // log.config( "MTable Loader.close"); + try + { + if (m_rs != null) + m_rs.close(); + if (m_pstmt != null) + m_pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "closeRS", e); + } + m_rs = null; + m_pstmt = null; + } // close + + /** + * Fill Buffer to include Row + */ + public void run() + { + log.info(""); + if (m_rs == null) + return; + + try + { + while (m_rs.next()) + { + if (this.isInterrupted()) + { + log.fine("Interrupted"); + close(); + return; + } + // Get Data + Object[] rowData = readData(m_rs); + // add Data + MSort sort = new MSort(m_buffer.size(), null); // index + m_buffer.add(rowData); + m_sort.add(sort); + + // Statement all 250 rows & sleep + if (m_buffer.size() % 250 == 0) + { + // give the other processes a chance + try + { + yield(); + sleep(10); // .01 second + } + catch (InterruptedException ie) + { + log.fine("Interrupted while sleeping"); + close(); + return; + } + DataStatusEvent evt = createDSE(); + evt.setLoading(m_buffer.size()); + fireDataStatusChanged(evt); + } + } // while(rs.next()) + } + catch (SQLException e) + { + log.log(Level.SEVERE, "run", e); + } + close(); + fireDataStatusIEvent("", ""); + } // run + + /** + * Set Parameter for Query. + * elements must be Integer, BigDecimal, String (default) + * @param pstmt prepared statement + * @param countSQL count + */ + private void setParameter (PreparedStatement pstmt, boolean countSQL) + { + if (m_parameterSELECT.size() == 0 && m_parameterWHERE.size() == 0) + return; + try + { + int pos = 1; // position in Statement + // Select Clause Parameters + for (int i = 0; !countSQL && i < m_parameterSELECT.size(); i++) + { + Object para = m_parameterSELECT.get(i); + if (para != null) + log.fine("Select " + i + "=" + para); + // + if (para == null) + ; + else if (para instanceof Integer) + { + Integer ii = (Integer)para; + pstmt.setInt (pos++, ii.intValue()); + } + else if (para instanceof BigDecimal) + pstmt.setBigDecimal (pos++, (BigDecimal)para); + else + pstmt.setString(pos++, para.toString()); + } + // Where Clause Parameters + for (int i = 0; i < m_parameterWHERE.size(); i++) + { + Object para = m_parameterWHERE.get(i); + if (para != null) + log.fine("Where " + i + "=" + para); + // + if (para == null) + ; + else if (para instanceof Integer) + { + Integer ii = (Integer)para; + pstmt.setInt (pos++, ii.intValue()); + } + else if (para instanceof BigDecimal) + pstmt.setBigDecimal (pos++, (BigDecimal)para); + else + pstmt.setString(pos++, para.toString()); + } + } + catch (SQLException e) + { + log.log(Level.SEVERE, "parameter", e); + } + } // setParameter + + } // Loader + +} diff --git a/base/src/org/compiere/model/GridWindow.java b/base/src/org/compiere/model/GridWindow.java new file mode 100644 index 0000000000..59cea08695 --- /dev/null +++ b/base/src/org/compiere/model/GridWindow.java @@ -0,0 +1,512 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.awt.*; +import java.io.*; +import java.rmi.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import javax.swing.*; +import org.apache.ecs.xhtml.*; +import org.compiere.db.*; +import org.compiere.plaf.*; +import org.compiere.util.*; + +/** + * Window Model + * + * @author Jorg Janke + * @version $Id: GridWindow.java,v 1.4 2006/07/30 00:51:02 jjanke Exp $ + */ +public class GridWindow implements Serializable +{ + /** + * Get Grid Window + * @param ctx context + * @param WindowNo window no for ctx + * @param AD_Window_ID window id + * @return window or null if not found + */ + public static GridWindow get (Properties ctx, int WindowNo, int AD_Window_ID) + { + log.config("Window=" + WindowNo + ", AD_Window_ID=" + AD_Window_ID); + GridWindowVO mWindowVO = GridWindowVO.create (Env.getCtx(), WindowNo, AD_Window_ID); + if (mWindowVO == null) + return null; + return new GridWindow(mWindowVO); + } // get + + + /************************************************************************** + * Constructor + * @param vo value object + */ + public GridWindow (GridWindowVO vo) + { + m_vo = vo; + if (loadTabData()) + enableEvents(); + } // MWindow + + /** Value Object */ + private GridWindowVO m_vo; + /** Tabs */ + private ArrayList m_tabs = new ArrayList(); + /** Position */ + private Rectangle m_position = null; + /** Model last updated */ + private Timestamp m_modelUpdated = null; + + /** Logger */ + private static CLogger log = CLogger.getCLogger(GridWindow.class); + + /************************************************************************** + * Dispose + */ + public void dispose() + { + log.info("AD_Window_ID=" + m_vo.AD_Window_ID); + for (int i = 0; i < getTabCount(); i++) + getTab(i).dispose(); + m_tabs.clear(); + m_tabs = null; + } // dispose + + /** + * Load is complete. + * Return when async load is complete + * Used for performance tests (Base.test()) + */ + public void loadCompete () + { + // for all tabs + for (int i = 0; i < getTabCount(); i++) + getTab(i).getMTable().loadComplete(); + } // loadComplete + + /** + * Get Tab data and create MTab(s) + * @return true if tab loaded + */ + private boolean loadTabData() + { + log.config(""); + + if (m_vo.Tabs == null) + return false; + + for (int t = 0; t < m_vo.Tabs.size(); t++) + { + GridTabVO mTabVO = (GridTabVO)m_vo.Tabs.get(t); + if (mTabVO != null) + { + GridTab mTab = new GridTab(mTabVO); + Env.setContext(mTabVO.ctx, mTabVO.WindowNo, mTabVO.TabNo, + "KeyColumnName", mTab.getKeyColumnName()); + // Set Link Column + if (mTab.getLinkColumnName().length() == 0) + { + ArrayList parents = mTab.getParentColumnNames(); + // No Parent - no link + if (parents.size() == 0) + ; + // Standard case + else if (parents.size() == 1) + mTab.setLinkColumnName((String)parents.get(0)); + else + { + // More than one parent. + // Search prior tabs for the "right parent" + // for all previous tabs + for (int i = 0; i < m_tabs.size(); i++) + { + // we have a tab + GridTab tab = (GridTab)m_tabs.get(i); + String tabKey = tab.getKeyColumnName(); // may be "" + // look, if one of our parents is the key of that tab + for (int j = 0; j < parents.size(); j++) + { + String parent = (String)parents.get(j); + if (parent.equals(tabKey)) + { + mTab.setLinkColumnName(parent); + break; + } + // The tab could have more than one key, look into their parents + if (tabKey.equals("")) + for (int k = 0; k < tab.getParentColumnNames().size(); k++) + if (parent.equals(tab.getParentColumnNames().get(k))) + { + mTab.setLinkColumnName(parent); + break; + } + } // for all parents + } // for all previous tabs + } // parents.size > 1 + } // set Link column + mTab.setLinkColumnName(null); // overwrites, if AD_Column_ID exists + // + m_tabs.add(mTab); + } + } // for all tabs + return true; + } // loadTabData + + /** + * Get Window Icon + * @return Icon for Window + */ + public Image getImage() + { + if (m_vo.AD_Image_ID == 0) + return null; + // + MImage mImage = MImage.get(Env.getCtx(), m_vo.AD_Image_ID); + return mImage.getImage(); + } // getImage + + /** + * Get Window Icon + * @return Icon for Window + */ + public Icon getIcon() + { + if (m_vo.AD_Image_ID == 0) + return null; + // + MImage mImage = MImage.get(Env.getCtx(), m_vo.AD_Image_ID); + return mImage.getIcon(); + } // getIcon + + /** + * Get Color + * @return AdempiereColor or null + */ + public AdempiereColor getColor() + { + if (m_vo.AD_Color_ID == 0) + return null; + MColor mc = new MColor(m_vo.ctx, m_vo.AD_Color_ID, null); + return mc.getAdempiereColor(); + } // getColor + + /** + * SO Trx Window + * @return true if SO Trx + */ + public boolean isSOTrx() + { + return m_vo.IsSOTrx; + } // isSOTrx + + + /** + * Open and query first Tab (events should be enabled) and get first row. + */ + public void query() + { + log.info(""); + GridTab tab = getTab(0); + tab.query(false, 0, 0); + if (tab.getRowCount() > 0) + tab.navigate(0); + } // open + + /** + * Enable Events - enable data events of tabs (add listeners) + */ + private void enableEvents() + { + for (int i = 0; i < getTabCount(); i++) + getTab(i).enableEvents(); + } // enableEvents + + /** + * Get number of Tabs + * @return number of tabs + */ + public int getTabCount() + { + return m_tabs.size(); + } // getTabCount + + /** + * Get i-th MTab - null if not valid + * @param i index + * @return MTab + */ + public GridTab getTab (int i) + { + if (i < 0 || i+1 > m_tabs.size()) + return null; + return (GridTab)m_tabs.get(i); + } // getTab + + /** + * Get Window_ID + * @return AD_Window_ID + */ + public int getAD_Window_ID() + { + return m_vo.AD_Window_ID; + } // getAD_Window_ID + + /** + * Get WindowNo + * @return WindowNo + */ + public int getWindowNo() + { + return m_vo.WindowNo; + } // getWindowNo + + /** + * Get Name + * @return name + */ + public String getName() + { + return m_vo.Name; + } // getName + + /** + * Get Description + * @return Description + */ + public String getDescription() + { + return m_vo.Description; + } // getDescription + + /** + * Get Help + * @return Help + */ + public String getHelp() + { + return m_vo.Help; + } // getHelp + + /** + * Get Window Type + * @return Window Type see WindowType_* + */ + public String getWindowType() + { + return m_vo.WindowType; + } // getWindowType + + /** + * Is Transaction Window + * @return true if transaction + */ + public boolean isTransaction() + { + return m_vo.WindowType.equals(GridWindowVO.WINDOWTYPE_TRX); + } // isTransaction + + /** + * Get Window Size + * @return window size or null if not set + */ + public Dimension getWindowSize() + { + if (m_vo.WinWidth != 0 && m_vo.WinHeight != 0) + return new Dimension (m_vo.WinWidth, m_vo.WinHeight); + return null; + } // getWindowSize + + /** + * To String + * @return String representation + */ + public String toString() + { + return "MWindow[" + m_vo.WindowNo + "," + m_vo.Name + " (" + m_vo.AD_Window_ID + ")]"; + } // toString + + /** + * Get Help HTML Document + * @param javaClient true if java client false for browser + * @return help + */ + public WebDoc getHelpDoc (boolean javaClient) + { + String title = Msg.getMsg(Env.getCtx(), "Window") + ": " + getName(); + WebDoc doc = null; + if (javaClient) + { + doc = WebDoc.create (false, title, javaClient); + } + else // HTML + { + doc = WebDoc.createPopup (title); + doc.addPopupClose(); + } + + // body.addElement("© Adempiere   "); + // body.addElement(new a("http://www.adempiere.org/help/", "Online Help")); + td center = doc.addPopupCenter(false); + // Window + if (getDescription().length() != 0) + center.addElement(new p().addElement(new i(getDescription()))); + if (getHelp().length() != 0) + center.addElement(new p().addElement(getHelp())); + + // Links to Tabs + int size = getTabCount(); + p p = new p(); + for (int i = 0; i < size; i++) + { + GridTab tab = getTab(i); + if (i > 0) + p.addElement(" - "); + p.addElement(new a("#Tab"+i).addElement(tab.getName())); + } + center.addElement(p) + .addElement(new p().addElement(WebDoc.NBSP)); + + // For all Tabs + for (int i = 0; i < size; i++) + { + table table = new table("1", "5", "5", "100%", null); + GridTab tab = getTab(i); + tr tr = new tr() + .addElement(new th() + .addElement(new a().setName("Tab" + i) + .addElement(new h2(Msg.getMsg(Env.getCtx(), "Tab") + ": " + tab.getName())))); + if (tab.getDescription().length() != 0) + tr.addElement(new th() + .addElement(new i(tab.getDescription()))); + else + tr.addElement(new th() + .addElement(WebDoc.NBSP)); + table.addElement(tr); + // Desciption + td td = new td().setColSpan(2); + if (tab.getHelp().length() != 0) + td.addElement(new p().addElement(tab.getHelp())); + // Links to Fields + p = new p(); + for (int j = 0; j < tab.getFieldCount(); j++) + { + GridField field = tab.getField(j); + String hdr = field.getHeader(); + if (hdr != null && hdr.length() > 0) + { + if (j > 0) + p.addElement(" - "); + p.addElement(new a("#Field" + i + j, hdr)); + } + } + td.addElement(p); + table.addElement(new tr().addElement(td)); + + // For all Fields + for (int j = 0; j < tab.getFieldCount(); j++) + { + GridField field = tab.getField(j); + String hdr = field.getHeader(); + if (hdr != null && hdr.length() > 0) + { + td = new td().setColSpan(2) + .addElement(new a().setName("Field" + i + j) + .addElement(new h3(Msg.getMsg(Env.getCtx(), "Field") + ": " + hdr)) + ); + if (field.getDescription().length() != 0) + td.addElement(new i(field.getDescription())); + // + if (field.getHelp().length() != 0) + td.addElement(new p().addElement(field.getHelp())); + table.addElement(new tr().addElement(td)); + } + } // for all Fields + + center.addElement(table); + center.addElement(new p().addElement(WebDoc.NBSP)); + } // for all Tabs + + if (!javaClient) + doc.addPopupClose(); + // System.out.println(doc.toString()); + return doc; + } // getHelpDoc + + /** + * Get Model last Updated + * @param recalc recalculate again + * @return date + */ + public Timestamp getModelUpdated (boolean recalc) + { + if (recalc || m_modelUpdated == null) + { + String sql = "SELECT MAX(w.Updated), MAX(t.Updated), MAX(tt.Updated), MAX(f.Updated), MAX(c.Updated) " + + "FROM AD_Window w" + + " INNER JOIN AD_Tab t ON (w.AD_Window_ID=t.AD_Window_ID)" + + " INNER JOIN AD_Table tt ON (t.AD_Table_ID=tt.AD_Table_ID)" + + " INNER JOIN AD_Field f ON (t.AD_Tab_ID=f.AD_Tab_ID)" + + " INNER JOIN AD_Column c ON (f.AD_Column_ID=c.AD_Column_ID) " + + "WHERE w.AD_Window_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getAD_Window_ID()); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + m_modelUpdated = rs.getTimestamp(1); // Window + Timestamp ts = rs.getTimestamp(2); // Tab + if (ts.after(m_modelUpdated)) + m_modelUpdated = ts; + ts = rs.getTimestamp(3); // Table + if (ts.after(m_modelUpdated)) + m_modelUpdated = ts; + ts = rs.getTimestamp(4); // Field + if (ts.after(m_modelUpdated)) + m_modelUpdated = ts; + ts = rs.getTimestamp(5); // Column + if (ts.after(m_modelUpdated)) + m_modelUpdated = ts; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + } + return m_modelUpdated; + } // getModelUpdated + + +} // MWindow diff --git a/base/src/org/compiere/model/GridWorkbench.java b/base/src/org/compiere/model/GridWorkbench.java new file mode 100644 index 0000000000..247172c724 --- /dev/null +++ b/base/src/org/compiere/model/GridWorkbench.java @@ -0,0 +1,526 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.awt.*; +import java.io.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import javax.swing.*; +import org.compiere.util.*; + +/** + * Window Workbench Model + * + * @author Jorg Janke + * @version $Id: GridWorkbench.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class GridWorkbench implements Serializable +{ + /** + * Workbench Model Constructor + * @param ctx context + */ + public GridWorkbench (Properties ctx) + { + m_ctx = ctx; + } // MWorkbench + + /** + * No Workbench - Just Frame for Window + * @param ctx context + * @param AD_Window_ID window + */ + public GridWorkbench (Properties ctx, int AD_Window_ID) + { + m_ctx = ctx; + m_windows.add (new WBWindow(TYPE_WINDOW, AD_Window_ID)); + } // MWorkbench + + /** Properties */ + private Properties m_ctx; + + /** List of windows */ + private ArrayList m_windows = new ArrayList(); + + private int AD_Workbench_ID = 0; + private String Name = ""; + private String Description = ""; + private String Help = ""; + private int AD_Column_ID = 0; + private int AD_Image_ID = 0; + private int AD_Color_ID = 0; + private int PA_Goal_ID = 0; + private String ColumnName = ""; + + /** Logger */ + private static CLogger log = CLogger.getCLogger(GridWorkbench.class); + + /** + * Init Workbench + * @param ad_Workbench_ID workbench + * @return true if initialized + */ + public boolean initWorkbench (int ad_Workbench_ID) + { + AD_Workbench_ID = ad_Workbench_ID; + // Get WB info + String sql = null; + if (Env.isBaseLanguage(m_ctx, "AD_Workbench")) + sql = "SELECT w.Name,w.Description,w.Help," // 1..3 + + " w.AD_Column_ID,w.AD_Image_ID,w.AD_Color_ID,w.PA_Goal_ID," // 4..7 + + " c.ColumnName " // 8 + + "FROM AD_Workbench w, AD_Column c " + + "WHERE w.AD_Workbench_ID=?" // #1 + + " AND w.IsActive='Y'" + + " AND w.AD_Column_ID=c.AD_Column_ID"; + else + sql = "SELECT t.Name,t.Description,t.Help," + + " w.AD_Column_ID,w.AD_Image_ID,w.AD_Color_ID,w.PA_Goal_ID," + + " c.ColumnName " + + "FROM AD_Workbench w, AD_Workbench_Trl t, AD_Column c " + + "WHERE w.AD_Workbench_ID=?" // #1 + + " AND w.IsActive='Y'" + + " AND w.AD_Workbench_ID=t.AD_Workbench_ID" + + " AND t.AD_Language='" + Env.getAD_Language(m_ctx) + "'" + + " AND w.AD_Column_ID=c.AD_Column_ID"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Workbench_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + Name = rs.getString(1); + Description = rs.getString(2); + if (Description == null) + Description = ""; + Help = rs.getString(3); + if (Help == null) + Help = ""; + // + AD_Column_ID = rs.getInt(4); + AD_Image_ID = rs.getInt(5); + AD_Color_ID = rs.getInt(6); + PA_Goal_ID = rs.getInt(7); + ColumnName = rs.getString(8); + } + else + AD_Workbench_ID = 0; + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + + if (AD_Workbench_ID == 0) + return false; + return initWorkbenchWindows(); + } // initWorkbench + + /** + * String Representation + * @return info + */ + public String toString() + { + return "MWorkbench ID=" + AD_Workbench_ID + " " + Name + + ", windows=" + m_windows.size() + ", LinkColumn=" + ColumnName; + } // toString + + /** + * Dispose + */ + public void dispose() + { + for (int i = 0; i < m_windows.size(); i++) + { + dispose(i); + } + m_windows.clear(); + m_windows = null; + } // dispose + + /** + * Get Workbench Query. + * @return ColumnName=@#ColumnName@ + */ + public MQuery getQuery() + { + return MQuery.getEqualQuery(ColumnName, "@#" + ColumnName + "@"); + } // getQuery + + /*************************************************************************/ + + /** + * Get Workbench + * @return workbensch id + */ + public int getAD_Workbench_ID() + { + return AD_Workbench_ID; + } + /** + * Get Name + * @return name + */ + public String getName() + { + return Name; + } + /** + * Get Description + * @return description + */ + public String getDescription() + { + return Description; + } + /** + * Get Help + * @return help + */ + public String getHelp() + { + return Help; + } + /** + * Get Link AD_Column_ID + * @return column + */ + public int getAD_Column_ID() + { + return AD_Column_ID; + } + /** + * Get AD_Image_ID + * @return image + */ + public int getAD_Image_ID() + { + return AD_Image_ID; + } + /** + * Get AD_Color_ID + * @return color + */ + public int getAD_Color_ID() + { + return AD_Color_ID; + } + /** + * Get PA_Goal_ID + * @return goal + */ + public int getPA_Goal_ID() + { + return PA_Goal_ID; + } + + /*************************************************************************/ + + /** Window */ + public static final int TYPE_WINDOW = 1; + /** Form */ + public static final int TYPE_FORM = 2; + /** Process */ + public static final int TYPE_PROCESS = 3; + /** Task */ + public static final int TYPE_TASK = 4; + + /** + * Init Workbench Windows + * @return true if init ok + */ + private boolean initWorkbenchWindows() + { + String sql = "SELECT AD_Window_ID, AD_Form_ID, AD_Process_ID, AD_Task_ID " + + "FROM AD_WorkbenchWindow " + + "WHERE AD_Workbench_ID=? AND IsActive='Y'" + + "ORDER BY SeqNo"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Workbench_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + int AD_Window_ID = rs.getInt(1); + int AD_Form_ID = rs.getInt(2); + int AD_Process_ID = rs.getInt(3); + int AD_Task_ID = rs.getInt(4); + // + if (AD_Window_ID > 0) + m_windows.add (new WBWindow(TYPE_WINDOW, AD_Window_ID)); + else if (AD_Form_ID > 0) + m_windows.add (new WBWindow(TYPE_FORM, AD_Form_ID)); + else if (AD_Process_ID > 0) + m_windows.add (new WBWindow(TYPE_PROCESS, AD_Process_ID)); + else if (AD_Task_ID > 0) + m_windows.add (new WBWindow(TYPE_TASK, AD_Task_ID)); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + return false; + } + return true; + } // initWorkbenchWindows + + /** + * Get Window Count + * @return window count + */ + public int getWindowCount() + { + return m_windows.size(); + } // getWindowCount + + /** + * Get Window Type of Window + * @param index index in workbench + * @return -1 if not valid + */ + public int getWindowType (int index) + { + if (index < 0 || index > m_windows.size()) + return -1; + WBWindow win = (WBWindow)m_windows.get(index); + return win.Type; + } // getWindowType + + /** + * Get ID for Window + * @param index index in workbench + * @return -1 if not valid + */ + public int getWindowID (int index) + { + if (index < 0 || index > m_windows.size()) + return -1; + WBWindow win = (WBWindow)m_windows.get(index); + return win.ID; + } // getWindowID + + + /************************************************************************** + * Set Window Model of Window + * @param index index in workbench + * @param mw model window + */ + public void setMWindow (int index, GridWindow mw) + { + if (index < 0 || index > m_windows.size()) + throw new IllegalArgumentException ("Index invalid: " + index); + WBWindow win = (WBWindow)m_windows.get(index); + if (win.Type != TYPE_WINDOW) + throw new IllegalArgumentException ("Not a MWindow: " + index); + win.mWindow = mw; + } // setMWindow + + /** + * Get Window Model of Window + * @param index index in workbench + * @return model window + */ + public GridWindow getMWindow (int index) + { + if (index < 0 || index > m_windows.size()) + throw new IllegalArgumentException ("Index invalid: " + index); + WBWindow win = (WBWindow)m_windows.get(index); + if (win.Type != TYPE_WINDOW) + throw new IllegalArgumentException ("Not a MWindow: " + index); + return win.mWindow; + } // getMWindow + + /** + * Get Name of Window + * @param index index in workbench + * @return Window Name or null if not set + */ + public String getName (int index) + { + if (index < 0 || index > m_windows.size()) + throw new IllegalArgumentException ("Index invalid: " + index); + WBWindow win = (WBWindow)m_windows.get(index); + if (win.mWindow != null && win.Type == TYPE_WINDOW) + return win.mWindow.getName(); + return null; + } // getName + + /** + * Get Description of Window + * @param index index in workbench + * @return Window Description or null if not set + */ + public String getDescription (int index) + { + if (index < 0 || index > m_windows.size()) + throw new IllegalArgumentException ("Index invalid: " + index); + WBWindow win = (WBWindow)m_windows.get(index); + if (win.mWindow != null && win.Type == TYPE_WINDOW) + return win.mWindow.getDescription(); + return null; + } // getDescription + + /** + * Get Help of Window + * @param index index in workbench + * @return Window Help or null if not set + */ + public String getHelp (int index) + { + if (index < 0 || index > m_windows.size()) + throw new IllegalArgumentException ("Index invalid: " + index); + WBWindow win = (WBWindow)m_windows.get(index); + if (win.mWindow != null && win.Type == TYPE_WINDOW) + return win.mWindow.getHelp(); + return null; + } // getHelp + + /** + * Get Icon of Window + * @param index index in workbench + * @return Window Icon or null if not set + */ + public Icon getIcon (int index) + { + if (index < 0 || index > m_windows.size()) + throw new IllegalArgumentException ("Index invalid: " + index); + WBWindow win = (WBWindow)m_windows.get(index); + if (win.mWindow != null && win.Type == TYPE_WINDOW) + return win.mWindow.getIcon(); + return null; + } // getIcon + + /** + * Get Image Icon of Window + * @param index index in workbench + * @return Window Icon or null if not set + */ + public Image getImage (int index) + { + if (index < 0 || index > m_windows.size()) + throw new IllegalArgumentException ("Index invalid: " + index); + WBWindow win = (WBWindow)m_windows.get(index); + if (win.mWindow != null && win.Type == TYPE_WINDOW) + return win.mWindow.getImage(); + return null; + } // getImage + + /** + * Get AD_Color_ID of Window + * @param index index in workbench + * @return Window Color or Workbench color if not set + */ + public int getAD_Color_ID (int index) + { + if (index < 0 || index > m_windows.size()) + throw new IllegalArgumentException ("Index invalid: " + index); + WBWindow win = (WBWindow)m_windows.get(index); + int retValue = -1; + // if (win.mWindow != null && win.Type == TYPE_WINDOW) + // return win.mWindow.getAD_Color_ID(); + if (retValue == -1) + return getAD_Color_ID(); + return retValue; + } // getAD_Color_ID + + /** + * Set WindowNo of Window + * @param index index in workbench + * @param windowNo window no + */ + public void setWindowNo (int index, int windowNo) + { + if (index < 0 || index > m_windows.size()) + throw new IllegalArgumentException ("Index invalid: " + index); + WBWindow win = (WBWindow)m_windows.get(index); + win.WindowNo = windowNo; + } // getWindowNo + + /** + * Get WindowNo of Window + * @param index index in workbench + * @return WindowNo of Window if previously set, otherwise -1; + */ + public int getWindowNo (int index) + { + if (index < 0 || index > m_windows.size()) + throw new IllegalArgumentException ("Index invalid: " + index); + WBWindow win = (WBWindow)m_windows.get(index); + return win.WindowNo; + } // getWindowNo + + /** + * Dispose of Window + * @param index index in workbench + */ + public void dispose (int index) + { + if (index < 0 || index > m_windows.size()) + throw new IllegalArgumentException ("Index invalid: " + index); + WBWindow win = (WBWindow)m_windows.get(index); + if (win.mWindow != null) + win.mWindow.dispose(); + win.mWindow = null; + } // dispose + + /** + * Get Window Size + * @return window size or null if not set + */ + public Dimension getWindowSize() + { + return null; + } // getWindowSize + + + /************************************************************************** + * Window Type + */ + class WBWindow + { + /** + * WBWindow + * @param type + * @param id + */ + public WBWindow (int type, int id) + { + Type = type; + ID = id; + } + /** Type */ + public int Type = 0; + /** ID */ + public int ID = 0; + /** Window No */ + public int WindowNo = -1; + /** Window Midel */ + public GridWindow mWindow = null; + // public MFrame mFrame = null; + // public MProcess mProcess = null; + } // WBWindow + +} // Workbench diff --git a/base/src/org/compiere/model/MAccessProfile.java b/base/src/org/compiere/model/MAccessProfile.java new file mode 100644 index 0000000000..98551a636e --- /dev/null +++ b/base/src/org/compiere/model/MAccessProfile.java @@ -0,0 +1,83 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Media Access Profile + * + * @author Jorg Janke + * @version $Id: MAccessProfile.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MAccessProfile extends X_CM_AccessProfile +{ + /** + * Access to Container + * @param ctx context + * @param CM_Container_ID + * @param AD_User_ID user to check + * @return true if access to container + */ + public static boolean isAccessContainer (Properties ctx, int CM_Container_ID, + int AD_User_ID) + { + // NIT + return true; + } // isAccessContainer + + /** + * Access to Container + * @param ctx context + * @param CM_Container_ID + * @param AD_Role_ID 0 or role to checl + * @param C_BPGroup_ID 0 or bpartner to check + * @return true if access to container + */ + public static boolean isAccessContainer (Properties ctx, int CM_Container_ID, + int AD_Role_ID, int C_BPGroup_ID) + { + // NIT + return true; + } // isAccessContainer + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param CM_AccessProfile_ID id + * @param trxName transaction + */ + public MAccessProfile (Properties ctx, int CM_AccessProfile_ID, + String trxName) + { + super (ctx, CM_AccessProfile_ID, trxName); + } // MAccessProfile + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MAccessProfile (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MAccessProfile + + +} // MAccessProfile diff --git a/base/src/org/compiere/model/MAcctProcessor.java b/base/src/org/compiere/model/MAcctProcessor.java new file mode 100644 index 0000000000..ae84146400 --- /dev/null +++ b/base/src/org/compiere/model/MAcctProcessor.java @@ -0,0 +1,201 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Accounting Processor Model + * + * @author Jorg Janke + * @version $Id: MAcctProcessor.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MAcctProcessor extends X_C_AcctProcessor + implements AdempiereProcessor +{ + /** + * Get Active + * @param ctx context + * @return active processors + */ + public static MAcctProcessor[] getActive (Properties ctx) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_AcctProcessor WHERE IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MAcctProcessor (ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "getActive", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MAcctProcessor[] retValue = new MAcctProcessor[list.size ()]; + list.toArray (retValue); + return retValue; + } // getActive + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MAcctProcessor.class); + + + /** + * Standard Construvtor + * @param ctx context + * @param C_AcctProcessor_ID id + * @param trxName transaction + */ + public MAcctProcessor (Properties ctx, int C_AcctProcessor_ID, String trxName) + { + super (ctx, C_AcctProcessor_ID, trxName); + if (C_AcctProcessor_ID == 0) + { + // setName (null); + // setSupervisor_ID (0); + setFrequencyType (FREQUENCYTYPE_Hour); + setFrequency (1); + setKeepLogDays (7); // 7 + } + } // MAcctProcessor + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MAcctProcessor (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAcctProcessor + + /** + * Parent Constructor + * @param client parent + * @param Supervisor_ID admin + */ + public MAcctProcessor (MClient client, int Supervisor_ID) + { + this (client.getCtx(), 0, client.get_TrxName()); + setClientOrg(client); + setName (client.getName() + " - " + + Msg.translate(getCtx(), "C_AcctProcessor_ID")); + setSupervisor_ID (Supervisor_ID); + } // MAcctProcessor + + + + /** + * Get Server ID + * @return id + */ + public String getServerID () + { + return "AcctProcessor" + get_ID(); + } // getServerID + + /** + * Get Date Next Run + * @param requery requery + * @return date next run + */ + public Timestamp getDateNextRun (boolean requery) + { + if (requery) + load(get_TrxName()); + return getDateNextRun(); + } // getDateNextRun + + /** + * Get Logs + * @return logs + */ + public AdempiereProcessorLog[] getLogs () + { + ArrayList list = new ArrayList(); + String sql = "SELECT * " + + "FROM C_AcctProcessorLog " + + "WHERE C_AcctProcessor_ID=? " + + "ORDER BY Created DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_AcctProcessor_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MAcctProcessorLog (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MAcctProcessorLog[] retValue = new MAcctProcessorLog[list.size ()]; + list.toArray (retValue); + return retValue; + } // getLogs + + /** + * Delete old Request Log + * @return number of records + */ + public int deleteLog() + { + if (getKeepLogDays() < 1) + return 0; + String sql = "DELETE C_AcctProcessorLog " + + "WHERE C_AcctProcessor_ID=" + getC_AcctProcessor_ID() + + " AND (Created+" + getKeepLogDays() + ") < SysDate"; + int no = DB.executeUpdate(sql, get_TrxName()); + return 0; + } // deleteLog + +} // MAcctProcessor diff --git a/base/src/org/compiere/model/MAcctProcessorLog.java b/base/src/org/compiere/model/MAcctProcessorLog.java new file mode 100644 index 0000000000..c2b5cc0843 --- /dev/null +++ b/base/src/org/compiere/model/MAcctProcessorLog.java @@ -0,0 +1,68 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Accounting Processor Log + * + * @author Jorg Janke + * @version $Id: MAcctProcessorLog.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MAcctProcessorLog extends X_C_AcctProcessorLog + implements AdempiereProcessorLog +{ + + /** + * Standard Constructor + * @param ctx context + * @param C_AcctProcessorLog_ID id + * @param trxName transaction + */ + public MAcctProcessorLog (Properties ctx, int C_AcctProcessorLog_ID, String trxName) + { + super (ctx, C_AcctProcessorLog_ID, trxName); + } // MAcctProcessorLog + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MAcctProcessorLog (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAcctProcessorLog + + /** + * Parent Constructor + * @param parent parent + * @param summary summary + */ + public MAcctProcessorLog (MAcctProcessor parent, String summary) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setC_AcctProcessor_ID(parent.getC_AcctProcessor_ID()); + setSummary(summary); + } // MAcctProcessorLog + +} // MAcctProcessorLog diff --git a/base/src/org/compiere/model/MAchievement.java b/base/src/org/compiere/model/MAchievement.java new file mode 100644 index 0000000000..ccb1533b92 --- /dev/null +++ b/base/src/org/compiere/model/MAchievement.java @@ -0,0 +1,174 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Performance Achievement + * + * @author Jorg Janke + * @version $Id: MAchievement.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MAchievement extends X_PA_Achievement +{ + /** + * Get achieved Achievements Of Measure + * @param measure Measure + * @return array of Achievements + */ + public static MAchievement[] get (MMeasure measure) + { + return getOfMeasure(measure.getCtx(), measure.getPA_Measure_ID()); + } // get + + /** + * Get achieved Achievements Of Measure + * @param ctx context + * @param PA_Measure_ID measure id + * @return array of Achievements + */ + public static MAchievement[] getOfMeasure (Properties ctx, int PA_Measure_ID) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM PA_Achievement " + + "WHERE PA_Measure_ID=? AND IsAchieved='Y' ORDER BY SeqNo, DateDoc"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, PA_Measure_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MAchievement (ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + MAchievement[] retValue = new MAchievement[list.size ()]; + list.toArray (retValue); + return retValue; + } // getOfMeasure + + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MAchievement.class); + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param PA_Achievement_ID id + * @param trxName trx + */ + public MAchievement (Properties ctx, int PA_Achievement_ID, String trxName) + { + super (ctx, PA_Achievement_ID, trxName); + } // MAchievement + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MAchievement (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MAchievement + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MAchievement["); + sb.append (get_ID()).append ("-").append (getName()).append ("]"); + return sb.toString (); + } // toString + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (isAchieved()) + { + if (getManualActual().signum() == 0) + setManualActual(Env.ONE); + if (getDateDoc() == null) + setDateDoc(new Timestamp(System.currentTimeMillis())); + } + return true; + } // beforeSave + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (success) + updateAchievementGoals(); + return success; + } // afterSave + + /** + * After Delete + * @param success success + * @return success + */ + protected boolean afterDelete (boolean success) + { + if (success) + updateAchievementGoals(); + return success; + } // afterDelete + + /** + * Update Goals with Achievement + */ + private void updateAchievementGoals() + { + MMeasure measure = MMeasure.get (getCtx(), getPA_Measure_ID()); + measure.updateGoals(); + } // updateAchievementGoals + +} // MAchievement diff --git a/base/src/org/compiere/model/MActivity.java b/base/src/org/compiere/model/MActivity.java new file mode 100644 index 0000000000..82f4907915 --- /dev/null +++ b/base/src/org/compiere/model/MActivity.java @@ -0,0 +1,87 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Activity Model + * + * @author Jorg Janke + * @version $Id: MActivity.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MActivity extends X_C_Activity +{ + + /** + * Standard Constructor + * @param ctx context + * @param C_Activity_ID id + * @param trxName transaction + */ + public MActivity (Properties ctx, int C_Activity_ID, String trxName) + { + super (ctx, C_Activity_ID, trxName); + } // MActivity + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MActivity (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MActivity + + + /** + * After Save. + * Insert + * - create tree + * @param newRecord insert + * @param success save success + * @return true if saved + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + if (newRecord) + insert_Tree(MTree_Base.TREETYPE_Activity); + // Value/Name change + if (!newRecord && (is_ValueChanged("Value") || is_ValueChanged("Name"))) + MAccount.updateValueDescription(getCtx(), "C_Activity_ID=" + getC_Activity_ID(), get_TrxName()); + return true; + } // afterSave + + /** + * After Delete + * @param success + * @return deleted + */ + protected boolean afterDelete (boolean success) + { + if (success) + delete_Tree(MTree_Base.TREETYPE_Activity); + return success; + } // afterDelete + +} // MActivity diff --git a/base/src/org/compiere/model/MAd.java b/base/src/org/compiere/model/MAd.java new file mode 100644 index 0000000000..a3aadbd1c4 --- /dev/null +++ b/base/src/org/compiere/model/MAd.java @@ -0,0 +1,96 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.util.*; +import javax.servlet.http.*; + +/** + * Container Model + * + * @author Yves Sandfort + * @version $Id$ + */ +@SuppressWarnings("serial") +public class MAd extends X_CM_Ad +{ + + /** + * Standard constructor for AD + * @param ctx Context + * @param CM_Ad_ID ID + * @param trxName Transaction + */ + public MAd (Properties ctx, int CM_Ad_ID, String trxName) + { + super (ctx, CM_Ad_ID, trxName); + } + + /** + * Get's the relevant current Impression value which is Actual+Start + * @return int + */ + public int getCurrentImpression() { + return getActualImpression() + getStartImpression(); + } + + /** + * Adds an Impression to the current Ad + * We will deactivate the Ad as soon as one of the Max Criterias are fullfiled + */ + public void addImpression() { + setActualImpression(getActualImpression()+1); + if (getCurrentImpression()>=getMaxImpression()) + setIsActive(false); + save(); + } + + /** + * Get Next of this Category, this Procedure will return the next Ad in a category and expire it if needed + * @param ctx Context + * @param CM_Ad_Cat_ID Category + * @param trxName Transaction + * @return MAd + */ + public static MAd getNext(Properties ctx, int CM_Ad_Cat_ID, String trxName) { + MAd thisAd = null; + int [] thisAds = MAd.getAllIDs("CM_Ad","ActualImpression+StartImpression= -7) + setDue0_7 (getDue0_7().add(amt)); + + if (daysDue >= -30) + setDue0_30 (getDue0_30().add(amt)); + + if (daysDue <= -1 && daysDue >= -7) + setDue1_7 (getDue1_7().add(amt)); + + if (daysDue <= -8 && daysDue >= -30) + setDue8_30 (getDue8_30().add(amt)); + + if (daysDue <= -31 && daysDue >= -60) + setDue31_60 (getDue31_60().add(amt)); + + if (daysDue <= -31) + setDue31_Plus (getDue31_Plus().add(amt)); + + if (daysDue <= -61 && daysDue >= -90) + setDue61_90 (getDue61_90().add(amt)); + + if (daysDue <= -61) + setDue61_Plus (getDue61_Plus().add(amt)); + + if (daysDue <= -91) + setDue91_Plus (getDue91_Plus().add(amt)); + } + else // Due = positive (> 1) + { + setPastDueAmt (getPastDueAmt().add(amt)); + if (daysDue <= 7) + setPastDue1_7 (getPastDue1_7().add(amt)); + + if (daysDue <= 30) + setPastDue1_30 (getPastDue1_30().add(amt)); + + if (daysDue >= 8 && daysDue <= 30) + setPastDue8_30 (getPastDue8_30().add(amt)); + + if (daysDue >= 31 && daysDue <= 60) + setPastDue31_60 (getPastDue31_60().add(amt)); + + if (daysDue >= 31) + setPastDue31_Plus (getPastDue31_Plus().add(amt)); + + if (daysDue >= 61 && daysDue <= 90) + setPastDue61_90 (getPastDue61_90().add(amt)); + + if (daysDue >= 61) + setPastDue61_Plus (getPastDue61_Plus().add(amt)); + + if (daysDue >= 91) + setPastDue91_Plus (getPastDue91_Plus().add(amt)); + } + } // add + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("MAging["); + sb.append("AD_PInstance_ID=").append(getAD_PInstance_ID()) + .append(",C_BPartner_ID=").append(getC_BPartner_ID()) + .append(",C_Currency_ID=").append(getC_Currency_ID()) + .append(",C_Invoice_ID=").append(getC_Invoice_ID()); + sb.append("]"); + return sb.toString(); + } // toString + +} // MAging diff --git a/base/src/org/compiere/model/MAlert.java b/base/src/org/compiere/model/MAlert.java new file mode 100644 index 0000000000..47d0237373 --- /dev/null +++ b/base/src/org/compiere/model/MAlert.java @@ -0,0 +1,226 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Alert Model + * + * @author Jorg Janke + * @version $Id: MAlert.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MAlert extends X_AD_Alert +{ + /** + * Standard Constructor + * @param ctx context + * @param AD_Alert_ID id + * @param trxName transaction + */ + public MAlert (Properties ctx, int AD_Alert_ID, String trxName) + { + super (ctx, AD_Alert_ID, trxName); + if (AD_Alert_ID == 0) + { + // setAD_AlertProcessor_ID (0); + // setName (null); + // setAlertMessage (null); + // setAlertSubject (null); + setEnforceClientSecurity (true); // Y + setEnforceRoleSecurity (true); // Y + setIsValid (true); // Y + } + } // MAlert + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MAlert (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAlert + + + /** The Rules */ + private MAlertRule[] m_rules = null; + /** The Recipients */ + private MAlertRecipient[] m_recipients = null; + + /** + * Get Rules + * @param reload reload data + * @return array of rules + */ + public MAlertRule[] getRules (boolean reload) + { + if (m_rules != null && !reload) + return m_rules; + String sql = "SELECT * FROM AD_AlertRule " + + "WHERE AD_Alert_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getAD_Alert_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MAlertRule (getCtx(), rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + m_rules = new MAlertRule[list.size ()]; + list.toArray (m_rules); + return m_rules; + } // getRules + + /** + * Get Recipients + * @param reload reload data + * @return array of recipients + */ + public MAlertRecipient[] getRecipients (boolean reload) + { + if (m_recipients != null && !reload) + return m_recipients; + String sql = "SELECT * FROM AD_AlertRecipient " + + "WHERE AD_Alert_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getAD_Alert_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MAlertRecipient (getCtx(), rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + m_recipients = new MAlertRecipient[list.size ()]; + list.toArray (m_recipients); + return m_recipients; + } // getRecipients + + /** + * Get First Role if exist + * @return AD_Role_ID or -1 + */ + public int getFirstAD_Role_ID() + { + getRecipients(false); + for (int i = 0; i < m_recipients.length; i++) + { + if (m_recipients[i].getAD_Role_ID() != -1) + return m_recipients[i].getAD_Role_ID(); + } + return -1; + } // getForstAD_Role_ID + + /** + * Get First User Role if exist + * @return AD_Role_ID or -1 + */ + public int getFirstUserAD_Role_ID() + { + getRecipients(false); + int AD_User_ID = getFirstAD_User_ID(); + if (AD_User_ID != -1) + { + MUserRoles[] urs = MUserRoles.getOfUser(getCtx(), AD_User_ID); + for (int i = 0; i < urs.length; i++) + { + if (urs[i].isActive()) + return urs[i].getAD_Role_ID(); + } + } + return -1; + } // getFirstUserAD_Role_ID + + /** + * Get First User if exist + * @return AD_User_ID or -1 + */ + public int getFirstAD_User_ID() + { + getRecipients(false); + for (int i = 0; i < m_recipients.length; i++) + { + if (m_recipients[i].getAD_User_ID() != -1) + return m_recipients[i].getAD_User_ID(); + } + return -1; + } // getFirstAD_User_ID + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MAlert["); + sb.append(get_ID()) + .append("-").append(getName()) + .append(",Valid=").append(isValid()); + if (m_rules != null) + sb.append(",Rules=").append(m_rules.length); + if (m_recipients != null) + sb.append(",Recipients=").append(m_recipients.length); + sb.append ("]"); + return sb.toString (); + } // toString + +} // MAlert diff --git a/base/src/org/compiere/model/MAlertProcessor.java b/base/src/org/compiere/model/MAlertProcessor.java new file mode 100644 index 0000000000..60589d1da8 --- /dev/null +++ b/base/src/org/compiere/model/MAlertProcessor.java @@ -0,0 +1,225 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Alert Processor + * + * @author Jorg Janke + * @version $Id: MAlertProcessor.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MAlertProcessor extends X_AD_AlertProcessor + implements AdempiereProcessor +{ + /** + * Get Active + * @param ctx context + * @return active processors + */ + public static MAlertProcessor[] getActive (Properties ctx) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM AD_AlertProcessor WHERE IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MAlertProcessor (ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MAlertProcessor[] retValue = new MAlertProcessor[list.size ()]; + list.toArray (retValue); + return retValue; + } // getActive + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MAlertProcessor.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param AD_AlertProcessorLog_ID id + * @param trxName transaction + */ + public MAlertProcessor (Properties ctx, int AD_AlertProcessorLog_ID, String trxName) + { + super (ctx, AD_AlertProcessorLog_ID, trxName); + } // MAlertProcessor + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MAlertProcessor (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAlertProcessor + + /** The Alerts */ + private MAlert[] m_alerts = null; + + /** + * Get Server ID + * @return id + */ + public String getServerID () + { + return "AlertProcessor" + get_ID(); + } // getServerID + + /** + * Get Date Next Run + * @param requery requery + * @return date next run + */ + public Timestamp getDateNextRun (boolean requery) + { + if (requery) + load(get_TrxName()); + return getDateNextRun(); + } // getDateNextRun + + /** + * Get Logs + * @return logs + */ + public AdempiereProcessorLog[] getLogs () + { + ArrayList list = new ArrayList(); + String sql = "SELECT * " + + "FROM AD_AlertProcessorLog " + + "WHERE AD_AlertProcessor_ID=? " + + "ORDER BY Created DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getAD_AlertProcessor_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MAlertProcessorLog (getCtx(), rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MAlertProcessorLog[] retValue = new MAlertProcessorLog[list.size ()]; + list.toArray (retValue); + return retValue; + } // getLogs + + /** + * Delete old Request Log + * @return number of records + */ + public int deleteLog() + { + if (getKeepLogDays() < 1) + return 0; + String sql = "DELETE AD_AlertProcessorLog " + + "WHERE AD_AlertProcessor_ID=" + getAD_AlertProcessor_ID() + + " AND (Created+" + getKeepLogDays() + ") < SysDate"; + int no = DB.executeUpdate(sql, get_TrxName()); + return 0; + } // deleteLog + + + /** + * Get Alerts + * @param reload reload data + * @return array of alerts + */ + public MAlert[] getAlerts (boolean reload) + { + if (m_alerts != null && !reload) + return m_alerts; + String sql = "SELECT * FROM AD_Alert " + + "WHERE AD_AlertProcessor_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getAD_AlertProcessor_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MAlert (getCtx(), rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + m_alerts = new MAlert[list.size ()]; + list.toArray (m_alerts); + return m_alerts; + } // getAlerts + +} // MAlertProcessor diff --git a/base/src/org/compiere/model/MAlertProcessorLog.java b/base/src/org/compiere/model/MAlertProcessorLog.java new file mode 100644 index 0000000000..61e26ccc8c --- /dev/null +++ b/base/src/org/compiere/model/MAlertProcessorLog.java @@ -0,0 +1,67 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Alert Log + * + * @author Jorg Janke + * @version $Id: MAlertProcessorLog.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MAlertProcessorLog extends X_AD_AlertProcessorLog + implements AdempiereProcessorLog +{ + /** + * Standard Constructor + * @param ctx context + * @param AD_AlertProcessorLog_ID id + * @param trxName transaction + */ + public MAlertProcessorLog (Properties ctx, int AD_AlertProcessorLog_ID, String trxName) + { + super (ctx, AD_AlertProcessorLog_ID, trxName); + } // MAlertProcessorLog + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MAlertProcessorLog (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAlertProcessorLog + + /** + * Parent Constructor + * @param parent parent + * @param summary summary + */ + public MAlertProcessorLog (MAlertProcessor parent, String summary) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setAD_AlertProcessor_ID(parent.getAD_AlertProcessor_ID()); + setSummary(summary); + } // MAlertProcessorLog + +} // MAlertProcessorLog diff --git a/base/src/org/compiere/model/MAlertRecipient.java b/base/src/org/compiere/model/MAlertRecipient.java new file mode 100644 index 0000000000..eaee08a750 --- /dev/null +++ b/base/src/org/compiere/model/MAlertRecipient.java @@ -0,0 +1,94 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Alert Recipient + * + * @author Jorg Janke + * @version $Id: MAlertRecipient.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MAlertRecipient extends X_AD_AlertRecipient +{ + /** + * Standard Constructor + * @param ctx context + * @param AD_AlertRecipient_ID id + * @param trxName transaction + */ + public MAlertRecipient (Properties ctx, int AD_AlertRecipient_ID, String trxName) + { + super (ctx, AD_AlertRecipient_ID, trxName); + } // MAlertRecipient + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MAlertRecipient (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAlertRecipient + + + + /** + * Get User + * @return AD_User_ID or -1 if none + */ + public int getAD_User_ID () + { + Integer ii = (Integer)get_Value("AD_User_ID"); + if (ii == null) + return -1; + return ii.intValue(); + } // getAD_User_ID + + + /** + * Get Role + * @return AD_Role_ID or -1 if none + */ + public int getAD_Role_ID () + { + Integer ii = (Integer)get_Value("AD_Role_ID"); + if (ii == null) + return -1; + return ii.intValue(); + } // getAD_Role_ID + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MAlertRecipient["); + sb.append(get_ID()) + .append(",AD_User_ID=").append(getAD_User_ID()) + .append(",AD_Role_ID=").append(getAD_Role_ID()) + .append ("]"); + return sb.toString (); + } // toString + +} // MAlertRecipient diff --git a/base/src/org/compiere/model/MAlertRule.java b/base/src/org/compiere/model/MAlertRule.java new file mode 100644 index 0000000000..fd23237505 --- /dev/null +++ b/base/src/org/compiere/model/MAlertRule.java @@ -0,0 +1,99 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Alert Rule Model + * + * @author Jorg Janke + * @version $Id: MAlertRule.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MAlertRule extends X_AD_AlertRule +{ + /** + * Standatd Constructor + * @param ctx context + * @param AD_AlertRule_ID id + * @param trxName transaction + */ + public MAlertRule (Properties ctx, int AD_AlertRule_ID, String trxName) + { + super (ctx, AD_AlertRule_ID, trxName); + } // MAlertRule + + /** + * Standard Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MAlertRule (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAlertRule + + /** + * Get Sql + * @return sql + */ + public String getSql() + { + StringBuffer sql = new StringBuffer(); + sql.append("SELECT ").append(getSelectClause()) + .append(" FROM ").append(getFromClause()); + if (getWhereClause() != null && getWhereClause().length() > 0) + sql.append(" WHERE ").append(getWhereClause()); + if (getOtherClause() != null && getOtherClause().length() > 0) + sql.append(" ").append(getOtherClause()); + return sql.toString(); + } // getSql + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (newRecord) + setIsValid(true); + if (isValid()) + setErrorMsg(null); + return true; + } // beforeSave + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MAlertRule["); + sb.append(get_ID()) + .append("-").append(getName()) + .append(",Valid=").append(isValid()) + .append(",").append(getSql()); + sb.append ("]"); + return sb.toString (); + } // toString + +} // MAlertRule diff --git a/base/src/org/compiere/model/MAllocationHdr.java b/base/src/org/compiere/model/MAllocationHdr.java new file mode 100644 index 0000000000..a163e2493c --- /dev/null +++ b/base/src/org/compiere/model/MAllocationHdr.java @@ -0,0 +1,683 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Payment Allocation Model. + * Allocation Trigger update C_BPartner + * + * @author Jorg Janke + * @version $Id: MAllocationHdr.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public final class MAllocationHdr extends X_C_AllocationHdr implements DocAction +{ + /** + * Get Allocations of Payment + * @param ctx context + * @param C_Payment_ID payment + * @return allocations of payment + * @param trxName transaction + */ + public static MAllocationHdr[] getOfPayment (Properties ctx, int C_Payment_ID, String trxName) + { + String sql = "SELECT * FROM C_AllocationHdr h " + + "WHERE IsActive='Y'" + + " AND EXISTS (SELECT * FROM C_AllocationLine l " + + "WHERE h.C_AllocationHdr_ID=l.C_AllocationHdr_ID AND l.C_Payment_ID=?)"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, C_Payment_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add (new MAllocationHdr(ctx, rs, trxName)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MAllocationHdr[] retValue = new MAllocationHdr[list.size()]; + list.toArray(retValue); + return retValue; + } // getOfPayment + + /** + * Get Allocations of Invoice + * @param ctx context + * @param C_Invoice_ID payment + * @return allocations of payment + * @param trxName transaction + */ + public static MAllocationHdr[] getOfInvoice (Properties ctx, int C_Invoice_ID, String trxName) + { + String sql = "SELECT * FROM C_AllocationHdr h " + + "WHERE IsActive='Y'" + + " AND EXISTS (SELECT * FROM C_AllocationLine l " + + "WHERE h.C_AllocationHdr_ID=l.C_AllocationHdr_ID AND l.C_Invoice_ID=?)"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, C_Invoice_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add (new MAllocationHdr(ctx, rs, trxName)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MAllocationHdr[] retValue = new MAllocationHdr[list.size()]; + list.toArray(retValue); + return retValue; + } // getOfInvoice + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger(MAllocationHdr.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param C_AllocationHdr_ID id + * @param trxName transaction + */ + public MAllocationHdr (Properties ctx, int C_AllocationHdr_ID, String trxName) + { + super (ctx, C_AllocationHdr_ID, trxName); + if (C_AllocationHdr_ID == 0) + { + // setDocumentNo (null); + setDateTrx (new Timestamp(System.currentTimeMillis())); + setDateAcct (getDateTrx()); + setDocAction (DOCACTION_Complete); // CO + setDocStatus (DOCSTATUS_Drafted); // DR + // setC_Currency_ID (0); + setApprovalAmt (Env.ZERO); + setIsApproved (false); + setIsManual (false); + // + setPosted (false); + setProcessed (false); + setProcessing(false); + } + } // MAllocation + + /** + * Mandatory New Constructor + * @param ctx context + * @param IsManual manual trx + * @param DateTrx date (if null today) + * @param C_Currency_ID currency + * @param description description + * @param trxName transaction + */ + public MAllocationHdr (Properties ctx, boolean IsManual, Timestamp DateTrx, + int C_Currency_ID, String description, String trxName) + { + this (ctx, 0, trxName); + setIsManual(IsManual); + if (DateTrx != null) + { + setDateTrx (DateTrx); + setDateAcct (DateTrx); + } + setC_Currency_ID (C_Currency_ID); + if (description != null) + setDescription(description); + } // create Allocation + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MAllocationHdr (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAllocation + + /** Lines */ + private MAllocationLine[] m_lines = null; + + /** + * Get Lines + * @param requery if true requery + * @return lines + */ + public MAllocationLine[] getLines (boolean requery) + { + if (m_lines != null && m_lines.length != 0 && !requery) + return m_lines; + // + String sql = "SELECT * FROM C_AllocationLine WHERE C_AllocationHdr_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_AllocationHdr_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MAllocationLine line = new MAllocationLine(getCtx(), rs, get_TrxName()); + line.setParent(this); + list.add (line); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } catch (Exception e) + { + pstmt = null; + } + // + m_lines = new MAllocationLine[list.size ()]; + list.toArray (m_lines); + return m_lines; + } // getLines + + /** + * Set Processed + * @param processed Processed + */ + public void setProcessed (boolean processed) + { + super.setProcessed (processed); + if (get_ID() == 0) + return; + String sql = "UPDATE C_AllocationHdr SET Processed='" + + (processed ? "Y" : "N") + + "' WHERE C_AllocationHdr_ID=" + getC_AllocationHdr_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + m_lines = null; + log.fine(processed + " - #" + no); + } // setProcessed + + + /************************************************************************** + * Before Save + * @param newRecord + * @return save + */ + protected boolean beforeSave (boolean newRecord) + { + // Changed from Not to Active + if (!newRecord && is_ValueChanged("IsActive") && isActive()) + { + log.severe ("Cannot Re-Activate deactivated Allocations"); + return false; + } + return true; + } // beforeSave + + /** + * Before Delete. + * @return true if acct was deleted + */ + protected boolean beforeDelete () + { + String trxName = get_TrxName(); + if (trxName == null || trxName.length() == 0) + log.warning ("No transaction"); + if (isPosted()) + { + if (!MPeriod.isOpen(getCtx(), getDateTrx(), MDocType.DOCBASETYPE_PaymentAllocation)) + { + log.warning ("Period Closed"); + return false; + } + setPosted(false); + if (MFactAcct.delete (Table_ID, get_ID(), trxName) < 0) + return false; + } + // Mark as Inactive + setIsActive(false); // updated DB for line delete/process + String sql = "UPDATE C_AllocationHdr SET IsActive='N' WHERE C_AllocationHdr_ID=?"; + DB.executeUpdate(sql, getC_AllocationHdr_ID(), trxName); + + // Unlink + getLines(true); + HashSet bps = new HashSet(); + for (int i = 0; i < m_lines.length; i++) + { + MAllocationLine line = m_lines[i]; + bps.add(new Integer(line.getC_BPartner_ID())); + if (!line.delete(true, trxName)) + return false; + } + updateBP(bps); + return true; + } // beforeDelete + + /** + * After Save + * @param newRecord + * @param success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + return success; + } // afterSave + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // processIt + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info(toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info(toString()); + setDocAction(DOCACTION_Prepare); + return true; + } // invalidateIt + + /** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + + // Std Period open? + if (!MPeriod.isOpen(getCtx(), getDateAcct(), MDocType.DOCBASETYPE_PaymentAllocation)) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + getLines(false); + if (m_lines.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + // Add up Amounts & validate + BigDecimal approval = Env.ZERO; + for (int i = 0; i < m_lines.length; i++) + { + MAllocationLine line = m_lines[i]; + approval = approval.add(line.getWriteOffAmt()).add(line.getDiscountAmt()); + // Make sure there is BP + if (line.getC_BPartner_ID() == 0) + { + m_processMsg = "No Business Partner"; + return DocAction.STATUS_Invalid; + } + } + setApprovalAmt(approval); + // + m_justPrepared = true; + if (!DOCACTION_Complete.equals(getDocAction())) + setDocAction(DOCACTION_Complete); + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info(toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info(toString()); + setIsApproved(false); + return true; + } // rejectIt + + /** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + // Implicit Approval + if (!isApproved()) + approveIt(); + log.info(toString()); + + // Link + getLines(false); + HashSet bps = new HashSet(); + for (int i = 0; i < m_lines.length; i++) + { + MAllocationLine line = m_lines[i]; + bps.add(new Integer(line.processIt(false))); // not reverse + } + updateBP(bps); + + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + m_processMsg = valid; + return DocAction.STATUS_Invalid; + } + + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + /** + * Void Document. + * Same as Close. + * @return true if success + */ + public boolean voidIt() + { + log.info(toString()); + boolean retValue = reverseIt(); + setDocAction(DOCACTION_None); + return retValue; + } // voidIt + + /** + * Close Document. + * Cancel not delivered Qunatities + * @return true if success + */ + public boolean closeIt() + { + log.info(toString()); + + setDocAction(DOCACTION_None); + return true; + } // closeIt + + /** + * Reverse Correction + * @return true if success + */ + public boolean reverseCorrectIt() + { + log.info(toString()); + boolean retValue = reverseIt(); + setDocAction(DOCACTION_None); + return retValue; + } // reverseCorrectionIt + + /** + * Reverse Accrual - none + * @return false + */ + public boolean reverseAccrualIt() + { + log.info(toString()); + boolean retValue = reverseIt(); + setDocAction(DOCACTION_None); + return retValue; + } // reverseAccrualIt + + /** + * Re-activate + * @return false + */ + public boolean reActivateIt() + { + log.info(toString()); + return false; + } // reActivateIt + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MAllocationHdr["); + sb.append(get_ID()).append("-").append(getSummary()).append ("]"); + return sb.toString (); + } // toString + + /** + * Get Document Info + * @return document info (untranslated) + */ + public String getDocumentInfo() + { + return Msg.getElement(getCtx(), "C_AllocationHdr_ID") + " " + getDocumentNo(); + } // getDocumentInfo + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + // ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.INVOICE, getC_Invoice_ID()); + // if (re == null) + return null; + // return re.getPDF(file); + } // createPDF + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getDocumentNo()); + // : Total Lines = 123.00 (#1) + sb.append(": ") + .append(Msg.translate(getCtx(),"ApprovalAmt")).append("=").append(getApprovalAmt()) + .append(" (#").append(getLines(false).length).append(")"); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner (Responsible) + * @return AD_User_ID + */ + public int getDoc_User_ID() + { + return getCreatedBy(); + } // getDoc_User_ID + + + /************************************************************************** + * Reverse Allocation. + * Period needs to be open + * @return true if reversed + */ + private boolean reverseIt() + { + if (!isActive()) + throw new IllegalStateException("Allocation already reversed (not active)"); + + // Can we delete posting + if (!MPeriod.isOpen(getCtx(), getDateTrx(), MPeriodControl.DOCBASETYPE_PaymentAllocation)) + throw new IllegalStateException("@PeriodClosed@"); + + // Set Inactive + setIsActive (false); + setDocumentNo(getDocumentNo()+"^"); + setDocStatus(DOCSTATUS_Reversed); // for direct calls + if (!save() || isActive()) + throw new IllegalStateException("Cannot de-activate allocation"); + + // Delete Posting + String sql = "DELETE FROM Fact_Acct WHERE AD_Table_ID=" + MAllocationHdr.Table_ID + + " AND Record_ID=" + getC_AllocationHdr_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + log.fine("Fact_Acct deleted #" + no); + + // Unlink Invoices + getLines(true); + HashSet bps = new HashSet(); + for (int i = 0; i < m_lines.length; i++) + { + MAllocationLine line = m_lines[i]; + line.setIsActive(false); + line.save(); + bps.add(new Integer(line.processIt(true))); // reverse + } + updateBP(bps); + return true; + } // reverse + + + /** + * Update Open Balance of BP's + * @param bps list of business partners + */ + private void updateBP(HashSet bps) + { + log.info("#" + bps.size()); + Iterator it = bps.iterator(); + while (it.hasNext()) + { + int C_BPartner_ID = it.next(); + MBPartner bp = new MBPartner(getCtx(), C_BPartner_ID, get_TrxName()); + bp.setTotalOpenBalance(); // recalculates from scratch + // bp.setSOCreditStatus(); // called automatically + if (bp.save()) + log.fine(bp.toString()); + else + log.log(Level.SEVERE, "BP not updated - " + bp); + } + } // updateBP + +} // MAllocation diff --git a/base/src/org/compiere/model/MAllocationLine.java b/base/src/org/compiere/model/MAllocationLine.java new file mode 100644 index 0000000000..4b0a8c8973 --- /dev/null +++ b/base/src/org/compiere/model/MAllocationLine.java @@ -0,0 +1,337 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Allocation Line Model + * + * @author Jorg Janke + * @version $Id: MAllocationLine.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MAllocationLine extends X_C_AllocationLine +{ + + /** + * Standard Constructor + * @param ctx context + * @param C_AllocationLine_ID id + * @param trxName name + */ + public MAllocationLine (Properties ctx, int C_AllocationLine_ID, String trxName) + { + super (ctx, C_AllocationLine_ID, trxName); + if (C_AllocationLine_ID == 0) + { + // setC_AllocationHdr_ID (0); + setAmount (Env.ZERO); + setDiscountAmt (Env.ZERO); + setWriteOffAmt (Env.ZERO); + setOverUnderAmt(Env.ZERO); + } + } // MAllocationLine + + /** + * Load Constructor + * @param ctx ctx + * @param rs result set + * @param trxName transaction + */ + public MAllocationLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAllocationLine + + /** + * Parent Constructor + * @param parent parent + */ + public MAllocationLine (MAllocationHdr parent) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setC_AllocationHdr_ID(parent.getC_AllocationHdr_ID()); + m_parent = parent; + set_TrxName(parent.get_TrxName()); + } // MAllocationLine + + /** + * Parent Constructor + * @param parent parent + * @param Amount amount + * @param DiscountAmt optional discount + * @param WriteOffAmt optional write off + * @param OverUnderAmt over/underpayment + */ + public MAllocationLine (MAllocationHdr parent, BigDecimal Amount, + BigDecimal DiscountAmt, BigDecimal WriteOffAmt, BigDecimal OverUnderAmt) + { + this (parent); + setAmount (Amount); + setDiscountAmt (DiscountAmt == null ? Env.ZERO : DiscountAmt); + setWriteOffAmt (WriteOffAmt == null ? Env.ZERO : WriteOffAmt); + setOverUnderAmt (OverUnderAmt == null ? Env.ZERO : OverUnderAmt); + } // MAllocationLine + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MAllocationLine.class); + /** Invoice info */ + private MInvoice m_invoice = null; + /** Allocation Header */ + private MAllocationHdr m_parent = null; + + /** + * Get Parent + * @return parent + */ + public MAllocationHdr getParent() + { + if (m_parent == null) + m_parent = new MAllocationHdr (getCtx(), getC_AllocationHdr_ID(), get_TrxName()); + return m_parent; + } // getParent + + /** + * Set Parent + * @param parent parent + */ + protected void setParent (MAllocationHdr parent) + { + m_parent = parent; + } // setParent + + /** + * Get Parent Trx Date + * @return date trx + */ + public Timestamp getDateTrx () + { + return getParent().getDateTrx (); + } // getDateTrx + + /** + * Set Document Info + * @param C_BPartner_ID partner + * @param C_Order_ID order + * @param C_Invoice_ID invoice + */ + public void setDocInfo (int C_BPartner_ID, int C_Order_ID, int C_Invoice_ID) + { + setC_BPartner_ID(C_BPartner_ID); + setC_Order_ID(C_Order_ID); + setC_Invoice_ID(C_Invoice_ID); + } // setDocInfo + + /** + * Set Payment Info + * @param C_Payment_ID payment + * @param C_CashLine_ID cash line + */ + public void setPaymentInfo (int C_Payment_ID, int C_CashLine_ID) + { + if (C_Payment_ID != 0) + setC_Payment_ID(C_Payment_ID); + if (C_CashLine_ID != 0) + setC_CashLine_ID(C_CashLine_ID); + } // setPaymentInfo + + /** + * Get Invoice + * @return invoice or null + */ + public MInvoice getInvoice() + { + if (m_invoice == null && getC_Invoice_ID() != 0) + m_invoice = new MInvoice (getCtx(), getC_Invoice_ID(), get_TrxName()); + return m_invoice; + } // getInvoice + + + /************************************************************************** + * Before Save + * @param newRecord + * @return save + */ + protected boolean beforeSave (boolean newRecord) + { + if (!newRecord + && (is_ValueChanged("C_BPartner_ID") || is_ValueChanged("C_Invoice_ID"))) + { + log.severe ("Cannot Change Business Partner or Invoice"); + return false; + } + + // Set BPartner/Order from Invoice + if (getC_BPartner_ID() == 0 && getInvoice() != null) + setC_BPartner_ID(getInvoice().getC_BPartner_ID()); + if (getC_Order_ID() == 0 && getInvoice() != null) + setC_Order_ID(getInvoice().getC_Order_ID()); + // + return true; + } // beforeSave + + + /** + * Before Delete + * @return true if reversed + */ + protected boolean beforeDelete () + { + setIsActive(false); + processIt(true); + return true; + } // beforeDelete + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MAllocationLine["); + sb.append(get_ID()); + if (getC_Payment_ID() != 0) + sb.append(",C_Payment_ID=").append(getC_Payment_ID()); + if (getC_CashLine_ID() != 0) + sb.append(",C_CashLine_ID=").append(getC_CashLine_ID()); + if (getC_Invoice_ID() != 0) + sb.append(",C_Invoice_ID=").append(getC_Invoice_ID()); + if (getC_BPartner_ID() != 0) + sb.append(",C_BPartner_ID=").append(getC_BPartner_ID()); + sb.append(", Amount=").append(getAmount()) + .append(",Discount=").append(getDiscountAmt()) + .append(",WriteOff=").append(getWriteOffAmt()) + .append(",OverUnder=").append(getOverUnderAmt()); + sb.append ("]"); + return sb.toString (); + } // toString + + /************************************************************************** + * Process Allocation (does not update line). + * - Update and Link Invoice/Payment/Cash + * @param reverse if true allocation is reversed + * @return C_BPartner_ID + */ + protected int processIt (boolean reverse) + { + log.fine("Reverse=" + reverse + " - " + toString()); + int C_Invoice_ID = getC_Invoice_ID(); + MInvoice invoice = getInvoice(); + if (invoice != null + && getC_BPartner_ID() != invoice.getC_BPartner_ID()) + setC_BPartner_ID(invoice.getC_BPartner_ID()); + // + int C_Payment_ID = getC_Payment_ID(); + int C_CashLine_ID = getC_CashLine_ID(); + + // Update Payment + if (C_Payment_ID != 0) + { + MPayment payment = new MPayment (getCtx(), C_Payment_ID, get_TrxName()); + if (getC_BPartner_ID() != payment.getC_BPartner_ID()) + log.warning("C_BPartner_ID different - Invoice=" + getC_BPartner_ID() + " - Payment=" + payment.getC_BPartner_ID()); + if (reverse) + { + if (!payment.isCashTrx()) + { + payment.setIsAllocated(false); + payment.save(); + } + } + else + { + if (payment.testAllocation()) + payment.save(); + } + } + + // Payment - Invoice + if (C_Payment_ID != 0 && invoice != null) + { + // Link to Invoice + if (reverse) + { + invoice.setC_Payment_ID(0); + log.fine("C_Payment_ID=" + C_Payment_ID + + " Unlinked from C_Invoice_ID=" + C_Invoice_ID); + } + else if (invoice.isPaid()) + { + invoice.setC_Payment_ID(C_Payment_ID); + log.fine("C_Payment_ID=" + C_Payment_ID + + " Linked to C_Invoice_ID=" + C_Invoice_ID); + } + + // Link to Order + String update = "UPDATE C_Order o " + + "SET C_Payment_ID=" + + (reverse ? "NULL " : "(SELECT C_Payment_ID FROM C_Invoice WHERE C_Invoice_ID=" + C_Invoice_ID + ") ") + + "WHERE EXISTS (SELECT * FROM C_Invoice i " + + "WHERE o.C_Order_ID=i.C_Order_ID AND i.C_Invoice_ID=" + C_Invoice_ID + ")"; + if (DB.executeUpdate(update, get_TrxName()) > 0) + log.fine("C_Payment_ID=" + C_Payment_ID + + (reverse ? " UnLinked from" : " Linked to") + + " order of C_Invoice_ID=" + C_Invoice_ID); + } + + // Cash - Invoice + if (C_CashLine_ID != 0 && invoice != null) + { + // Link to Invoice + if (reverse) + { + invoice.setC_CashLine_ID(0); + log.fine("C_CashLine_ID=" + C_CashLine_ID + + " Unlinked from C_Invoice_ID=" + C_Invoice_ID); + } + else + { + invoice.setC_CashLine_ID(C_CashLine_ID); + log.fine("C_CashLine_ID=" + C_CashLine_ID + + " Linked to C_Invoice_ID=" + C_Invoice_ID); + } + + // Link to Order + String update = "UPDATE C_Order o " + + "SET C_CashLine_ID=" + + (reverse ? "NULL " : "(SELECT C_CashLine_ID FROM C_Invoice WHERE C_Invoice_ID=" + C_Invoice_ID + ") ") + + "WHERE EXISTS (SELECT * FROM C_Invoice i " + + "WHERE o.C_Order_ID=i.C_Order_ID AND i.C_Invoice_ID=" + C_Invoice_ID + ")"; + if (DB.executeUpdate(update, get_TrxName()) > 0) + log.fine("C_CashLine_ID=" + C_CashLine_ID + + (reverse ? " UnLinked from" : " Linked to") + + " order of C_Invoice_ID=" + C_Invoice_ID); + } + + // Update Balance / Credit used - Counterpart of MInvoice.completeIt + if (invoice != null) + { + if (invoice.testAllocation() + && !invoice.save()) + log.log(Level.SEVERE, "Invoice not updated - " + invoice); + } + + return getC_BPartner_ID(); + } // processIt + +} // MAllocationLine diff --git a/base/src/org/compiere/model/MAsset.java b/base/src/org/compiere/model/MAsset.java new file mode 100644 index 0000000000..d1b89a4f7f --- /dev/null +++ b/base/src/org/compiere/model/MAsset.java @@ -0,0 +1,456 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import javax.servlet.http.*; +import org.compiere.util.*; + +/** + * Asset Model + * + * @author Jorg Janke + * @version $Id: MAsset.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MAsset extends X_A_Asset +{ + /** + * Get Asset From Shipment + * @param ctx context + * @param M_InOutLine_ID shipment line + * @param trxName transaction + * @return asset or null + */ + public static MAsset getFromShipment (Properties ctx, int M_InOutLine_ID, String trxName) + { + MAsset retValue = null; + String sql = "SELECT * FROM A_Asset WHERE M_InOutLine_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_InOutLine_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = new MAsset (ctx, rs, trxName); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return retValue; + } // getFromShipment + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MAsset.class); + + + /************************************************************************** + * Asset Constructor + * @param ctx context + * @param A_Asset_ID asset + * @param trxName transaction name + */ + public MAsset (Properties ctx, int A_Asset_ID, String trxName) + { + super (ctx, A_Asset_ID, trxName); + if (A_Asset_ID == 0) + { + setIsDepreciated (false); + setIsFullyDepreciated (false); + // setValue (null); + // setName (null); + setIsInPosession (false); + setIsOwned (false); + // setA_Asset_Group_ID (0); + setIsDisposed (false); + setM_AttributeSetInstance_ID(0); + setQty(Env.ONE); + } + } // MAsset + + /** + * Discontinued Asset Constructor - DO NOT USE (but don't delete either) + * @param ctx context + * @param A_Asset_ID asset + */ + public MAsset (Properties ctx, int A_Asset_ID) + { + this (ctx, A_Asset_ID, null); + } // MAsset + + /** + * Load Constructor + * @param ctx context + * @param rs result set record + * @param trxName transaction + */ + public MAsset (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAsset + + /** + * Shipment Constructor + * @param shipment shipment + * @param shipLine shipment line + * @param deliveryCount 0 or number of delivery + */ + public MAsset (MInOut shipment, MInOutLine shipLine, int deliveryCount) + { + this (shipment.getCtx(), 0, shipment.get_TrxName()); + setClientOrg(shipment); + + setValueNameDescription(shipment, shipLine, deliveryCount); + // Header + setAssetServiceDate(shipment.getMovementDate()); + setIsOwned(false); + setC_BPartner_ID(shipment.getC_BPartner_ID()); + setC_BPartner_Location_ID(shipment.getC_BPartner_Location_ID()); + setAD_User_ID(shipment.getAD_User_ID()); + + // Line + MProduct product = shipLine.getProduct(); + setM_Product_ID(product.getM_Product_ID()); + setA_Asset_Group_ID(product.getA_Asset_Group_ID()); + // Guarantee & Version + setGuaranteeDate(TimeUtil.addDays(shipment.getMovementDate(), product.getGuaranteeDays())); + setVersionNo(product.getVersionNo()); + if (shipLine.getM_AttributeSetInstance_ID() != 0) + { + MAttributeSetInstance asi = new MAttributeSetInstance (getCtx(), shipLine.getM_AttributeSetInstance_ID(), get_TrxName()); + setM_AttributeSetInstance_ID(asi.getM_AttributeSetInstance_ID()); + setLot(asi.getLot()); + setSerNo(asi.getSerNo()); + } + setHelp(shipLine.getDescription()); + if (deliveryCount != 0) + setQty(shipLine.getMovementQty()); + setM_InOutLine_ID(shipLine.getM_InOutLine_ID()); + + // Activate + MAssetGroup ag = MAssetGroup.get(getCtx(), getA_Asset_Group_ID()); + if (!ag.isCreateAsActive()) + setIsActive(false); + } // MAsset + + + /** Product Info */ + private MProduct m_product = null; + + /** + * Set Value Name Description + * @param shipment shipment + * @param line line + * @param deliveryCount + */ + public void setValueNameDescription(MInOut shipment, MInOutLine line, + int deliveryCount) + { + MProduct product = line.getProduct(); + MBPartner partner = shipment.getBPartner(); + setValueNameDescription(shipment, deliveryCount, product, partner); + } // setValueNameDescription + + /** + * Set Value, Name, Description + * @param shipment shipment + * @param deliveryCount count + * @param product product + * @param partner partner + */ + public void setValueNameDescription (MInOut shipment, + int deliveryCount, MProduct product, MBPartner partner) + { + String documentNo = "_" + shipment.getDocumentNo(); + if (deliveryCount > 1) + documentNo += "_" + deliveryCount; + // Value + String value = partner.getValue() + "_" + product.getValue(); + if (value.length() > 40-documentNo.length()) + value = value.substring(0,40-documentNo.length()) + documentNo; + setValue(value); + + // Name MProduct.afterSave + String name = partner.getName() + " - " + product.getName(); + if (name.length() > 60) + name = name.substring(0,60); + setName(name); + // Description + String description = product.getDescription(); + setDescription(description); + } // setValueNameDescription + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * Get Qty + * @return 1 or Qty + */ + public BigDecimal getQty () + { + BigDecimal qty = super.getQty(); + if (qty == null || qty.equals(Env.ZERO)) + setQty(Env.ONE); + return super.getQty(); + } // getQty + + /** + * String representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MAsset[") + .append (get_ID ()) + .append("-").append(getValue()) + .append ("]"); + return sb.toString (); + } // toString + + + /************************************************************************** + * Get Deliveries + * @return deliveries + */ + public MAssetDelivery[] getDeliveries() + { + ArrayList list = new ArrayList(); + + String sql = "SELECT * FROM A_Asset_Delivery WHERE A_Asset_ID=? ORDER BY Created DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getA_Asset_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MAssetDelivery(getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + // + MAssetDelivery[] retValue = new MAssetDelivery[list.size()]; + list.toArray(retValue); + return retValue; + } // getDeliveries + + /** + * Get Delivery count + * @return delivery count + */ + public int getDeliveryCount() + { + String sql = "SELECT COUNT(*) FROM A_Asset_Delivery WHERE A_Asset_ID=?"; + return DB.getSQLValue(get_TrxName(), + sql, getA_Asset_ID()); + } // getDeliveries + + + /************************************************************************** + * Can we download. + * Based on guarantee date and availability of download + * @return true if downloadable + */ + public boolean isDownloadable() + { + if (!isActive()) + return false; + + // Guarantee Date + Timestamp guarantee = getGuaranteeDate(); + if (guarantee == null) + return false; + guarantee = TimeUtil.getDay(guarantee); + Timestamp now = TimeUtil.getDay(System.currentTimeMillis()); + // valid + if (!now.after(guarantee)) // not after guarantee date + { + getProduct(); + return m_product != null + && m_product.hasDownloads(); + } + // + return false; + } // isDownloadable + + /************************************************************************** + * Get Product Version No + * @return VersionNo + */ + public String getProductVersionNo() + { + return getProduct().getVersionNo(); + } // getProductVersionNo + + /** + * Get Product R_MailText_ID + * @return R_MailText_ID + */ + public int getProductR_MailText_ID() + { + return getProduct().getR_MailText_ID(); + } // getProductR_MailText_ID + + /** + * Get Product Info + * @return product + */ + private MProduct getProduct() + { + if (m_product == null) + m_product = MProduct.get (getCtx(), getM_Product_ID()); + return m_product; + } // getProductInfo + + /** + * Get Active Addl. Product Downloads + * @return array of downloads + */ + public MProductDownload[] getProductDownloads() + { + if (m_product == null) + getProduct(); + if (m_product != null) + return m_product.getProductDownloads(false); + return null; + } // getProductDownloads + + /** + * Get Additional Download Names + * @return names + */ + public String[] getDownloadNames() + { + MProductDownload[] dls = getProductDownloads(); + if (dls != null && dls.length > 0) + { + String[] retValue = new String[dls.length]; + for (int i = 0; i < retValue.length; i++) + retValue[i] = dls[i].getName(); + log.fine("#" + dls.length); + return retValue; + } + return new String[]{}; + } // addlDownloadNames + + /** + * Get Additional Download URLs + * @return URLs + */ + public String[] getDownloadURLs() + { + MProductDownload[] dls = getProductDownloads(); + if (dls != null && dls.length > 0) + { + String[] retValue = new String[dls.length]; + for (int i = 0; i < retValue.length; i++) + { + String url = dls[i].getDownloadURL(); + int pos = Math.max(url.lastIndexOf('/'), url.lastIndexOf('\\')); + if (pos != -1) + url = url.substring(pos+1); + retValue[i] = url; + } + return retValue; + } + return new String[]{}; + } // addlDownloadURLs + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + getQty(); // set to 1 + return true; + } // beforeSave + + + /************************************************************************* + * Confirm Asset EMail Delivery + * @param email email sent + * @param AD_User_ID recipient + * @return asset delivery + */ + public MAssetDelivery confirmDelivery (EMail email, int AD_User_ID) + { + setVersionNo(getProductVersionNo()); + MAssetDelivery ad = new MAssetDelivery (this, email, AD_User_ID); + return ad; + } // confirmDelivery + + /** + * Confirm Asset Download Delivery + * @param request request + * @param AD_User_ID recipient + * @return asset delivery + */ + public MAssetDelivery confirmDelivery (HttpServletRequest request, int AD_User_ID) + { + setVersionNo(getProductVersionNo()); + setLifeUseUnits(getLifeUseUnits()+1); + MAssetDelivery ad = new MAssetDelivery (this, request, AD_User_ID); + return ad; + } // confirmDelivery + +} // MAsset diff --git a/base/src/org/compiere/model/MAssetDelivery.java b/base/src/org/compiere/model/MAssetDelivery.java new file mode 100644 index 0000000000..7ae982ee43 --- /dev/null +++ b/base/src/org/compiere/model/MAssetDelivery.java @@ -0,0 +1,128 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import javax.servlet.http.*; +import org.compiere.util.*; + +/** + * Asset Delivery Model + * + * @author Jorg Janke + * @version $Id: MAssetDelivery.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MAssetDelivery extends X_A_Asset_Delivery +{ + /** + * Constructor + * @param ctx context + * @param A_Asset_Delivery_ID id or 0 + * @param trxName trx + */ + public MAssetDelivery (Properties ctx, int A_Asset_Delivery_ID, String trxName) + { + super (ctx, A_Asset_Delivery_ID, trxName); + if (A_Asset_Delivery_ID == 0) + { + setMovementDate (new Timestamp (System.currentTimeMillis ())); + } + } // MAssetDelivery + + /** + * Load Constructor + * @param ctx context + * @param rs result set record + * @param trxName transaction + */ + public MAssetDelivery (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAssetDelivery + + /** + * Create Asset Delivery for HTTP Request + * @param asset asset + * @param request request + * @param AD_User_ID BP Contact + */ + public MAssetDelivery (MAsset asset, + HttpServletRequest request, int AD_User_ID) + { + super (asset.getCtx(), 0, asset.get_TrxName()); + setAD_Client_ID(asset.getAD_Client_ID()); + setAD_Org_ID(asset.getAD_Org_ID()); + // Asset Info + setA_Asset_ID (asset.getA_Asset_ID()); + setLot(asset.getLot()); + setSerNo(asset.getSerNo()); + setVersionNo(asset.getVersionNo()); + // + setMovementDate (new Timestamp (System.currentTimeMillis ())); + // Request + setURL(request.getRequestURL().toString()); + setReferrer(request.getHeader("Referer")); + setRemote_Addr(request.getRemoteAddr()); + setRemote_Host(request.getRemoteHost()); + // Who + setAD_User_ID(AD_User_ID); + // + save(); + } // MAssetDelivery + + /** + * Create Asset Delivery for EMail + * @param asset asset + * @param email email + * @param AD_User_ID BP Contact + */ + public MAssetDelivery (MAsset asset, EMail email, int AD_User_ID) + { + super (asset.getCtx(), 0, asset.get_TrxName()); + // Asset Info + setA_Asset_ID (asset.getA_Asset_ID()); + setLot(asset.getLot()); + setSerNo(asset.getSerNo()); + setVersionNo(asset.getVersionNo()); + // + setMovementDate (new Timestamp (System.currentTimeMillis ())); + // EMail + setEMail(email.getTo().toString()); + setMessageID(email.getMessageID()); + // Who + setAD_User_ID(AD_User_ID); + // + save(); + } // MAssetDelivery + + /** + * String representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MAssetDelivery[") + .append (get_ID ()) + .append(",A_Asset_ID=").append(getA_Asset_ID()) + .append(",MovementDate=").append(getMovementDate()) + .append ("]"); + return sb.toString (); + } // toString + +} // MAssetDelivery + diff --git a/base/src/org/compiere/model/MAssetGroup.java b/base/src/org/compiere/model/MAssetGroup.java new file mode 100644 index 0000000000..7ce5baaff5 --- /dev/null +++ b/base/src/org/compiere/model/MAssetGroup.java @@ -0,0 +1,80 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Asset Group Model + * + * @author Jorg Janke + * @version $Id: MAssetGroup.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MAssetGroup extends X_A_Asset_Group +{ + /** + * Get from Cache + * @param ctx context + * @param A_Asset_Group_ID id + * @return category + */ + public static MAssetGroup get (Properties ctx, int A_Asset_Group_ID) + { + Integer ii = new Integer (A_Asset_Group_ID); + MAssetGroup pc = (MAssetGroup)s_cache.get(ii); + if (pc == null) + pc = new MAssetGroup (ctx, A_Asset_Group_ID, null); + return pc; + } // get + + /** Categopry Cache */ + private static CCache s_cache = new CCache ("A_Asset_Group", 10); + + /** + * Standard Constructor + * @param ctx context + * @param A_Asset_Group_ID id + * @param trxName trx + */ + public MAssetGroup (Properties ctx, int A_Asset_Group_ID, String trxName) + { + super (ctx, A_Asset_Group_ID, trxName); + if (A_Asset_Group_ID == 0) + { + // setName (null); + setIsDepreciated (false); + setIsOneAssetPerUOM (false); + setIsOwned (false); + setIsCreateAsActive(true); + setIsTrackIssues(false); + } + } // MAssetGroup + + /** + * Load Cosntructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MAssetGroup (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MAssetGroup + +} // MAssetGroup diff --git a/base/src/org/compiere/model/MAssignmentSlot.java b/base/src/org/compiere/model/MAssignmentSlot.java new file mode 100644 index 0000000000..029c463c14 --- /dev/null +++ b/base/src/org/compiere/model/MAssignmentSlot.java @@ -0,0 +1,665 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.awt.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Assignment Slot. + * Display Information about Assignment Slot + * + * @author Jorg Janke + * @version $Id: MAssignmentSlot.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MAssignmentSlot implements Comparator +{ + /** + * Comparator Constructor + */ + public MAssignmentSlot () + { + this (null, null, null, null, STATUS_TimeSlot); + } // MAssignmentSlot + + /** + * Timeslot Constructor + * @param startTime start time + * @param endTime end time + */ + public MAssignmentSlot (Timestamp startTime, Timestamp endTime) + { + this (startTime, endTime, null, null, STATUS_TimeSlot); + setDisplay(DISPLAY_TIME_FROM); + } // MAssignmentSlot + + /** + * Timeslot Constructor + * @param startTime start time + * @param endTime end time + */ + public MAssignmentSlot (long startTime, long endTime) + { + this (new Timestamp(startTime), new Timestamp(endTime), null, null, STATUS_TimeSlot); + setDisplay(DISPLAY_TIME_FROM); + } // MAssignmentSlot + + /** + * Non Assignment Constructor + * @param startTime start time + * @param endTime end time + * @param name name + * @param description description + * @param status status + */ + public MAssignmentSlot (Timestamp startTime, Timestamp endTime, + String name, String description, int status) + { + setStartTime(startTime); + setEndTime(endTime); + setName(name); + setDescription(description); + setStatus(status); + // + // log.fine( toString()); + } // MAssignmentSlot + + /** + * Assignment Constructor + * @param assignment MAssignment + */ + public MAssignmentSlot (MResourceAssignment assignment) + { + setStatus(assignment.isConfirmed() ? STATUS_Confirmed : STATUS_NotConfirmed); + setMAssignment(assignment); + // log.fine( toString()); + } // MAssignmentSlot + + + /** Not Available Code */ + public static final int STATUS_NotAvailable = 0; + /** Not Available Code */ + public static final int STATUS_UnAvailable = 11; + /** Not Available Code */ + public static final int STATUS_NonBusinessDay = 12; + /** Not Available Code */ + public static final int STATUS_NotInSlotDay = 21; + /** Not Available Code */ + public static final int STATUS_NotInSlotTime = 22; + /** Assignment Code */ + public static final int STATUS_NotConfirmed = 101; + /** Assignment Code */ + public static final int STATUS_Confirmed = 102; + + /** Assignment Code */ + public static final int STATUS_TimeSlot = 100000; + + /** Start Time */ + private Timestamp m_startTime; + /** End Time */ + private Timestamp m_endTime; + /** Name */ + private String m_name; + /** Description */ + private String m_description; + /** Status */ + private int m_status = STATUS_NotAvailable; + /** Y position */ + private int m_yStart = 0; + private int m_yEnd = 0; + private int m_xPos = 0; + private int m_xMax = 1; + + /** The assignment */ + private MResourceAssignment m_mAssignment; + + /** Language used for formatting */ + private Language m_language = Language.getLoginLanguage(); + + /** toString displays everything */ + public static final int DISPLAY_ALL = 0; + + /** toString displays formatted time from */ + public static final int DISPLAY_TIME_FROM = 1; + /** toString displays formatted time from-to */ + public static final int DISPLAY_TIME_FROM_TO = 1; + /** toString displays formatted day time from-to */ + public static final int DISPLAY_DATETIME_FROM_TO = 1; + /** toString displays name */ + public static final int DISPLAY_NAME = 1; + /** toString displays name and optional description */ + public static final int DISPLAY_NAME_DESCRIPTION = 1; + /** toString displays formatted all info */ + public static final int DISPLAY_FULL = 1; + + /** DisplayMode */ + private int m_displayMode = DISPLAY_FULL; + + /*************************************************************************/ + + /** + * Set Status + * @param status STATUS_.. + */ + public void setStatus (int status) + { + m_status = status; + } // setStatus + + /** + * Get Status + * @return STATUS_.. + */ + public int getStatus() + { + return m_status; + } // getStatus + + /** + * Is the Slot an Assignment? + * @return true if slot is an assignment + */ + public boolean isAssignment() + { + return (m_status == STATUS_NotConfirmed || m_status == STATUS_Confirmed); + } // isAssignment + + /** + * Get Color for Status + * @param background true if background - or foreground + * @return Color + */ + public Color getColor (boolean background) + { + // Not found, Inactive, not available + if (m_status == STATUS_NotAvailable) + return background ? Color.gray : Color.magenta; + + // Holiday + else if (m_status == STATUS_UnAvailable) + return background ? Color.gray : Color.pink; + + // Vacation + else if (m_status == STATUS_NonBusinessDay) + return background ? Color.lightGray : Color.red; + + // Out of normal hours + else if (m_status == STATUS_NotInSlotDay || m_status == STATUS_NotInSlotTime) + return background ? Color.lightGray : Color.black; + + // Assigned + else if (m_status == STATUS_NotConfirmed) + return background ? Color.blue : Color.white; + + // Confirmed + else if (m_status == STATUS_Confirmed) + return background ? Color.blue : Color.black; + + // Unknown + return background ? Color.black : Color.white; + } // getColor + + /*************************************************************************/ + + /** + * Get Start time + * @return start time + */ + public Timestamp getStartTime() + { + return m_startTime; + } + + /** + * Set Start time + * @param startTime start time, if null use current time + */ + public void setStartTime (Timestamp startTime) + { + if (startTime == null) + m_startTime = new Timestamp(System.currentTimeMillis()); + else + m_startTime = startTime; + } // setStartTime + + /** + * Get End time + * @return end time + */ + public Timestamp getEndTime() + { + return m_endTime; + } + + /** + * Set End time + * @param endTime end time, if null use start time + */ + public void setEndTime (Timestamp endTime) + { + if (endTime == null) + m_endTime = m_startTime; + else + m_endTime = endTime; + } + + /*************************************************************************/ + + /** + * Set Assignment + * @param assignment MAssignment + */ + public void setMAssignment (MResourceAssignment assignment) + { + if (assignment == null) + return; + if (!isAssignment()) + throw new IllegalArgumentException("Assignment Slot not an Assignment"); + // + m_mAssignment = assignment; + setStartTime(m_mAssignment.getAssignDateFrom()); + setEndTime(m_mAssignment.getAssignDateTo()); + setName(m_mAssignment.getName()); + setDescription(m_mAssignment.getDescription()); + setStatus(m_mAssignment.isConfirmed() ? STATUS_Confirmed : STATUS_NotConfirmed); + } // setMAssignment + + /** + * Get Assugnment + * @return assignment + */ + public MResourceAssignment getMAssignment() + { + return m_mAssignment; + } // getAssignment + + /** + * Set Name + * @param name name + */ + public void setName (String name) + { + if (name == null) + m_name = ""; + else + m_name = name; + } // setName + + /** + * Get Name + * @return name + */ + public String getName() + { + return m_name; + } // getName + + /** + * Set Description + * @param description description + */ + public void setDescription (String description) + { + if (description == null) + m_description = ""; + else + m_description = description; + } // setDescription + + /** + * Get Description + * @return description + */ + public String getDescription() + { + return m_description; + } // getDescription + + /*************************************************************************/ + + /** + * Set Y position + * @param yStart zero based Y start index + * @param yEnd zero based Y end index + */ + public void setY (int yStart, int yEnd) + { + m_yStart = yStart; + m_yEnd = yEnd; + } // setY + + /** + * Get Y start position + * @return zero based Y start index + */ + public int getYStart () + { + return m_yStart; + } // getYStart + + /** + * Get Y end position + * @return zero based Y end index + */ + public int getYEnd () + { + return m_yEnd; + } // setYEnd + + /** + * Set X position + * @param xPos zero based X position index + * @param xMax number of parallel columns + */ + public void setX (int xPos, int xMax) + { + m_xPos = xPos; + if (xMax > m_xMax) + m_xMax = xMax; + } // setX + + /** + * Get X position + * @return zero based X position index + */ + public int getXPos() + { + return m_xPos; + } // setXPos + + /** + * Get X columns + * @return number of parallel columns + */ + public int getXMax() + { + return m_xMax; + } // setXMax + + /*************************************************************************/ + + /** + * Set Language + * @param language language + */ + public void setLanguage (Language language) + { + m_language = language; + } // setLanguage + + /** + * Set Display Mode of toString() + * @param displayMode DISPLAY_ + */ + public void setDisplay (int displayMode) + { + m_displayMode = displayMode; + } // setDisplay + + + /** + * String representation + * @return info + */ + public String toString() + { + if (m_displayMode == DISPLAY_TIME_FROM) + return getInfoTimeFrom(); + else if (m_displayMode == DISPLAY_TIME_FROM_TO) + return getInfoTimeFromTo(); + else if (m_displayMode == DISPLAY_DATETIME_FROM_TO) + return getInfoDateTimeFromTo(); + else if (m_displayMode == DISPLAY_NAME) + return m_name; + else if (m_displayMode == DISPLAY_NAME_DESCRIPTION) + return getInfoNameDescription(); + else if (m_displayMode == DISPLAY_FULL) + return getInfo(); + + // DISPLAY_ALL + StringBuffer sb = new StringBuffer("MAssignmentSlot["); + sb.append(m_startTime).append("-").append(m_endTime) + .append("-Status=").append(m_status).append(",Name=") + .append(m_name).append(",").append(m_description).append("]"); + return sb.toString(); + } // toString + + /** + * Get Info with Time From + * @return info 00:00 + */ + public String getInfoTimeFrom() + { + return m_language.getTimeFormat().format(m_startTime); + } // getInfoTimeFrom + + /** + * Get Info with Time From-To + * @return info 00:00 - 01:00 + */ + public String getInfoTimeFromTo() + { + StringBuffer sb = new StringBuffer(); + sb.append(m_language.getTimeFormat().format(m_startTime)) + .append(" - ") + .append(m_language.getTimeFormat().format(m_endTime)); + return sb.toString(); + } // getInfoTimeFromTo + + /** + * Get Info with Date & Time From-To + * @return info 12/12/01 00:00 - 01:00 or 12/12/01 00:00 - 12/13/01 01:00 + */ + public String getInfoDateTimeFromTo() + { + StringBuffer sb = new StringBuffer(); + sb.append(m_language.getDateTimeFormat().format(m_startTime)) + .append(" - "); + if (TimeUtil.isSameDay(m_startTime, m_endTime)) + sb.append(m_language.getTimeFormat().format(m_endTime)); + else + m_language.getDateTimeFormat().format(m_endTime); + return sb.toString(); + } + + /** + * Get Info with Name and optional Description + * @return Name (Description) + */ + public String getInfoNameDescription() + { + StringBuffer sb = new StringBuffer(m_name); + if (m_description.length() > 0) + sb.append(" (").append(m_description).append(")"); + return sb.toString(); + } // getInfoNameDescription + + /** + * Get Info with Date, Time From-To Name Description + * @return 12/12/01 00:00 - 01:00: Name (Description) + */ + public String getInfo() + { + StringBuffer sb = new StringBuffer(getInfoDateTimeFromTo()); + sb.append(": ").append(m_name); + if (m_description.length() > 0) + sb.append(" (").append(m_description).append(")"); + return sb.toString(); + } // getInfo + + /*************************************************************************/ + + /** + * Returns true if time is between start and end Time. + * Date part is ignored. + *
+	 *  Example:
+	 *  - Slots: 0:00-9:00 - 9:00-10:00 - 10:00-11:00 - ...
+	 *  - inSlot (9:00, false) -> 1		//	start time
+	 *  - inSlot (10:00, true) -> 1		//	end time
+	 *  
+ * @param time time of the day + * @param endTime if true, the end time is included + * @return true if within slot + */ + public boolean inSlot (Timestamp time, boolean endTime) + { + // Compare -- + GregorianCalendar cal = new GregorianCalendar(); + cal.setTime(time); + cal.set(Calendar.YEAR, 1970); + cal.set(Calendar.DAY_OF_YEAR, 1); + // handle -00:00 (end time) + if (endTime && cal.get(Calendar.HOUR_OF_DAY) == 0 && cal.get(Calendar.MINUTE) == 0) + { + cal.set(Calendar.HOUR_OF_DAY, 23); + cal.set(Calendar.MINUTE, 59); + } + Time compare = new Time (cal.getTimeInMillis()); + // Start Time -- + cal.setTime(m_startTime); + cal.set(Calendar.YEAR, 1970); + cal.set(Calendar.DAY_OF_YEAR, 1); + Time start = new Time (cal.getTimeInMillis()); + // End time -- + cal.setTime(m_endTime); + cal.set(Calendar.YEAR, 1970); + cal.set(Calendar.DAY_OF_YEAR, 1); + if (cal.get(Calendar.HOUR_OF_DAY) == 0 && cal.get(Calendar.MINUTE) == 0) + { + cal.set(Calendar.HOUR_OF_DAY, 23); + cal.set(Calendar.MINUTE, 59); + } + Time end = new Time (cal.getTimeInMillis()); + + // before start x |---| + if (compare.before(start)) + { + // System.out.println("InSlot-false Compare=" + compare + " before start " + start); + return false; + } + // after end |---| x + if (compare.after(end)) + { + // System.out.println("InSlot-false Compare=" + compare + " after end " + end); + return false; + } + + // start x---| + if (!endTime && compare.equals(start)) + { + // System.out.println("InSlot-true Compare=" + compare + " = Start=" + start); + return true; + } + + // + // end |---x + if (endTime && compare.equals(end)) + { + // System.out.println("InSlot-true Compare=" + compare + " = End=" + end); + return true; + } + // between start/end |-x-| + if (compare.before(end)) + { + // System.out.println("InSlot-true Compare=" + compare + " before end " + end); + return true; + } + return false; + } // inSlot + + /*************************************************************************/ + + /** + * Compares its two arguments for order. Returns a negative integer, + * zero, or a positive integer as the first argument is less than, equal + * to, or greater than the second. + * + * @param o1 the first object to be compared. + * @param o2 the second object to be compared. + * @return a negative integer, zero, or a positive integer as the + * first argument is less than, equal to, or greater than the + * second. + * @throws ClassCastException if the arguments' types prevent them from + * being compared by this Comparator. + */ + public int compare(Object o1, Object o2) + { + if (!(o1 instanceof MAssignmentSlot && o2 instanceof MAssignmentSlot)) + throw new ClassCastException ("MAssignmentSlot.compare arguments not MAssignmentSlot"); + + MAssignmentSlot s1 = (MAssignmentSlot)o1; + MAssignmentSlot s2 = (MAssignmentSlot)o2; + + // Start Date + int result = s1.getStartTime().compareTo(s2.getStartTime()); + if (result != 0) + return result; + // Status + result = s2.getStatus() - s1.getStatus(); + if (result != 0) + return result; + // End Date + result = s1.getEndTime().compareTo(s2.getEndTime()); + if (result != 0) + return result; + // Name + result = s1.getName().compareTo(s2.getName()); + if (result != 0) + return result; + // Description + return s1.getDescription().compareTo(s2.getDescription()); + } // compare + + /** + * Indicates whether some other object is "equal to" this + * Comparator. + * @param obj the reference object with which to compare. + * @return true only if the specified object is also + * a comparator and it imposes the same ordering as this + * comparator. + * @see java.lang.Object#equals(java.lang.Object) + * @see java.lang.Object#hashCode() + */ + public boolean equals(Object obj) + { + if (obj instanceof MAssignmentSlot) + { + MAssignmentSlot cmp = (MAssignmentSlot)obj; + if (m_startTime.equals(cmp.getStartTime()) + && m_endTime.equals(cmp.getEndTime()) + && m_status == cmp.getStatus() + && m_name.equals(cmp.getName()) + && m_description.equals(cmp.getDescription())) + return true; + } + return false; + } // equals + + /** + * HashCode of MAssignmentSlot + * @return has code + */ + public int hashCode() + { + return m_startTime.hashCode() + m_endTime.hashCode() + m_status + + m_name.hashCode() + m_description.hashCode(); + } // hashCode + +} // MAssignmentSlot diff --git a/base/src/org/compiere/model/MAttribute.java b/base/src/org/compiere/model/MAttribute.java new file mode 100644 index 0000000000..2b1a4a2504 --- /dev/null +++ b/base/src/org/compiere/model/MAttribute.java @@ -0,0 +1,312 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Product Attribute + * + * @author Jorg Janke + * @version $Id: MAttribute.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MAttribute extends X_M_Attribute +{ + /** + * Get Attributes Of Client + * @param ctx Properties + * @param onlyProductAttributes only Product Attributes + * @param onlyListAttributes only List Attributes + * @return array of attributes + */ + public static MAttribute[] getOfClient(Properties ctx, + boolean onlyProductAttributes, boolean onlyListAttributes) + { + ArrayList list = new ArrayList(); + int AD_Client_ID = Env.getAD_Client_ID(ctx); + String sql = "SELECT * FROM M_Attribute " + + "WHERE AD_Client_ID=? AND IsActive='Y'"; + if (onlyProductAttributes) + sql += " AND IsInstanceAttribute='N'"; + if (onlyListAttributes) + sql += " AND AttributeValueType='L'"; + sql += " ORDER BY Name"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, AD_Client_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MAttribute (ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + MAttribute[] retValue = new MAttribute[list.size ()]; + list.toArray (retValue); + s_log.fine("AD_Client_ID=" + AD_Client_ID + " - #" + retValue.length); + return retValue; + } // getOfClient + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MAttribute.class); + + + /** + * Standard Constructor + * @param ctx context + * @param M_Attribute_ID id + * @param trxName transaction + */ + public MAttribute (Properties ctx, int M_Attribute_ID, String trxName) + { + super (ctx, M_Attribute_ID, trxName); + if (M_Attribute_ID == 0) + { + setAttributeValueType(ATTRIBUTEVALUETYPE_StringMax40); + setIsInstanceAttribute (false); + setIsMandatory (false); + } + } // MAttribute + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MAttribute (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAttribute + + /** Values */ + private MAttributeValue[] m_values = null; + + /** + * Get Values if List + * @return Values or null if not list + */ + public MAttributeValue[] getMAttributeValues() + { + if (m_values == null && ATTRIBUTEVALUETYPE_List.equals(getAttributeValueType())) + { + ArrayList list = new ArrayList(); + if (!isMandatory()) + list.add (null); + // + String sql = "SELECT * FROM M_AttributeValue " + + "WHERE M_Attribute_ID=? " + + "ORDER BY Value"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getM_Attribute_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MAttributeValue (getCtx(), rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close(); + } + catch (SQLException ex1) + { + } + pstmt = null; + m_values = new MAttributeValue[list.size()]; + list.toArray(m_values); + } + return m_values; + } // getValues + + + /************************************************************************** + * Get Attribute Instance + * @param M_AttributeSetInstance_ID attribute set instance + * @return Attribute Instance or null + */ + public MAttributeInstance getMAttributeInstance (int M_AttributeSetInstance_ID) + { + MAttributeInstance retValue = null; + String sql = "SELECT * " + + "FROM M_AttributeInstance " + + "WHERE M_Attribute_ID=? AND M_AttributeSetInstance_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getM_Attribute_ID()); + pstmt.setInt(2, M_AttributeSetInstance_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = new MAttributeInstance (getCtx(), rs, get_TrxName()); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + + return retValue; + } // getAttributeInstance + + /** + * Set Attribute Instance + * @param value value + * @param M_AttributeSetInstance_ID id + */ + public void setMAttributeInstance (int M_AttributeSetInstance_ID, MAttributeValue value) + { + MAttributeInstance instance = getMAttributeInstance(M_AttributeSetInstance_ID); + if (instance == null) + { + if (value != null) + instance = new MAttributeInstance (getCtx (), getM_Attribute_ID (), + M_AttributeSetInstance_ID, value.getM_AttributeValue_ID (), + value.getName (), get_TrxName()); // Cached !! + else + instance = new MAttributeInstance (getCtx(), getM_Attribute_ID(), + M_AttributeSetInstance_ID, 0, null, get_TrxName()); + } + else + { + if (value != null) + { + instance.setM_AttributeValue_ID (value.getM_AttributeValue_ID ()); + instance.setValue (value.getName()); // Cached !! + } + else + { + instance.setM_AttributeValue_ID (0); + instance.setValue (null); + } + } + instance.save(); + } // setAttributeInstance + + /** + * Set Attribute Instance + * @param value string value + * @param M_AttributeSetInstance_ID id + */ + public void setMAttributeInstance (int M_AttributeSetInstance_ID, String value) + { + MAttributeInstance instance = getMAttributeInstance(M_AttributeSetInstance_ID); + if (instance == null) + instance = new MAttributeInstance (getCtx(), getM_Attribute_ID(), + M_AttributeSetInstance_ID, value, get_TrxName()); + else + instance.setValue(value); + instance.save(); + } // setAttributeInstance + + /** + * Set Attribute Instance + * @param value number value + * @param M_AttributeSetInstance_ID id + */ + public void setMAttributeInstance (int M_AttributeSetInstance_ID, BigDecimal value) + { + MAttributeInstance instance = getMAttributeInstance(M_AttributeSetInstance_ID); + if (instance == null) + instance = new MAttributeInstance (getCtx(), getM_Attribute_ID(), + M_AttributeSetInstance_ID, value, get_TrxName()); + else + instance.setValueNumber(value); + instance.save(); + } // setAttributeInstance + + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MAttribute["); + sb.append (get_ID()).append ("-").append (getName()) + .append(",Type=").append(getAttributeValueType()) + .append(",Instance=").append(isInstanceAttribute()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * AfterSave + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + // Changed to Instance Attribute + if (!newRecord && is_ValueChanged("IsInstanceAttribute") && isInstanceAttribute()) + { + String sql = "UPDATE M_AttributeSet mas " + + "SET IsInstanceAttribute='Y' " + + "WHERE IsInstanceAttribute='N'" + + " AND EXISTS (SELECT * FROM M_AttributeUse mau " + + "WHERE mas.M_AttributeSet_ID=mau.M_AttributeSet_ID" + + " AND mau.M_Attribute_ID=" + getM_Attribute_ID() + ")"; + int no = DB.executeUpdate(sql, get_TrxName()); + log.fine("AttributeSet Instance set #" + no); + } + return success; + } // afterSave + +} // MAttribute diff --git a/base/src/org/compiere/model/MAttributeInstance.java b/base/src/org/compiere/model/MAttributeInstance.java new file mode 100644 index 0000000000..889b5e8757 --- /dev/null +++ b/base/src/org/compiere/model/MAttributeInstance.java @@ -0,0 +1,161 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; + +/** + * Product Attribute Set + * + * @author Jorg Janke + * @version $Id: MAttributeInstance.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MAttributeInstance extends X_M_AttributeInstance +{ + /** + * Persistency Constructor + * @param ctx context + * @param ignored ignored + * @param trxName transaction + */ + public MAttributeInstance (Properties ctx, int ignored, String trxName) + { + super(ctx, 0, trxName); + if (ignored != 0) + throw new IllegalArgumentException("Multi-Key"); + } // MAttributeInstance + + /** + * Load Cosntructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MAttributeInstance (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAttributeInstance + + /** + * String Value Constructior + * @param ctx context + * @param M_Attribute_ID attribute + * @param M_AttributeSetInstance_ID instance + * @param Value string value + * @param trxName transaction + */ + public MAttributeInstance (Properties ctx, int M_Attribute_ID, + int M_AttributeSetInstance_ID, String Value, String trxName) + { + super(ctx, 0, trxName); + setM_Attribute_ID (M_Attribute_ID); + setM_AttributeSetInstance_ID (M_AttributeSetInstance_ID); + setValue (Value); + } // MAttributeInstance + + /** + * Number Value Constructior + * @param ctx context + * @param M_Attribute_ID attribute + * @param M_AttributeSetInstance_ID instance + * @param BDValue number value + * @param trxName transaction + */ + public MAttributeInstance (Properties ctx, int M_Attribute_ID, + int M_AttributeSetInstance_ID, BigDecimal BDValue, String trxName) + { + super(ctx, 0, trxName); + setM_Attribute_ID (M_Attribute_ID); + setM_AttributeSetInstance_ID (M_AttributeSetInstance_ID); + setValueNumber(BDValue); + } // MAttributeInstance + + /** + * Selection Value Constructior + * @param ctx context + * @param M_Attribute_ID attribute + * @param M_AttributeSetInstance_ID instance + * @param M_AttributeValue_ID selection + * @param Value String representation for fast display + * @param trxName transaction + */ + public MAttributeInstance (Properties ctx, int M_Attribute_ID, + int M_AttributeSetInstance_ID, int M_AttributeValue_ID, String Value, String trxName) + { + super(ctx, 0, trxName); + setM_Attribute_ID (M_Attribute_ID); + setM_AttributeSetInstance_ID (M_AttributeSetInstance_ID); + setM_AttributeValue_ID (M_AttributeValue_ID); + setValue (Value); + } // MAttributeInstance + + + /** + * Set ValueNumber + * @param ValueNumber number + */ + public void setValueNumber (BigDecimal ValueNumber) + { + super.setValueNumber (ValueNumber); + if (ValueNumber == null) + { + setValue(null); + return; + } + if (ValueNumber.signum() == 0) + { + setValue("0"); + return; + } + // Display number w/o decimal 0 + char[] chars = ValueNumber.toString().toCharArray(); + StringBuffer display = new StringBuffer(); + boolean add = false; + for (int i = chars.length-1; i >= 0; i--) + { + char c = chars[i]; + if (add) + display.insert(0, c); + else + { + if (c == '0') + continue; + else if (c == '.') // decimal point + add = true; + else + { + display.insert(0, c); + add = true; + } + } + } + setValue(display.toString()); + } // setValueNumber + + + /** + * String Representation + * @return info + */ + public String toString() + { + return getValue(); + } // toString + +} // MAttributeInstance diff --git a/base/src/org/compiere/model/MAttributeSet.java b/base/src/org/compiere/model/MAttributeSet.java new file mode 100644 index 0000000000..9365f04064 --- /dev/null +++ b/base/src/org/compiere/model/MAttributeSet.java @@ -0,0 +1,489 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Product Attribute Set + * + * @author Jorg Janke + * @version $Id: MAttributeSet.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MAttributeSet extends X_M_AttributeSet +{ + /** + * Get MAttributeSet from Cache + * @param ctx context + * @param M_AttributeSet_ID id + * @return MAttributeSet + */ + public static MAttributeSet get (Properties ctx, int M_AttributeSet_ID) + { + Integer key = new Integer (M_AttributeSet_ID); + MAttributeSet retValue = (MAttributeSet) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MAttributeSet (ctx, M_AttributeSet_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache + = new CCache ("M_AttributeSet", 20); + + + /** + * Standard constructor + * @param ctx context + * @param M_AttributeSet_ID id + * @param trxName transaction + */ + public MAttributeSet (Properties ctx, int M_AttributeSet_ID, String trxName) + { + super (ctx, M_AttributeSet_ID, trxName); + if (M_AttributeSet_ID == 0) + { + // setName (null); + setIsGuaranteeDate (false); + setIsGuaranteeDateMandatory (false); + setIsLot (false); + setIsLotMandatory (false); + setIsSerNo (false); + setIsSerNoMandatory (false); + setIsInstanceAttribute(false); + setMandatoryType (MANDATORYTYPE_NotMandatary); + } + } // MAttributeSet + + /** + * Load constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MAttributeSet (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAttributeSet + + /** Instance Attributes */ + private MAttribute[] m_instanceAttributes = null; + /** Instance Attributes */ + private MAttribute[] m_productAttributes = null; + + /** Entry Exclude */ + private X_M_AttributeSetExclude[] m_excludes = null; + /** Lot create Exclude */ + private X_M_LotCtlExclude[] m_excludeLots = null; + /** Serial No create Exclude */ + private X_M_SerNoCtlExclude[] m_excludeSerNos = null; + + /** + * Get Attribute Array + * @param instanceAttributes true if for instance + * @return instance or product attribute array + */ + public MAttribute[] getMAttributes (boolean instanceAttributes) + { + if ((m_instanceAttributes == null && instanceAttributes) + || m_productAttributes == null && !instanceAttributes) + { + String sql = "SELECT mau.M_Attribute_ID " + + "FROM M_AttributeUse mau" + + " INNER JOIN M_Attribute ma ON (mau.M_Attribute_ID=ma.M_Attribute_ID) " + + "WHERE mau.IsActive='Y' AND ma.IsActive='Y'" + + " AND mau.M_AttributeSet_ID=? AND ma.IsInstanceAttribute=? " // #1,2 + + "ORDER BY mau.SeqNo"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getM_AttributeSet_ID()); + pstmt.setString(2, instanceAttributes ? "Y" : "N"); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + MAttribute ma = new MAttribute (getCtx(), rs.getInt(1), get_TrxName()); + list.add (ma); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close(); + } + catch (SQLException ex1) + { + } + pstmt = null; + + // Differentiate attributes + if (instanceAttributes) + { + m_instanceAttributes = new MAttribute[list.size()]; + list.toArray (m_instanceAttributes); + } + else + { + m_productAttributes = new MAttribute[list.size()]; + list.toArray (m_productAttributes); + } + } + // + if (instanceAttributes) + { + if (isInstanceAttribute() != m_instanceAttributes.length > 0) + setIsInstanceAttribute(m_instanceAttributes.length > 0); + } + + // Return + if (instanceAttributes) + return m_instanceAttributes; + return m_productAttributes; + } // getMAttributes + + /** + * Something is Mandatory + * @return true if something is mandatory + */ + public boolean isMandatory() + { + return !MANDATORYTYPE_NotMandatary.equals(getMandatoryType()) + || isLotMandatory() + || isSerNoMandatory() + || isGuaranteeDateMandatory(); + } // isMandatory + + /** + * Is always mandatory + * @return mandatory + */ + public boolean isMandatoryAlways() + { + return MANDATORYTYPE_AlwaysMandatory.equals(getMandatoryType()); + } // isMandatoryAlways + + /** + * Is Mandatory when Shipping + * @return true if required for shipping + */ + public boolean isMandatoryShipping() + { + return MANDATORYTYPE_WhenShipping.equals(getMandatoryType()); + } // isMandatoryShipping + + /** + * Exclude entry + * @param AD_Column_ID column + * @param isSOTrx sales order + * @return true if excluded + */ + public boolean excludeEntry (int AD_Column_ID, boolean isSOTrx) + { + if (m_excludes == null) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_AttributeSetExclude WHERE IsActive='Y' AND M_AttributeSet_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getM_AttributeSet_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new X_M_AttributeSetExclude (getCtx(), rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_excludes = new X_M_AttributeSetExclude[list.size ()]; + list.toArray (m_excludes); + } + // Find it + if (m_excludes != null && m_excludes.length > 0) + { + MColumn column = MColumn.get(getCtx(), AD_Column_ID); + for (int i = 0; i < m_excludes.length; i++) + { + if (m_excludes[i].getAD_Table_ID() == column.getAD_Table_ID() + && m_excludes[i].isSOTrx() == isSOTrx) + return true; + } + } + return false; + } // excludeEntry + + /** + * Exclude Lot creation + * @param AD_Column_ID column + * @param isSOTrx SO + * @return true if excluded + */ + public boolean isExcludeLot (int AD_Column_ID, boolean isSOTrx) + { + if (getM_LotCtl_ID() == 0) + return true; + if (m_excludeLots == null) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_LotCtlExclude WHERE IsActive='Y' AND M_LotCtl_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getM_LotCtl_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new X_M_LotCtlExclude (getCtx(), rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_excludeLots = new X_M_LotCtlExclude[list.size ()]; + list.toArray (m_excludeLots); + } + // Find it + if (m_excludeLots != null && m_excludeLots.length > 0) + { + MColumn column = MColumn.get(getCtx(), AD_Column_ID); + for (int i = 0; i < m_excludeLots.length; i++) + { + if (m_excludeLots[i].getAD_Table_ID() == column.getAD_Table_ID() + && m_excludeLots[i].isSOTrx() == isSOTrx) + return true; + } + } + return false; + } // isExcludeLot + + /** + * Exclude SerNo creation + * @param AD_Column_ID column + * @param isSOTrx SO + * @return true if excluded + */ + public boolean isExcludeSerNo (int AD_Column_ID, boolean isSOTrx) + { + if (getM_SerNoCtl_ID() == 0) + return true; + if (m_excludeSerNos == null) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_SerNoCtlExclude WHERE IsActive='Y' AND M_SerNoCtl_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getM_SerNoCtl_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new X_M_SerNoCtlExclude (getCtx(), rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_excludeSerNos = new X_M_SerNoCtlExclude[list.size ()]; + list.toArray (m_excludeSerNos); + } + // Find it + if (m_excludeSerNos != null && m_excludeSerNos.length > 0) + { + MColumn column = MColumn.get(getCtx(), AD_Column_ID); + for (int i = 0; i < m_excludeSerNos.length; i++) + { + if (m_excludeSerNos[i].getAD_Table_ID() == column.getAD_Table_ID() + && m_excludeSerNos[i].isSOTrx() == isSOTrx) + return true; + } + } + return false; + } // isExcludeSerNo + + /** + * Get Lot Char Start + * @return defined or \u00ab + */ + public String getLotCharStart() + { + String s = super.getLotCharSOverwrite (); + if (s != null && s.length() == 1 && !s.equals(" ")) + return s; + return "\u00ab"; + } // getLotCharStart + + /** + * Get Lot Char End + * @return defined or \u00bb + */ + public String getLotCharEnd() + { + String s = super.getLotCharEOverwrite (); + if (s != null && s.length() == 1 && !s.equals(" ")) + return s; + return "\u00bb"; + } // getLotCharEnd + + /** + * Get SerNo Char Start + * @return defined or # + */ + public String getSerNoCharStart() + { + String s = super.getSerNoCharSOverwrite (); + if (s != null && s.length() == 1 && !s.equals(" ")) + return s; + return "#"; + } // getSerNoCharStart + + /** + * Get SerNo Char End + * @return defined or none + */ + public String getSerNoCharEnd() + { + String s = super.getSerNoCharEOverwrite (); + if (s != null && s.length() == 1 && !s.equals(" ")) + return s; + return ""; + } // getSerNoCharEnd + + + /** + * Before Save. + * - set instance attribute flag + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (!isInstanceAttribute() + && (isSerNo() || isLot() || isGuaranteeDate()) ) + setIsInstanceAttribute(true); + return true; + } // beforeSave + + + /** + * After Save. + * - Verify Instance Attribute + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + // Set Instance Attribute + if (!isInstanceAttribute()) + { + String sql = "UPDATE M_AttributeSet mas" + + " SET IsInstanceAttribute='Y' " + + "WHERE M_AttributeSet_ID=" + getM_AttributeSet_ID() + + " AND IsInstanceAttribute='N'" + + " AND (IsSerNo='Y' OR IsLot='Y' OR IsGuaranteeDate='Y'" + + " OR EXISTS (SELECT * FROM M_AttributeUse mau" + + " INNER JOIN M_Attribute ma ON (mau.M_Attribute_ID=ma.M_Attribute_ID) " + + "WHERE mau.M_AttributeSet_ID=mas.M_AttributeSet_ID" + + " AND mau.IsActive='Y' AND ma.IsActive='Y'" + + " AND ma.IsInstanceAttribute='Y')" + + ")"; + int no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + { + log.warning("Set Instance Attribute"); + setIsInstanceAttribute(true); + } + } + // Reset Instance Attribute + if (isInstanceAttribute() && !isSerNo() && !isLot() && !isGuaranteeDate()) + { + String sql = "UPDATE M_AttributeSet mas" + + " SET IsInstanceAttribute='N' " + + "WHERE M_AttributeSet_ID=" + getM_AttributeSet_ID() + + " AND IsInstanceAttribute='Y'" + + " AND IsSerNo='N' AND IsLot='N' AND IsGuaranteeDate='N'" + + " AND NOT EXISTS (SELECT * FROM M_AttributeUse mau" + + " INNER JOIN M_Attribute ma ON (mau.M_Attribute_ID=ma.M_Attribute_ID) " + + "WHERE mau.M_AttributeSet_ID=mas.M_AttributeSet_ID" + + " AND mau.IsActive='Y' AND ma.IsActive='Y'" + + " AND ma.IsInstanceAttribute='Y')"; + int no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + { + log.warning("Reset Instance Attribute"); + setIsInstanceAttribute(false); + } + } + return success; + } // afterSave + +} // MAttributeSet diff --git a/base/src/org/compiere/model/MAttributeSetInstance.java b/base/src/org/compiere/model/MAttributeSetInstance.java new file mode 100644 index 0000000000..8f8abec07f --- /dev/null +++ b/base/src/org/compiere/model/MAttributeSetInstance.java @@ -0,0 +1,342 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.text.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Product Attribute Set Instance + * + * @author Jorg Janke + * @version $Id: MAttributeSetInstance.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MAttributeSetInstance extends X_M_AttributeSetInstance +{ + /** + * Get Attribute Set Instance from ID or Product + * @param ctx context + * @param M_AttributeSetInstance_ID id or 0 + * @param M_Product_ID required if id is 0 + * @return Attribute Set Instance or null + */ + public static MAttributeSetInstance get (Properties ctx, + int M_AttributeSetInstance_ID, int M_Product_ID) + { + MAttributeSetInstance retValue = null; + // Load Instance if not 0 + if (M_AttributeSetInstance_ID != 0) + { + s_log.fine("From M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID); + return new MAttributeSetInstance (ctx, M_AttributeSetInstance_ID, null); + } + // Get new from Product + s_log.fine("From M_Product_ID=" + M_Product_ID); + if (M_Product_ID == 0) + return null; + String sql = "SELECT M_AttributeSet_ID, M_AttributeSetInstance_ID " + + "FROM M_Product " + + "WHERE M_Product_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, M_Product_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + int M_AttributeSet_ID = rs.getInt(1); + // M_AttributeSetInstance_ID = rs.getInt(2); // needed ? + // + retValue = new MAttributeSetInstance (ctx, 0, M_AttributeSet_ID, null); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + s_log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close(); + } + catch (SQLException ex1) + { + } + pstmt = null; + // + return retValue; + } // get + + private static CLogger s_log = CLogger.getCLogger (MAttributeSetInstance.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_AttributeSetInstance_ID id + * @param trxName transaction + */ + public MAttributeSetInstance (Properties ctx, int M_AttributeSetInstance_ID, String trxName) + { + super (ctx, M_AttributeSetInstance_ID, trxName); + if (M_AttributeSetInstance_ID == 0) + { + } + } // MAttributeSetInstance + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MAttributeSetInstance (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAttributeSetInstance + + /** + * Standard Constructor + * @param ctx context + * @param M_AttributeSetInstance_ID id + * @param M_AttributeSet_ID attribute set + * @param trxName transaction + */ + public MAttributeSetInstance (Properties ctx, int M_AttributeSetInstance_ID, + int M_AttributeSet_ID, String trxName) + { + this (ctx, M_AttributeSetInstance_ID, trxName); + setM_AttributeSet_ID(M_AttributeSet_ID); + } // MAttributeSetInstance + + /** Attribute Set */ + private MAttributeSet m_mas = null; + /** Date Format */ + private DateFormat m_dateFormat = DisplayType.getDateFormat(DisplayType.Date); + + /** + * Set Attribute Set + * @param mas attribute set + */ + public void setMAttributeSet (MAttributeSet mas) + { + m_mas = mas; + setM_AttributeSet_ID(mas.getM_AttributeSet_ID()); + } // setAttributeSet + + /** + * Get Attribute Set + * @return Attrbute Set or null + */ + public MAttributeSet getMAttributeSet() + { + if (m_mas == null && getM_AttributeSet_ID() != 0) + m_mas = new MAttributeSet (getCtx(), getM_AttributeSet_ID(), get_TrxName()); + return m_mas; + } // getMAttributeSet + + /** + * Set Description. + * - Product Values + * - Instance Values + * - SerNo = #123 + * - Lot = \u00ab123\u00bb + * - GuaranteeDate = 10/25/2003 + */ + public void setDescription() + { + // Make sure we have a Attribute Set + getMAttributeSet(); + if (m_mas == null) + { + setDescription (""); + return; + } + + StringBuffer sb = new StringBuffer(); + + // Instance Attribute Values + MAttribute[] attributes = m_mas.getMAttributes(true); + for (int i = 0; i < attributes.length; i++) + { + MAttributeInstance mai = attributes[i].getMAttributeInstance(getM_AttributeSetInstance_ID()); + if (mai != null && mai.getValue() != null) + { + if (sb.length() > 0) + sb.append("_"); + sb.append(mai.getValue()); + } + } + // SerNo + if (m_mas.isSerNo() && getSerNo() != null) + { + if (sb.length() > 0) + sb.append("_"); + sb.append(m_mas.getSerNoCharStart()).append(getSerNo()).append(m_mas.getSerNoCharEnd()); + } + // Lot + if (m_mas.isLot() && getLot() != null) + { + if (sb.length() > 0) + sb.append("_"); + sb.append(m_mas.getLotCharStart()).append(getLot()).append(m_mas.getLotCharEnd()); + } + // GuaranteeDate + if (m_mas.isGuaranteeDate() && getGuaranteeDate() != null) + { + if (sb.length() > 0) + sb.append("_"); + sb.append (m_dateFormat.format(getGuaranteeDate())); + } + + // Product Attribute Values + attributes = m_mas.getMAttributes(false); + for (int i = 0; i < attributes.length; i++) + { + MAttributeInstance mai = attributes[i].getMAttributeInstance(getM_AttributeSetInstance_ID()); + if (mai != null && mai.getValue() != null) + { + if (sb.length() > 0) + sb.append("_"); + sb.append(mai.getValue()); + } + } + setDescription (sb.toString()); + } // setDescription + + + /** + * Get Guarantee Date + * @param getNew if true calculates/sets guarantee date + * @return guarantee date or null if days = 0 + */ + public Timestamp getGuaranteeDate(boolean getNew) + { + if (getNew) + { + int days = getMAttributeSet().getGuaranteeDays(); + if (days > 0) + { + Timestamp ts = TimeUtil.addDays(new Timestamp(System.currentTimeMillis()), days); + setGuaranteeDate(ts); + } + } + return getGuaranteeDate(); + } // getGuaranteeDate + + /** + * Get Lot No + * @param getNew if true create/set new lot + * @param M_Product_ID product used if new + * @return lot + */ + public String getLot (boolean getNew, int M_Product_ID) + { + if (getNew) + createLot(M_Product_ID); + return getLot(); + } // getLot + + /** + * Create Lot + * @param M_Product_ID product used if new + * @return lot info + */ + public KeyNamePair createLot (int M_Product_ID) + { + KeyNamePair retValue = null; + int M_LotCtl_ID = getMAttributeSet().getM_LotCtl_ID(); + if (M_LotCtl_ID != 0) + { + MLotCtl ctl = new MLotCtl (getCtx(), M_LotCtl_ID, null); + MLot lot = ctl.createLot(M_Product_ID); + setM_Lot_ID (lot.getM_Lot_ID()); + setLot (lot.getName()); + retValue = new KeyNamePair (lot.getM_Lot_ID(), lot.getName()); + } + return retValue; + } // createLot + + /** + * To to find lot and set Lot/ID + * @param Lot lot + * @param M_Product_ID product + */ + public void setLot (String Lot, int M_Product_ID) + { + // Try to find it + MLot mLot = MLot.getProductLot(getCtx(), M_Product_ID, Lot, get_TrxName()); + if (mLot != null) + setM_Lot_ID(mLot.getM_Lot_ID()); + setLot (Lot); + } // setLot + + /** + * Exclude Lot creation + * @param AD_Column_ID column + * @param isSOTrx SO + * @return true if excluded + */ + public boolean isExcludeLot (int AD_Column_ID, boolean isSOTrx) + { + getMAttributeSet(); + if (m_mas != null) + return m_mas.isExcludeLot (AD_Column_ID, isSOTrx); + return false; + } // isExcludeLot + + /** + * Get Serial No + * @param getNew if true create/set new Ser No + * @return Serial Number + */ + public String getSerNo (boolean getNew) + { + if (getNew) + { + int M_SerNoCtl_ID = getMAttributeSet().getM_SerNoCtl_ID(); + if (M_SerNoCtl_ID != 0) + { + MSerNoCtl ctl = new MSerNoCtl (getCtx(), M_SerNoCtl_ID, get_TrxName()); + setSerNo(ctl.createSerNo()); + } + } + return getSerNo(); + } // getSerNo + + /** + * Exclude SerNo creation + * @param AD_Column_ID column + * @param isSOTrx SO + * @return true if excluded + */ + public boolean isExcludeSerNo (int AD_Column_ID, boolean isSOTrx) + { + getMAttributeSet(); + if (m_mas != null) + return m_mas.isExcludeSerNo (AD_Column_ID, isSOTrx); + return false; + } // isExcludeSerNo + +} // MAttributeSetInstance diff --git a/base/src/org/compiere/model/MAttributeUse.java b/base/src/org/compiere/model/MAttributeUse.java new file mode 100644 index 0000000000..f95280c46c --- /dev/null +++ b/base/src/org/compiere/model/MAttributeUse.java @@ -0,0 +1,110 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + + +/** + * Attribute Use Model + * + * @author Jorg Janke + * @version $Id: MAttributeUse.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MAttributeUse extends X_M_AttributeUse +{ + /** + * Persistency Constructor + * @param ctx context + * @param ignored ignored + * @param trxName transaction + */ + public MAttributeUse (Properties ctx, int ignored, String trxName) + { + super (ctx, ignored, trxName); + if (ignored != 0) + throw new IllegalArgumentException("Multi-Key"); + } // MAttributeUse + + /** + * Load Cosntructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MAttributeUse (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAttributeUse + + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + // also used for afterDelete + String sql = "UPDATE M_AttributeSet mas" + + " SET IsInstanceAttribute='Y' " + + "WHERE M_AttributeSet_ID=" + getM_AttributeSet_ID() + + " AND IsInstanceAttribute='N'" + + " AND (IsSerNo='Y' OR IsLot='Y' OR IsGuaranteeDate='Y'" + + " OR EXISTS (SELECT * FROM M_AttributeUse mau" + + " INNER JOIN M_Attribute ma ON (mau.M_Attribute_ID=ma.M_Attribute_ID) " + + "WHERE mau.M_AttributeSet_ID=mas.M_AttributeSet_ID" + + " AND mau.IsActive='Y' AND ma.IsActive='Y'" + + " AND ma.IsInstanceAttribute='Y')" + + ")"; + int no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("afterSave - Set Instance Attribute"); + // + sql = "UPDATE M_AttributeSet mas" + + " SET IsInstanceAttribute='N' " + + "WHERE M_AttributeSet_ID=" + getM_AttributeSet_ID() + + " AND IsInstanceAttribute='Y'" + + " AND IsSerNo='N' AND IsLot='N' AND IsGuaranteeDate='N'" + + " AND NOT EXISTS (SELECT * FROM M_AttributeUse mau" + + " INNER JOIN M_Attribute ma ON (mau.M_Attribute_ID=ma.M_Attribute_ID) " + + "WHERE mau.M_AttributeSet_ID=mas.M_AttributeSet_ID" + + " AND mau.IsActive='Y' AND ma.IsActive='Y'" + + " AND ma.IsInstanceAttribute='Y')"; + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("afterSave - Reset Instance Attribute"); + + return success; + } // afterSave + + + /** + * After Delete + * @param success success + * @return success + */ + protected boolean afterDelete (boolean success) + { + afterSave(false, success); + return success; + } // afterDelete + +} // MAttributeUse diff --git a/base/src/org/compiere/model/MAttributeValue.java b/base/src/org/compiere/model/MAttributeValue.java new file mode 100644 index 0000000000..460d784d82 --- /dev/null +++ b/base/src/org/compiere/model/MAttributeValue.java @@ -0,0 +1,69 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.util.*; +import java.sql.*; + +/** + * Product Attribute Value + * + * @author Jorg Janke + * @version $Id: MAttributeValue.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MAttributeValue extends X_M_AttributeValue +{ + /** + * Constructor + * @param ctx context + * @param M_AttributeValue_ID id + * @param trxName transaction + */ + public MAttributeValue (Properties ctx, int M_AttributeValue_ID, String trxName) + { + super (ctx, M_AttributeValue_ID, trxName); + /** if (M_AttributeValue_ID == 0) + { + setM_AttributeValue_ID (0); + setM_Attribute_ID (0); + setName (null); + setValue (null); + } + **/ + } // MAttributeValue + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MAttributeValue (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MAttributeValue + + /** + * String Representation + * @return info + */ + public String toString() + { + return getName(); + } // toString + +} // MAttributeValue diff --git a/base/src/org/compiere/model/MBOM.java b/base/src/org/compiere/model/MBOM.java new file mode 100644 index 0000000000..2df26de019 --- /dev/null +++ b/base/src/org/compiere/model/MBOM.java @@ -0,0 +1,178 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * BOM Model + * @author Jorg Janke + * @version $Id: MBOM.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MBOM extends X_M_BOM +{ + /** + * Get BOM from Cache + * @param ctx context + * @param M_BOM_ID id + * @return MBOM + */ + public static MBOM get (Properties ctx, int M_BOM_ID) + { + Integer key = new Integer (M_BOM_ID); + MBOM retValue = (MBOM) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MBOM (ctx, M_BOM_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** + * Get BOMs Of Product + * @param ctx context + * @param M_Product_ID product + * @param trxName trx + * @param whereClause optional WHERE clause w/o AND + * @return array of BOMs + */ + public static MBOM[] getOfProduct (Properties ctx, int M_Product_ID, + String trxName, String whereClause) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_BOM WHERE M_Product_ID=?"; + if (whereClause != null && whereClause.length() > 0) + sql += " AND " + whereClause; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_Product_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MBOM (ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + MBOM[] retValue = new MBOM[list.size ()]; + list.toArray (retValue); + return retValue; + } // getOfProduct + + /** Cache */ + private static CCache s_cache + = new CCache("M_BOM", 20); + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MBOM.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_BOM_ID id + * @param trxName trx + */ + public MBOM (Properties ctx, int M_BOM_ID, String trxName) + { + super (ctx, M_BOM_ID, trxName); + if (M_BOM_ID == 0) + { + // setM_Product_ID (0); + // setName (null); + setBOMType (BOMTYPE_CurrentActive); // A + setBOMUse (BOMUSE_Master); // A + } + } // MBOM + + /** + * Load Constructor + * @param ctx ctx + * @param rs result set + * @param trxName trx + */ + public MBOM (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MBOM + + /** + * Before Save + * @param newRecord new + * @return true/false + */ + protected boolean beforeSave (boolean newRecord) + { + // BOM Type + if (newRecord || is_ValueChanged("BOMType")) + { + // Only one Current Active + if (getBOMType().equals(BOMTYPE_CurrentActive)) + { + MBOM[] boms = getOfProduct(getCtx(), getM_Product_ID(), get_TrxName(), + "BOMType='A' AND BOMUse='" + getBOMUse() + "' AND IsActive='Y'"); + if (boms.length == 0 // only one = this + || (boms.length == 1 && boms[0].getM_BOM_ID() == getM_BOM_ID())) + ; + else + { + log.saveError("Error", Msg.parseTranslation(getCtx(), + "Can only have one Current Active BOM for Product BOM Use (" + getBOMType() + ")")); + return false; + } + } + // Only one MTO + else if (getBOMType().equals(BOMTYPE_Make_To_Order)) + { + MBOM[] boms = getOfProduct(getCtx(), getM_Product_ID(), get_TrxName(), + "IsActive='Y'"); + if (boms.length == 0 // only one = this + || (boms.length == 1 && boms[0].getM_BOM_ID() == getM_BOM_ID())) + ; + else + { + log.saveError("Error", Msg.parseTranslation(getCtx(), + "Can only have single Make-to-Order BOM for Product")); + return false; + } + } + } // BOM Type + + return true; + } // beforeSave + +} // MBOM diff --git a/base/src/org/compiere/model/MBOMProduct.java b/base/src/org/compiere/model/MBOMProduct.java new file mode 100644 index 0000000000..c6302ed6d8 --- /dev/null +++ b/base/src/org/compiere/model/MBOMProduct.java @@ -0,0 +1,215 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * BOM Product/Component Model + * + * @author Jorg Janke + * @version $Id: MBOMProduct.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MBOMProduct extends X_M_BOMProduct +{ + /** + * Get Products of BOM + * @param bom bom + * @return array of BOM Products + */ + public static MBOMProduct[] getOfBOM (MBOM bom) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_BOMProduct WHERE M_BOM_ID=? ORDER BY SeqNo"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, bom.get_TrxName()); + pstmt.setInt (1, bom.getM_BOM_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MBOMProduct (bom.getCtx(), rs, bom.get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + MBOMProduct[] retValue = new MBOMProduct[list.size ()]; + list.toArray (retValue); + return retValue; + } // getOfProduct + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MBOMProduct.class); + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_BOMProduct_ID id + * @param trxName trx + */ + public MBOMProduct (Properties ctx, int M_BOMProduct_ID, String trxName) + { + super (ctx, M_BOMProduct_ID, trxName); + if (M_BOMProduct_ID == 0) + { + // setM_BOM_ID (0); + setBOMProductType (BOMPRODUCTTYPE_StandardProduct); // S + setBOMQty (Env.ONE); + setIsPhantom (false); + setLeadTimeOffset (0); + // setLine (0); // @SQL=SELECT NVL(MAX(Line),0)+10 AS DefaultValue FROM M_BOMProduct WHERE M_BOM_ID=@M_BOM_ID@ + } + } // MBOMProduct + + /** + * Parent Constructor + * @param bom product + */ + public MBOMProduct (MBOM bom) + { + this (bom.getCtx(), 0, bom.get_TrxName()); + m_bom = bom; + } // MBOMProduct + + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MBOMProduct (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MBOMProduct + + /** BOM Parent */ + private MBOM m_bom = null; + + /** + * Get Parent + * @return parent + */ + private MBOM getBOM() + { + if (m_bom == null && getM_BOM_ID() != 0) + m_bom = MBOM.get(getCtx(), getM_BOM_ID()); + return m_bom; + } // getBOM + + + /** + * Before Save + * @param newRecord new + * @return true/false + */ + protected boolean beforeSave (boolean newRecord) + { + // Product + if (getBOMProductType().equals(BOMPRODUCTTYPE_OutsideProcessing)) + { + if (getM_ProductBOM_ID() != 0) + setM_ProductBOM_ID(0); + } + else if (getM_ProductBOM_ID() == 0) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@NotFound@ @M_ProductBOM_ID@")); + return false; + } + // Operation + if (getM_ProductOperation_ID() == 0) + { + if (getSeqNo() != 0) + setSeqNo(0); + } + else if (getSeqNo() == 0) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@NotFound@ @SeqNo@")); + return false; + } + // Product Attribute Instance + if (getM_AttributeSetInstance_ID() != 0) + { + getBOM(); + if (m_bom != null + && MBOM.BOMTYPE_Make_To_Order.equals(m_bom.getBOMType())) + ; + else + { + log.saveError("Error", Msg.parseTranslation(getCtx(), + "Reset @M_AttributeSetInstance_ID@: Not Make-to-Order")); + setM_AttributeSetInstance_ID(0); + return false; + } + } + // Alternate + if ((getBOMProductType().equals(BOMPRODUCTTYPE_Alternative) + || getBOMProductType().equals(BOMPRODUCTTYPE_AlternativeDefault)) + && getM_BOMAlternative_ID() == 0) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@NotFound@ @M_BOMAlternative_ID@")); + return false; + } + // Operation + if (getM_ProductOperation_ID() != 0) + { + if (getSeqNo() == 0) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@NotFound@ @SeqNo@")); + return false; + } + } + else // no op + { + if (getSeqNo() != 0) + setSeqNo(0); + if (getLeadTimeOffset() != 0) + setLeadTimeOffset(0); + } + + // Set Line Number + if (getLine() == 0) + { + String sql = "SELECT NVL(MAX(Line),0)+10 FROM M_BOMProduct WHERE M_BOM_ID=?"; + int ii = DB.getSQLValue (get_TrxName(), sql, getM_BOM_ID()); + setLine (ii); + } + + return true; + } // beforeSave + + +} // MBOMProduct diff --git a/base/src/org/compiere/model/MBPBankAccount.java b/base/src/org/compiere/model/MBPBankAccount.java new file mode 100644 index 0000000000..2d86be58a2 --- /dev/null +++ b/base/src/org/compiere/model/MBPBankAccount.java @@ -0,0 +1,97 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * BP Bank Account Model + * + * @author Jorg Janke + * @version $Id: MBPBankAccount.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MBPBankAccount extends X_C_BP_BankAccount +{ + /** + * Constructor + * @param ctx context + * @param C_BP_BankAccount_ID BP bank account + * @param trxName transaction + */ + public MBPBankAccount (Properties ctx, int C_BP_BankAccount_ID, String trxName) + { + super (ctx, C_BP_BankAccount_ID, trxName); + if (C_BP_BankAccount_ID == 0) + { + // setC_BPartner_ID (0); + setIsACH (false); + } + } // MBP_BankAccount + + /** + * Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MBPBankAccount (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MBP_BankAccount + + /** + * Constructor + * @param ctx context + * @param bp BP + * @param bpc BP Contact + * @param location Location + */ + public MBPBankAccount (Properties ctx, MBPartner bp, MUser bpc, MLocation location) + { + super(ctx, 0, bp.get_TrxName()); + setIsACH (false); + // + setC_BPartner_ID(bp.getC_BPartner_ID()); + // + setA_Name(bpc.getName()); + setA_EMail(bpc.getEMail()); + // + setA_Street(location.getAddress1()); + setA_City(location.getCity()); + setA_Zip(location.getPostal()); + setA_State(location.getRegionName(true)); + setA_Country(location.getCountryName()); + } // MBP_BankAccount + + + /*************************************************************************/ + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MBP_BankAccount[") + .append (get_ID ()) + .append(", Name=").append(getA_Name()) + .append ("]"); + return sb.toString (); + } // toString + +} // MBPBankAccount diff --git a/base/src/org/compiere/model/MBPGroup.java b/base/src/org/compiere/model/MBPGroup.java new file mode 100644 index 0000000000..f14cd0f233 --- /dev/null +++ b/base/src/org/compiere/model/MBPGroup.java @@ -0,0 +1,245 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Business Partner Group Model + * + * @author Jorg Janke + * @version $Id: MBPGroup.java,v 1.4 2006/09/23 15:54:22 jjanke Exp $ + */ +public class MBPGroup extends X_C_BP_Group +{ + /** + * Get MBPGroup from Cache + * @param ctx context + * @param C_BP_Group_ID id + * @return MBPGroup + */ + public static MBPGroup get (Properties ctx, int C_BP_Group_ID) + { + Integer key = new Integer (C_BP_Group_ID); + MBPGroup retValue = (MBPGroup) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MBPGroup (ctx, C_BP_Group_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** + * Get Default MBPGroup + * @param ctx context + * @return MBPGroup + */ + public static MBPGroup getDefault (Properties ctx) + { + int AD_Client_ID = Env.getAD_Client_ID(ctx); + Integer key = new Integer (AD_Client_ID); + MBPGroup retValue = (MBPGroup) s_cacheDefault.get (key); + if (retValue != null) + return retValue; + + PreparedStatement pstmt = null; + String sql = "SELECT * FROM C_BP_Group g " + + "WHERE IsDefault='Y' AND AD_Client_ID=? " + + "ORDER BY IsActive DESC"; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, AD_Client_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + retValue = new MBPGroup (ctx, rs, null); + if (retValue.get_ID () != 0) + s_cacheDefault.put (key, retValue); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (retValue == null) + s_log.warning("No Default BP Group for AD_Client_ID=" + AD_Client_ID); + return retValue; + } // get + + /** + * Get MBPGroup from Business Partner + * @param ctx context + * @param C_BPartner_ID business partner id + * @return MBPGroup + */ + public static MBPGroup getOfBPartner (Properties ctx, int C_BPartner_ID) + { + MBPGroup retValue = null; + PreparedStatement pstmt = null; + String sql = "SELECT * FROM C_BP_Group g " + + "WHERE EXISTS (SELECT * FROM C_BPartner p " + + "WHERE p.C_BPartner_ID=? AND p.C_BP_Group_ID=g.C_BP_Group_ID)"; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, C_BPartner_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + retValue = new MBPGroup (ctx, rs, null); + Integer key = new Integer (retValue.getC_BP_Group_ID()); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + return retValue; + } // getOfBPartner + + /** Cache */ + private static CCache s_cache + = new CCache("BP_Group", 10); + /** Default Cache */ + private static CCache s_cacheDefault + = new CCache("BP_Group", 5); + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MBPGroup.class); + + /** + * Standard Constructor + * @param ctx context + * @param C_BP_Group_ID id + * @param trxName transaction + */ + public MBPGroup (Properties ctx, int C_BP_Group_ID, String trxName) + { + super (ctx, C_BP_Group_ID, trxName); + if (C_BP_Group_ID == 0) + { + // setValue (null); + // setName (null); + setIsConfidentialInfo (false); // N + setIsDefault (false); + setPriorityBase(PRIORITYBASE_Same); + } + } // MBPGroup + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MBPGroup (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MBPGroup + + + /** + * Get Credit Watch Percent + * @return 90 or defined percent + */ + public BigDecimal getCreditWatchPercent () + { + BigDecimal bd = super.getCreditWatchPercent(); + if (bd != null) + return bd; + return new BigDecimal(90); + } // getCreditWatchPercent + + /** + * Get Credit Watch Ratio + * @return 0.90 or defined percent + */ + public BigDecimal getCreditWatchRatio() + { + BigDecimal bd = super.getCreditWatchPercent(); + if (bd != null) + return bd.divide(Env.ONEHUNDRED, 2, BigDecimal.ROUND_HALF_UP); + return new BigDecimal(0.90); + } // getCreditWatchRatio + + + @Override + protected boolean beforeSave (boolean newRecord) + { + // TODO Auto-generated method stub + return true; + } + + /** + * After Save + * @param newRecord new record + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (newRecord & success) + return insert_Accounting("C_BP_Group_Acct", "C_AcctSchema_Default", null); + return success; + } // afterSave + + + /** + * Before Delete + * @return true + */ + protected boolean beforeDelete () + { + return delete_Accounting("C_BP_Group_Acct"); + } // beforeDelete + +} // MBPGroup diff --git a/base/src/org/compiere/model/MBPartner.java b/base/src/org/compiere/model/MBPartner.java new file mode 100644 index 0000000000..6d9fc5d3c7 --- /dev/null +++ b/base/src/org/compiere/model/MBPartner.java @@ -0,0 +1,1096 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Business Partner Model + * + * @author Jorg Janke + * @version $Id: MBPartner.java,v 1.5 2006/09/23 19:38:07 comdivision Exp $ + */ +public class MBPartner extends X_C_BPartner +{ + /** + * Get Empty Template Business Partner + * @param ctx context + * @param AD_Client_ID client + * @return Template Business Partner or null + */ + public static MBPartner getTemplate (Properties ctx, int AD_Client_ID) + { + MBPartner template = getBPartnerCashTrx (ctx, AD_Client_ID); + if (template == null) + template = new MBPartner (ctx, 0, null); + // Reset + if (template != null) + { + template.set_ValueNoCheck ("C_BPartner_ID", new Integer(0)); + template.setValue (""); + template.setName (""); + template.setName2 (null); + template.setDUNS(""); + template.setFirstSale(null); + // + template.setSO_CreditLimit (Env.ZERO); + template.setSO_CreditUsed (Env.ZERO); + template.setTotalOpenBalance (Env.ZERO); + // s_template.setRating(null); + // + template.setActualLifeTimeValue(Env.ZERO); + template.setPotentialLifeTimeValue(Env.ZERO); + template.setAcqusitionCost(Env.ZERO); + template.setShareOfCustomer(0); + template.setSalesVolume(0); + } + return template; + } // getTemplate + + /** + * Get Cash Trx Business Partner + * @param ctx context + * @param AD_Client_ID client + * @return Cash Trx Business Partner or null + */ + public static MBPartner getBPartnerCashTrx (Properties ctx, int AD_Client_ID) + { + MBPartner retValue = null; + String sql = "SELECT * FROM C_BPartner " + + "WHERE C_BPartner_ID=(SELECT C_BPartnerCashTrx_ID FROM AD_ClientInfo WHERE AD_Client_ID=?)"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Client_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + retValue = new MBPartner (ctx, rs, null); + else + s_log.log(Level.SEVERE, "Not found for AD_Client_ID=" + AD_Client_ID); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + return retValue; + } // getBPartnerCashTrx + + /** + * Get BPartner with Value + * @param ctx context + * @param Value value + * @return BPartner or null + */ + public static MBPartner get (Properties ctx, String Value) + { + if (Value == null || Value.length() == 0) + return null; + MBPartner retValue = null; + int AD_Client_ID = Env.getAD_Client_ID(ctx); + String sql = "SELECT * FROM C_BPartner WHERE Value=? AND AD_Client_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setString(1, Value); + pstmt.setInt(2, AD_Client_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = new MBPartner(ctx, rs, null); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return retValue; + } // get + + /** + * Get BPartner with Value + * @param ctx context + * @param Value value + * @return BPartner or null + */ + public static MBPartner get (Properties ctx, int C_BPartner_ID) + { + MBPartner retValue = null; + int AD_Client_ID = Env.getAD_Client_ID(ctx); + String sql = "SELECT * FROM C_BPartner WHERE C_BPartner_ID=? AND AD_Client_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt(1, C_BPartner_ID); + pstmt.setInt(2, AD_Client_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = new MBPartner(ctx, rs, null); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return retValue; + } // get + + /** + * Get Not Invoiced Shipment Value + * @param C_BPartner_ID partner + * @return value in accounting currency + */ + public static BigDecimal getNotInvoicedAmt (int C_BPartner_ID) + { + BigDecimal retValue = null; + String sql = "SELECT SUM(COALESCE(" + + "currencyBase((ol.QtyDelivered-ol.QtyInvoiced)*ol.PriceActual,o.C_Currency_ID,o.DateOrdered, o.AD_Client_ID,o.AD_Org_ID) ,0)) " + + "FROM C_OrderLine ol" + + " INNER JOIN C_Order o ON (ol.C_Order_ID=o.C_Order_ID) " + + "WHERE o.IsSOTrx='Y' AND Bill_BPartner_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, C_BPartner_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = rs.getBigDecimal(1); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return retValue; + } // getNotInvoicedAmt + + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MBPartner.class); + + + /************************************************************************** + * Constructor for new BPartner from Template + * @param ctx context + */ + public MBPartner (Properties ctx) + { + this (ctx, -1, null); + } // MBPartner + + /** + * Default Constructor + * @param ctx context + * @param rs ResultSet to load from + * @param trxName transaction + */ + public MBPartner (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MBPartner + + /** + * Default Constructor + * @param ctx context + * @param C_BPartner_ID partner or 0 or -1 (load from template) + * @param trxName transaction + */ + public MBPartner (Properties ctx, int C_BPartner_ID, String trxName) + { + super (ctx, C_BPartner_ID, trxName); + // + if (C_BPartner_ID == -1) + { + initTemplate (Env.getContextAsInt(ctx, "AD_Client_ID")); + C_BPartner_ID = 0; + } + if (C_BPartner_ID == 0) + { + // setValue (""); + // setName (""); + // setName2 (null); + // setDUNS(""); + // + setIsCustomer (true); + setIsProspect (true); + // + setSendEMail (false); + setIsOneTime (false); + setIsVendor (false); + setIsSummary (false); + setIsEmployee (false); + setIsSalesRep (false); + setIsTaxExempt(false); + setIsDiscountPrinted(false); + // + setSO_CreditLimit (Env.ZERO); + setSO_CreditUsed (Env.ZERO); + setTotalOpenBalance (Env.ZERO); + setSOCreditStatus(SOCREDITSTATUS_NoCreditCheck); + // + setFirstSale(null); + setActualLifeTimeValue(Env.ZERO); + setPotentialLifeTimeValue(Env.ZERO); + setAcqusitionCost(Env.ZERO); + setShareOfCustomer(0); + setSalesVolume(0); + } + log.fine(toString()); + } // MBPartner + + /** + * Import Contstructor + * @param impBP import + */ + public MBPartner (X_I_BPartner impBP) + { + this (impBP.getCtx(), 0, impBP.get_TrxName()); + setClientOrg(impBP); + setUpdatedBy(impBP.getUpdatedBy()); + // + String value = impBP.getValue(); + if (value == null || value.length() == 0) + value = impBP.getEMail(); + if (value == null || value.length() == 0) + value = impBP.getContactName(); + setValue(value); + String name = impBP.getName(); + if (name == null || name.length() == 0) + name = impBP.getContactName(); + if (name == null || name.length() == 0) + name = impBP.getEMail(); + setName(name); + setName2(impBP.getName2()); + setDescription(impBP.getDescription()); + // setHelp(impBP.getHelp()); + setDUNS(impBP.getDUNS()); + setTaxID(impBP.getTaxID()); + setNAICS(impBP.getNAICS()); + setC_BP_Group_ID(impBP.getC_BP_Group_ID()); + } // MBPartner + + + /** Users */ + private MUser[] m_contacts = null; + /** Addressed */ + private MBPartnerLocation[] m_locations = null; + /** BP Bank Accounts */ + private MBPBankAccount[] m_accounts = null; + /** Prim Address */ + private Integer m_primaryC_BPartner_Location_ID = null; + /** Prim User */ + private Integer m_primaryAD_User_ID = null; + /** Credit Limit recently calcualted */ + private boolean m_TotalOpenBalanceSet = false; + /** BP Group */ + private MBPGroup m_group = null; + + /** + * Load Default BPartner + * @param AD_Client_ID client + * @return true if loaded + */ + private boolean initTemplate (int AD_Client_ID) + { + if (AD_Client_ID == 0) + throw new IllegalArgumentException ("Client_ID=0"); + + boolean success = true; + String sql = "SELECT * FROM C_BPartner " + + "WHERE C_BPartner_ID=(SELECT C_BPartnerCashTrx_ID FROM AD_ClientInfo WHERE AD_Client_ID=?)"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Client_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + success = load (rs); + else + { + load(0, null); + success = false; + log.severe ("None found"); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + setStandardDefaults(); + // Reset + set_ValueNoCheck ("C_BPartner_ID", I_ZERO); + setValue (""); + setName (""); + setName2(null); + return success; + } // getTemplate + + + /** + * Get All Contacts + * @param reload if true users will be requeried + * @return contacts + */ + public MUser[] getContacts (boolean reload) + { + if (reload || m_contacts == null || m_contacts.length == 0) + ; + else + return m_contacts; + // + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM AD_User WHERE C_BPartner_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MUser (getCtx(), rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + + m_contacts = new MUser[list.size()]; + list.toArray(m_contacts); + return m_contacts; + } // getContacts + + /** + * Get specified or first Contact + * @param AD_User_ID optional user + * @return contact or null + */ + public MUser getContact (int AD_User_ID) + { + MUser[] users = getContacts(false); + if (users.length == 0) + return null; + for (int i = 0; AD_User_ID != 0 && i < users.length; i++) + { + if (users[i].getAD_User_ID() == AD_User_ID) + return users[i]; + } + return users[0]; + } // getContact + + + /** + * Get All Locations + * @param reload if true locations will be requeried + * @return locations + */ + public MBPartnerLocation[] getLocations (boolean reload) + { + if (reload || m_locations == null || m_locations.length == 0) + ; + else + return m_locations; + // + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_BPartner_Location WHERE C_BPartner_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MBPartnerLocation (getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + + m_locations = new MBPartnerLocation[list.size()]; + list.toArray(m_locations); + return m_locations; + } // getLocations + + /** + * Get explicit or first bill Location + * @param C_BPartner_Location_ID optional explicit location + * @return location or null + */ + public MBPartnerLocation getLocation(int C_BPartner_Location_ID) + { + MBPartnerLocation[] locations = getLocations(false); + if (locations.length == 0) + return null; + MBPartnerLocation retValue = null; + for (int i = 0; i < locations.length; i++) + { + if (locations[i].getC_BPartner_Location_ID() == C_BPartner_Location_ID) + return locations[i]; + if (retValue == null && locations[i].isBillTo()) + retValue = locations[i]; + } + if (retValue == null) + return locations[0]; + return retValue; + } // getLocation + + + /** + * Get Bank Accounts + * @param requery requery + * @return Bank Accounts + */ + public MBPBankAccount[] getBankAccounts (boolean requery) + { + if (m_accounts != null && m_accounts.length >= 0 && !requery) // re-load + return m_accounts; + // + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_BP_BankAccount WHERE C_BPartner_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MBPBankAccount (getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + + m_accounts = new MBPBankAccount[list.size()]; + list.toArray(m_accounts); + return m_accounts; + } // getBankAccounts + + + /************************************************************************** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MBPartner[ID=") + .append(get_ID()) + .append(",Value=").append(getValue()) + .append(",Name=").append(getName()) + .append(",Open=").append(getTotalOpenBalance()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Set Client/Org + * @param AD_Client_ID client + * @param AD_Org_ID org + */ + public void setClientOrg (int AD_Client_ID, int AD_Org_ID) + { + super.setClientOrg(AD_Client_ID, AD_Org_ID); + } // setClientOrg + + /** + * Set Linked Organization. + * (is Button) + * @param AD_OrgBP_ID + */ + public void setAD_OrgBP_ID (int AD_OrgBP_ID) + { + if (AD_OrgBP_ID == 0) + super.setAD_OrgBP_ID (null); + else + super.setAD_OrgBP_ID (String.valueOf(AD_OrgBP_ID)); + } // setAD_OrgBP_ID + + /** + * Get Linked Organization. + * (is Button) + * The Business Partner is another Organization + * for explicit Inter-Org transactions + * @return AD_Org_ID if BP + */ + public int getAD_OrgBP_ID_Int() + { + String org = super.getAD_OrgBP_ID(); + if (org == null) + return 0; + int AD_OrgBP_ID = 0; + try + { + AD_OrgBP_ID = Integer.parseInt (org); + } + catch (Exception ex) + { + log.log(Level.SEVERE, org, ex); + } + return AD_OrgBP_ID; + } // getAD_OrgBP_ID_Int + + /** + * Get Primary C_BPartner_Location_ID + * @return C_BPartner_Location_ID + */ + public int getPrimaryC_BPartner_Location_ID() + { + if (m_primaryC_BPartner_Location_ID == null) + { + MBPartnerLocation[] locs = getLocations(false); + for (int i = 0; m_primaryC_BPartner_Location_ID == null && i < locs.length; i++) + { + if (locs[i].isBillTo()) + { + setPrimaryC_BPartner_Location_ID (locs[i].getC_BPartner_Location_ID()); + break; + } + } + // get first + if (m_primaryC_BPartner_Location_ID == null && locs.length > 0) + setPrimaryC_BPartner_Location_ID (locs[0].getC_BPartner_Location_ID()); + } + if (m_primaryC_BPartner_Location_ID == null) + return 0; + return m_primaryC_BPartner_Location_ID.intValue(); + } // getPrimaryC_BPartner_Location_ID + + /** + * Get Primary C_BPartner_Location + * @return C_BPartner_Location + */ + public MBPartnerLocation getPrimaryC_BPartner_Location() + { + if (m_primaryC_BPartner_Location_ID == null) + { + m_primaryC_BPartner_Location_ID = getPrimaryC_BPartner_Location_ID(); + } + if (m_primaryC_BPartner_Location_ID == null) + return null; + return new MBPartnerLocation(getCtx(), m_primaryC_BPartner_Location_ID, null); + } // getPrimaryC_BPartner_Location + + /** + * Get Primary AD_User_ID + * @return AD_User_ID + */ + public int getPrimaryAD_User_ID() + { + if (m_primaryAD_User_ID == null) + { + MUser[] users = getContacts(false); + // for (int i = 0; i < users.length; i++) + // { + // } + if (m_primaryAD_User_ID == null && users.length > 0) + setPrimaryAD_User_ID(users[0].getAD_User_ID()); + } + if (m_primaryAD_User_ID == null) + return 0; + return m_primaryAD_User_ID.intValue(); + } // getPrimaryAD_User_ID + + /** + * Set Primary C_BPartner_Location_ID + * @param C_BPartner_Location_ID id + */ + public void setPrimaryC_BPartner_Location_ID(int C_BPartner_Location_ID) + { + m_primaryC_BPartner_Location_ID = new Integer (C_BPartner_Location_ID); + } // setPrimaryC_BPartner_Location_ID + + /** + * Set Primary AD_User_ID + * @param AD_User_ID id + */ + public void setPrimaryAD_User_ID(int AD_User_ID) + { + m_primaryAD_User_ID = new Integer (AD_User_ID); + } // setPrimaryAD_User_ID + + + /** + * Calculate Total Open Balance and SO_CreditUsed. + * (includes drafted invoices) + */ + public void setTotalOpenBalance () + { + BigDecimal SO_CreditUsed = null; + BigDecimal TotalOpenBalance = null; + String sql = "SELECT " + // SO Credit Used + + "COALESCE((SELECT SUM(currencyBase(invoiceOpen(i.C_Invoice_ID,i.C_InvoicePaySchedule_ID),i.C_Currency_ID,i.DateOrdered, i.AD_Client_ID,i.AD_Org_ID)) FROM C_Invoice_v i " + + "WHERE i.C_BPartner_ID=bp.C_BPartner_ID AND i.IsSOTrx='Y' AND i.IsPaid='N'),0), " + // Balance (incl. unallocated payments) + + "COALESCE((SELECT SUM(currencyBase(invoiceOpen(i.C_Invoice_ID,i.C_InvoicePaySchedule_ID),i.C_Currency_ID,i.DateOrdered, i.AD_Client_ID,i.AD_Org_ID)*i.MultiplierAP) FROM C_Invoice_v i " + + "WHERE i.C_BPartner_ID=bp.C_BPartner_ID AND i.IsPaid='N'),0) - " + + "COALESCE((SELECT SUM(currencyBase(p.PayAmt,p.C_Currency_ID,p.DateTrx,p.AD_Client_ID,p.AD_Org_ID)) FROM C_Payment_v p " + + "WHERE p.C_BPartner_ID=bp.C_BPartner_ID AND p.IsAllocated='N'" + + " AND p.C_Charge_ID IS NULL AND NOT EXISTS (SELECT * FROM C_AllocationLine al WHERE p.C_Payment_ID=al.C_Payment_ID)),0) " + + "FROM C_BPartner bp " + + "WHERE C_BPartner_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + SO_CreditUsed = rs.getBigDecimal(1); + TotalOpenBalance = rs.getBigDecimal(2); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + m_TotalOpenBalanceSet = true; + if (SO_CreditUsed != null) + super.setSO_CreditUsed (SO_CreditUsed); + if (TotalOpenBalance != null) + super.setTotalOpenBalance(TotalOpenBalance); + setSOCreditStatus(); + } // setTotalOpenBalance + + /** + * Set Actual Life Time Value from DB + */ + public void setActualLifeTimeValue() + { + BigDecimal ActualLifeTimeValue = null; + String sql = "SELECT " + + "COALESCE ((SELECT SUM(currencyBase(i.GrandTotal,i.C_Currency_ID,i.DateOrdered, i.AD_Client_ID,i.AD_Org_ID)) FROM C_Invoice_v i " + + "WHERE i.C_BPartner_ID=bp.C_BPartner_ID AND i.IsSOTrx='Y'),0) " + + "FROM C_BPartner bp " + + "WHERE C_BPartner_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + ActualLifeTimeValue = rs.getBigDecimal(1); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (ActualLifeTimeValue != null) + super.setActualLifeTimeValue (ActualLifeTimeValue); + } // setActualLifeTimeValue + + /** + * Get Total Open Balance + * @param calculate if null calculate it + * @return Open Balance + */ + public BigDecimal getTotalOpenBalance (boolean calculate) + { + if (getTotalOpenBalance().signum() == 0 && calculate) + setTotalOpenBalance(); + return super.getTotalOpenBalance (); + } // getTotalOpenBalance + + + /** + * Set Credit Status + */ + public void setSOCreditStatus () + { + BigDecimal creditLimit = getSO_CreditLimit(); + // Nothing to do + if (SOCREDITSTATUS_NoCreditCheck.equals(getSOCreditStatus()) + || SOCREDITSTATUS_CreditStop.equals(getSOCreditStatus()) + || Env.ZERO.compareTo(creditLimit) == 0) + return; + + // Above Credit Limit + if (creditLimit.compareTo(getTotalOpenBalance(!m_TotalOpenBalanceSet)) < 0) + setSOCreditStatus(SOCREDITSTATUS_CreditHold); + else + { + // Above Watch Limit + BigDecimal watchAmt = creditLimit.multiply(getCreditWatchRatio()); + if (watchAmt.compareTo(getTotalOpenBalance()) < 0) + setSOCreditStatus(SOCREDITSTATUS_CreditWatch); + else // is OK + setSOCreditStatus (SOCREDITSTATUS_CreditOK); + } + } // setSOCreditStatus + + + /** + * Get SO CreditStatus with additional amount + * @param additionalAmt additional amount in Accounting Currency + * @return sinulated credit status + */ + public String getSOCreditStatus (BigDecimal additionalAmt) + { + if (additionalAmt == null || additionalAmt.signum() == 0) + return getSOCreditStatus(); + // + BigDecimal creditLimit = getSO_CreditLimit(); + // Nothing to do + if (SOCREDITSTATUS_NoCreditCheck.equals(getSOCreditStatus()) + || SOCREDITSTATUS_CreditStop.equals(getSOCreditStatus()) + || Env.ZERO.compareTo(creditLimit) == 0) + return getSOCreditStatus(); + + // Above (reduced) Credit Limit + creditLimit = creditLimit.subtract(additionalAmt); + if (creditLimit.compareTo(getTotalOpenBalance(!m_TotalOpenBalanceSet)) < 0) + return SOCREDITSTATUS_CreditHold; + + // Above Watch Limit + BigDecimal watchAmt = creditLimit.multiply(getCreditWatchRatio()); + if (watchAmt.compareTo(getTotalOpenBalance()) < 0) + return SOCREDITSTATUS_CreditWatch; + + // is OK + return SOCREDITSTATUS_CreditOK; + } // getSOCreditStatus + + /** + * Get Credit Watch Ratio + * @return BP Group ratio or 0.9 + */ + public BigDecimal getCreditWatchRatio() + { + return getBPGroup().getCreditWatchRatio(); + } // getCreditWatchRatio + + /** + * Credit Status is Stop or Hold. + * @return true if Stop/Hold + */ + public boolean isCreditStopHold() + { + String status = getSOCreditStatus(); + return SOCREDITSTATUS_CreditStop.equals(status) + || SOCREDITSTATUS_CreditHold.equals(status); + } // isCreditStopHold + + /** + * Set Total Open Balance + * @param TotalOpenBalance + */ + public void setTotalOpenBalance (BigDecimal TotalOpenBalance) + { + m_TotalOpenBalanceSet = false; + super.setTotalOpenBalance (TotalOpenBalance); + } // setTotalOpenBalance + + /** + * Get BP Group + * @return group + */ + public MBPGroup getBPGroup() + { + if (m_group == null) + { + if (getC_BP_Group_ID() == 0) + m_group = MBPGroup.getDefault(getCtx()); + else + m_group = MBPGroup.get(getCtx(), getC_BP_Group_ID()); + } + return m_group; + } // getBPGroup + + /** + * Get BP Group + * @param group group + */ + public void setBPGroup(MBPGroup group) + { + m_group = group; + if (m_group == null) + return; + setC_BP_Group_ID(m_group.getC_BP_Group_ID()); + if (m_group.getC_Dunning_ID() != 0) + setC_Dunning_ID(m_group.getC_Dunning_ID()); + if (m_group.getM_PriceList_ID() != 0) + setM_PriceList_ID(m_group.getM_PriceList_ID()); + if (m_group.getPO_PriceList_ID() != 0) + setPO_PriceList_ID(m_group.getPO_PriceList_ID()); + if (m_group.getM_DiscountSchema_ID() != 0) + setM_DiscountSchema_ID(m_group.getM_DiscountSchema_ID()); + if (m_group.getPO_DiscountSchema_ID() != 0) + setPO_DiscountSchema_ID(m_group.getPO_DiscountSchema_ID()); + } // setBPGroup + + /** + * Get PriceList + * @return price List + */ + public int getM_PriceList_ID () + { + int ii = super.getM_PriceList_ID(); + if (ii == 0) + ii = getBPGroup().getM_PriceList_ID(); + return ii; + } // getM_PriceList_ID + + /** + * Get PO PriceList + * @return price list + */ + public int getPO_PriceList_ID () + { + int ii = super.getPO_PriceList_ID(); + if (ii == 0) + ii = getBPGroup().getPO_PriceList_ID(); + return ii; + } // + + /** + * Get DiscountSchema + * @return Discount Schema + */ + public int getM_DiscountSchema_ID () + { + int ii = super.getM_DiscountSchema_ID (); + if (ii == 0) + ii = getBPGroup().getM_DiscountSchema_ID(); + return ii; + } // getM_DiscountSchema_ID + + /** + * Get PO DiscountSchema + * @return po discount + */ + public int getPO_DiscountSchema_ID () + { + int ii = super.getPO_DiscountSchema_ID (); + if (ii == 0) + ii = getBPGroup().getPO_DiscountSchema_ID(); + return ii; + } // getPO_DiscountSchema_ID + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (newRecord || is_ValueChanged("C_BP_Group_ID")) + { + MBPGroup grp = getBPGroup(); + if (grp == null) + { + log.saveWarning("Error", Msg.parseTranslation(getCtx(), "@NotFound@: @C_BP_Group_ID@")); + return false; + } + setBPGroup(grp); // setDefaults + } + return true; + } // beforeSave + + /************************************************************************** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (newRecord & success) + { + // Trees + insert_Tree(MTree_Base.TREETYPE_BPartner); + // Accounting + insert_Accounting("C_BP_Customer_Acct", "C_BP_Group_Acct", + "p.C_BP_Group_ID=" + getC_BP_Group_ID()); + insert_Accounting("C_BP_Vendor_Acct", "C_BP_Group_Acct", + "p.C_BP_Group_ID=" + getC_BP_Group_ID()); + insert_Accounting("C_BP_Employee_Acct", "C_AcctSchema_Default", null); + } + + // Value/Name change + if (success && !newRecord + && (is_ValueChanged("Value") || is_ValueChanged("Name"))) + MAccount.updateValueDescription(getCtx(), "C_BPartner_ID=" + getC_BPartner_ID(), get_TrxName()); + + return success; + } // afterSave + + /** + * Before Delete + * @return true + */ + protected boolean beforeDelete () + { + return delete_Accounting("C_BP_Customer_Acct") + && delete_Accounting("C_BP_Vendor_Acct") + && delete_Accounting("C_BP_Employee_Acct"); + } // beforeDelete + + /** + * After Delete + * @param success + * @return deleted + */ + protected boolean afterDelete (boolean success) + { + if (success) + delete_Tree(MTree_Base.TREETYPE_BPartner); + return success; + } // afterDelete + +} // MBPartner diff --git a/base/src/org/compiere/model/MBPartnerInfo.java b/base/src/org/compiere/model/MBPartnerInfo.java new file mode 100644 index 0000000000..fc58c5d9c1 --- /dev/null +++ b/base/src/org/compiere/model/MBPartnerInfo.java @@ -0,0 +1,152 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Business Partner Info Model for Query + * + * @author Jorg Janke + * @version $Id: MBPartnerInfo.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MBPartnerInfo extends X_RV_BPartner +{ + /** + * Find BPartners + * @param ctx context + * @param Value Business Partner Value + * @param Name Business Partner Name + * @param Contact Contact/User Name + * @param EMail Contact/User EMail + * @param Phone phone + * @param City city + * @return array if of info + */ + public static MBPartnerInfo[] find (Properties ctx, + String Value, String Name, String Contact, String EMail, String Phone, String City) + { + StringBuffer sql = new StringBuffer ("SELECT * FROM RV_BPartner WHERE IsActive='Y'"); + StringBuffer sb = new StringBuffer(); + Value = getFindParameter (Value); + if (Value != null) + sb.append("UPPER(Value) LIKE ?"); + Name = getFindParameter (Name); + if (Name != null) + { + if (sb.length() > 0) + sb.append(" OR "); + sb.append("UPPER(Name) LIKE ?"); + } + Contact = getFindParameter (Contact); + if (Contact != null) + { + if (sb.length() > 0) + sb.append(" OR "); + sb.append("UPPER(Contact) LIKE ?"); + } + EMail = getFindParameter (EMail); + if (EMail != null) + { + if (sb.length() > 0) + sb.append(" OR "); + sb.append("UPPER(EMail) LIKE ?"); + } + Phone = getFindParameter (Phone); + if (Phone != null) + { + if (sb.length() > 0) + sb.append(" OR "); + sb.append("UPPER(Phone) LIKE ?"); + } + City = getFindParameter (City); + if (City != null) + { + if (sb.length() > 0) + sb.append(" OR "); + sb.append("UPPER(City) LIKE ?"); + } + if (sb.length() > 0) + sql.append(" AND (").append(sb).append(")"); + sql.append(" ORDER BY Value"); + // + String finalSQL = MRole.getDefault().addAccessSQL(sql.toString(), + "RV_BPartner", MRole.SQL_NOTQUALIFIED, MRole.SQL_RO); + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(finalSQL, null); + int index = 1; + if (Value != null) + pstmt.setString(index++, Value); + if (Name != null) + pstmt.setString(index++, Name); + if (Contact != null) + pstmt.setString(index++, Contact); + if (EMail != null) + pstmt.setString(index++, EMail); + if (Phone != null) + pstmt.setString(index++, Phone); + if (City != null) + pstmt.setString(index++, City); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MBPartnerInfo (ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "find - " + finalSQL, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // Return + MBPartnerInfo[] retValue = new MBPartnerInfo[list.size()]; + list.toArray(retValue); + return retValue; + } // find + + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MBPartnerInfo.class); + + /************************************************************************** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MBPartnerInfo (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MBPartnerInfo + +} // MBPartnerInfo diff --git a/base/src/org/compiere/model/MBPartnerLocation.java b/base/src/org/compiere/model/MBPartnerLocation.java new file mode 100644 index 0000000000..958f984d68 --- /dev/null +++ b/base/src/org/compiere/model/MBPartnerLocation.java @@ -0,0 +1,265 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Partner Location Model + * + * @author Jorg Janke + * @version $Id: MBPartnerLocation.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MBPartnerLocation extends X_C_BPartner_Location +{ + /** + * Get Locations for BPartner + * @param ctx context + * @param C_BPartner_ID bp + * @return array of locations + */ + public static MBPartnerLocation[] getForBPartner (Properties ctx, int C_BPartner_ID) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_BPartner_Location WHERE C_BPartner_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, C_BPartner_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MBPartnerLocation(ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "getForBPartner", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MBPartnerLocation[] retValue = new MBPartnerLocation[list.size ()]; + list.toArray (retValue); + return retValue; + } // getForBPartner + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MBPartnerLocation.class); + + + /************************************************************************** + * Default Constructor + * @param ctx context + * @param C_BPartner_Location_ID id + * @param trxName transaction + */ + public MBPartnerLocation (Properties ctx, int C_BPartner_Location_ID, String trxName) + { + super (ctx, C_BPartner_Location_ID, trxName); + if (C_BPartner_Location_ID == 0) + { + setName ("."); + // + setIsShipTo (true); + setIsRemitTo (true); + setIsPayFrom (true); + setIsBillTo (true); + } + } // MBPartner_Location + + /** + * BP Parent Constructor + * @param bp partner + */ + public MBPartnerLocation (MBPartner bp) + { + this (bp.getCtx(), 0, bp.get_TrxName()); + setClientOrg(bp); + // may (still) be 0 + set_ValueNoCheck ("C_BPartner_ID", new Integer(bp.getC_BPartner_ID())); + } // MBPartner_Location + + /** + * Constructor from ResultSet row + * @param ctx context + * @param rs current row of result set to be loaded + * @param trxName transaction + */ + public MBPartnerLocation (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MBPartner_Location + + /** Cached Location */ + private MLocation m_location = null; + /** Unique Name */ + private String m_uniqueName = null; + private int m_unique = 0; + + /** + * Get Loaction/Address + * @param requery requery + * @return location + */ + public MLocation getLocation (boolean requery) + { + if (m_location == null) + m_location = MLocation.get (getCtx(), getC_Location_ID(), get_TrxName()); + return m_location; + } // getLoaction + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MBPartner_Location[ID=") + .append(get_ID()) + .append(",C_Location_ID=").append(getC_Location_ID()) + .append(",Name=").append(getName()) + .append ("]"); + return sb.toString (); + } // toString + + + /************************************************************************** + * Before Save. + * - Set Name + * @param newRecord new + * @return save + */ + protected boolean beforeSave (boolean newRecord) + { + if (getC_Location_ID() == 0) + return false; + + // Set New Name + if (!newRecord) + return true; + MLocation address = getLocation(true); + m_uniqueName = getName(); + if (m_uniqueName != null && m_uniqueName.equals(".")) // default + m_uniqueName = null; + m_unique = 0; + makeUnique(address); + + // Check uniqueness + MBPartnerLocation[] locations = MBPartnerLocation.getForBPartner(getCtx(), getC_BPartner_ID()); + boolean unique = locations.length == 0; + while (!unique) + { + unique = true; + for (int i = 0; i < locations.length; i++) + { + MBPartnerLocation location = locations[i]; + if (location.getC_BPartner_Location_ID() == get_ID()) + continue; + if (m_uniqueName.equals(location.getName())) + { + makeUnique(address); + unique = false; + break; + } + } + } + setName (m_uniqueName); + return true; + } // beforeSave + + /** + * Make name Unique + * @param address address + */ + private void makeUnique (MLocation address) + { + // m_uniqueName = address.toString(); + // return; + + if (m_uniqueName == null) + m_uniqueName = ""; + m_unique++; + + // 0 - City + if (m_uniqueName.length() == 0) + { + String xx = address.getCity(); + if (xx != null && xx.length() > 0) + m_uniqueName = xx; + m_unique = 0; + } + // 1 + Address1 + if (m_unique == 1 || m_uniqueName.length() == 0) + { + String xx = address.getAddress1(); + if (xx != null && xx.length() > 0) + { + if (m_uniqueName.length() > 0) + m_uniqueName += " "; + m_uniqueName += xx; + } + m_unique = 1; + } + // 2 + Address2 + if (m_unique == 2 || m_uniqueName.length() == 0) + { + String xx = address.getAddress2(); + if (xx != null && xx.length() > 0) + { + if (m_uniqueName.length() > 0) + m_uniqueName += " "; + m_uniqueName += xx; + } + m_unique = 2; + } + // 3 - Region + if (m_unique == 3 || m_uniqueName.length() == 0) + { + String xx = address.getRegionName(true); + { + if (m_uniqueName.length() > 0) + m_uniqueName += " "; + m_uniqueName += xx; + } + m_unique = 3; + } + // 4 - ID + if (m_unique == 4 || m_uniqueName.length() == 0) + { + int id = get_ID(); + if (id == 0) + id = address.get_ID(); + m_uniqueName += "#" + id; + m_unique = 4; + } + } // makeUnique + +} // MBPartnerLocation diff --git a/base/src/org/compiere/model/MBank.java b/base/src/org/compiere/model/MBank.java new file mode 100644 index 0000000000..504ec7056b --- /dev/null +++ b/base/src/org/compiere/model/MBank.java @@ -0,0 +1,88 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import org.compiere.util.*; + +/** + * Bank Model + * + * @author Jorg Janke + * @version $Id: MBank.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MBank extends X_C_Bank +{ + /** + * Get MBank from Cache + * @param ctx context + * @param C_Bank_ID id + * @return MBank + */ + public static MBank get (Properties ctx, int C_Bank_ID) + { + Integer key = new Integer (C_Bank_ID); + MBank retValue = (MBank)s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MBank (ctx, C_Bank_ID, null); + if (retValue.get_ID() != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = + new CCache ("C_Bank", 3); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param C_Bank_ID bank + * @param trxName trx + */ + public MBank (Properties ctx, int C_Bank_ID, String trxName) + { + super (ctx, C_Bank_ID, trxName); + } // MBank + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MBank (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MBank + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MBank["); + sb.append (get_ID ()).append ("-").append(getName ()).append ("]"); + return sb.toString (); + } // toString + +} // MBank diff --git a/base/src/org/compiere/model/MBankAccount.java b/base/src/org/compiere/model/MBankAccount.java new file mode 100644 index 0000000000..76cd1d9c92 --- /dev/null +++ b/base/src/org/compiere/model/MBankAccount.java @@ -0,0 +1,138 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + + +/** + * Bank Account Model + * + * @author Jorg Janke + * @version $Id: MBankAccount.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MBankAccount extends X_C_BankAccount +{ + /** + * Get BankAccount from Cache + * @param ctx context + * @param C_BankAccount_ID id + * @return MBankAccount + */ + public static MBankAccount get (Properties ctx, int C_BankAccount_ID) + { + Integer key = new Integer (C_BankAccount_ID); + MBankAccount retValue = (MBankAccount) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MBankAccount (ctx, C_BankAccount_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache + = new CCache("C_BankAccount", 5); + + /** + * Bank Account Model + * @param ctx context + * @param C_BankAccount_ID bank account + * @param trxName transaction + */ + public MBankAccount (Properties ctx, int C_BankAccount_ID, String trxName) + { + super (ctx, C_BankAccount_ID, trxName); + if (C_BankAccount_ID == 0) + { + setIsDefault (false); + setBankAccountType (BANKACCOUNTTYPE_Checking); + setCurrentBalance (Env.ZERO); + // setC_Currency_ID (0); + setCreditLimit (Env.ZERO); + // setC_BankAccount_ID (0); + } + } // MBankAccount + + /** + * Bank Account Model + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MBankAccount (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MBankAccount + + /** + * String representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MBankAccount[") + .append (get_ID()) + .append("-").append(getAccountNo()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Get Bank + * @return bank parent + */ + public MBank getBank() + { + return MBank.get(getCtx(), getC_Bank_ID()); + } // getBank + + /** + * Get Bank Name and Account No + * @return Bank/Account + */ + public String getName() + { + return getBank().getName() + " " + getAccountNo(); + } // getName + + /** + * After Save + * @param newRecord new record + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (newRecord & success) + return insert_Accounting("C_BankAccount_Acct", "C_AcctSchema_Default", null); + return success; + } // afterSave + + /** + * Before Delete + * @return true + */ + protected boolean beforeDelete () + { + return delete_Accounting("C_BankAccount_Acct"); + } // beforeDelete + +} // MBankAccount diff --git a/base/src/org/compiere/model/MBankStatement.java b/base/src/org/compiere/model/MBankStatement.java new file mode 100644 index 0000000000..7b8c4b5715 --- /dev/null +++ b/base/src/org/compiere/model/MBankStatement.java @@ -0,0 +1,587 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** +* Bank Statement Model +* +* @author Eldir Tomassen/Jorg Janke +* @version $Id: MBankStatement.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ +*/ +public class MBankStatement extends X_C_BankStatement implements DocAction +{ + /** + * Standard Constructor + * @param ctx context + * @param C_BankStatement_ID id + * @param trxName transaction + */ + public MBankStatement (Properties ctx, int C_BankStatement_ID, String trxName) + { + super (ctx, C_BankStatement_ID, trxName); + if (C_BankStatement_ID == 0) + { + // setC_BankAccount_ID (0); // parent + setStatementDate (new Timestamp(System.currentTimeMillis())); // @Date@ + setDocAction (DOCACTION_Complete); // CO + setDocStatus (DOCSTATUS_Drafted); // DR + setBeginningBalance(Env.ZERO); + setStatementDifference(Env.ZERO); + setEndingBalance (Env.ZERO); + setIsApproved (false); // N + setIsManual (true); // Y + setPosted (false); // N + super.setProcessed (false); + } + } // MBankStatement + + /** + * Load Constructor + * @param ctx Current context + * @param rs result set + * @param trxName transaction + */ + public MBankStatement(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MBankStatement + + /** + * Parent Constructor + * @param account Bank Account + * @param isManual Manual statement + **/ + public MBankStatement (MBankAccount account, boolean isManual) + { + this (account.getCtx(), 0, account.get_TrxName()); + setClientOrg(account); + setC_BankAccount_ID(account.getC_BankAccount_ID()); + setStatementDate(new Timestamp(System.currentTimeMillis())); + setBeginningBalance(account.getCurrentBalance()); + setName(getStatementDate().toString()); + setIsManual(isManual); + } // MBankStatement + + /** + * Create a new Bank Statement + * @param account Bank Account + */ + public MBankStatement(MBankAccount account) + { + this(account, false); + } // MBankStatement + + /** Lines */ + private MBankStatementLine[] m_lines = null; + + /** + * Get Bank Statement Lines + * @param requery requery + * @return line array + */ + public MBankStatementLine[] getLines (boolean requery) + { + if (m_lines != null && !requery) + return m_lines; + // + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_BankStatementLine " + + "WHERE C_BankStatement_ID=?" + + "ORDER BY Line"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_BankStatement_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add (new MBankStatementLine(getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getLines", e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + MBankStatementLine[] retValue = new MBankStatementLine[list.size()]; + list.toArray(retValue); + return retValue; + } // getLines + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * Set Processed. + * Propergate to Lines/Taxes + * @param processed processed + */ + public void setProcessed (boolean processed) + { + super.setProcessed (processed); + if (get_ID() == 0) + return; + String sql = "UPDATE C_BankStatementLine SET Processed='" + + (processed ? "Y" : "N") + + "' WHERE C_BankStatement_ID=" + getC_BankStatement_ID(); + int noLine = DB.executeUpdate(sql, get_TrxName()); + m_lines = null; + log.fine("setProcessed - " + processed + " - Lines=" + noLine); + } // setProcessed + + /** + * Get Bank Account + * @return bank Account + */ + public MBankAccount getBankAccount() + { + return MBankAccount.get(getCtx(), getC_BankAccount_ID()); + } // getBankAccount + + /** + * Get Document No + * @return name + */ + public String getDocumentNo() + { + return getName(); + } // getDocumentNo + + /** + * Get Document Info + * @return document info (untranslated) + */ + public String getDocumentInfo() + { + return getBankAccount().getName() + " " + getDocumentNo(); + } // getDocumentInfo + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + // ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.INVOICE, getC_Invoice_ID()); + // if (re == null) + return null; + // return re.getPDF(file); + } // createPDF + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getBeginningBalance().compareTo(Env.ZERO) == 0) + { + MBankAccount ba = MBankAccount.get(getCtx(), getC_BankAccount_ID()); + setBeginningBalance(ba.getCurrentBalance()); + } + setEndingBalance(getBeginningBalance().add(getStatementDifference())); + return true; + } // beforeSave + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // processIt + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info("unlockIt - " + toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info("invalidateIt - " + toString()); + setDocAction(DOCACTION_Prepare); + return true; + } // invalidateIt + + /** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + + // Std Period open? + if (!MPeriod.isOpen(getCtx(), getStatementDate(), MDocType.DOCBASETYPE_BankStatement)) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + MBankStatementLine[] lines = getLines(true); + if (lines.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + // Lines + BigDecimal total = Env.ZERO; + Timestamp minDate = getStatementDate(); + Timestamp maxDate = minDate; + for (int i = 0; i < lines.length; i++) + { + MBankStatementLine line = lines[i]; + total = total.add(line.getStmtAmt()); + if (line.getDateAcct().before(minDate)) + minDate = line.getDateAcct(); + if (line.getDateAcct().after(maxDate)) + maxDate = line.getDateAcct(); + } + setStatementDifference(total); + setEndingBalance(getBeginningBalance().add(total)); + if (!MPeriod.isOpen(getCtx(), minDate, MDocType.DOCBASETYPE_BankStatement) + || !MPeriod.isOpen(getCtx(), maxDate, MDocType.DOCBASETYPE_BankStatement)) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + + m_justPrepared = true; + if (!DOCACTION_Complete.equals(getDocAction())) + setDocAction(DOCACTION_Complete); + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info("approveIt - " + toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info("rejectIt - " + toString()); + setIsApproved(false); + return true; + } // rejectIt + + /** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + // Implicit Approval + if (!isApproved()) + approveIt(); + log.info("completeIt - " + toString()); + + // Set Payment reconciled + MBankStatementLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MBankStatementLine line = lines[i]; + if (line.getC_Payment_ID() != 0) + { + MPayment payment = new MPayment (getCtx(), line.getC_Payment_ID(), get_TrxName()); + payment.setIsReconciled(true); + payment.save(get_TrxName()); + } + } + // Update Bank Account + MBankAccount ba = MBankAccount.get(getCtx(), getC_BankAccount_ID()); + ba.setCurrentBalance(getEndingBalance()); + ba.save(get_TrxName()); + + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + m_processMsg = valid; + return DocAction.STATUS_Invalid; + } + // + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + /** + * Void Document. + * @return false + */ + public boolean voidIt() + { + log.info(toString()); + if (DOCSTATUS_Closed.equals(getDocStatus()) + || DOCSTATUS_Reversed.equals(getDocStatus()) + || DOCSTATUS_Voided.equals(getDocStatus())) + { + m_processMsg = "Document Closed: " + getDocStatus(); + setDocAction(DOCACTION_None); + return false; + } + + // Not Processed + if (DOCSTATUS_Drafted.equals(getDocStatus()) + || DOCSTATUS_Invalid.equals(getDocStatus()) + || DOCSTATUS_InProgress.equals(getDocStatus()) + || DOCSTATUS_Approved.equals(getDocStatus()) + || DOCSTATUS_NotApproved.equals(getDocStatus()) ) + ; + // Std Period open? + else + { + if (!MPeriod.isOpen(getCtx(), getStatementDate(), MDocType.DOCBASETYPE_BankStatement)) + { + m_processMsg = "@PeriodClosed@"; + return false; + } + if (MFactAcct.delete(Table_ID, getC_BankStatement_ID(), get_TrxName()) < 0) + return false; // could not delete + } + + // Set lines to 0 + MBankStatementLine[] lines = getLines(true); + for (int i = 0; i < lines.length; i++) + { + MBankStatementLine line = lines[i]; + BigDecimal old = line.getStmtAmt(); + if (line.getStmtAmt().compareTo(Env.ZERO) != 0) + { + String description = Msg.getMsg(getCtx(), "Voided") + " (" + + Msg.translate(getCtx(), "StmtAmt") + "=" + line.getStmtAmt(); + if (line.getTrxAmt().compareTo(Env.ZERO) != 0) + description += ", " + Msg.translate(getCtx(), "TrxAmt") + "=" + line.getTrxAmt(); + if (line.getChargeAmt().compareTo(Env.ZERO) != 0) + description += ", " + Msg.translate(getCtx(), "ChargeAmt") + "=" + line.getChargeAmt(); + if (line.getInterestAmt().compareTo(Env.ZERO) != 0) + description += ", " + Msg.translate(getCtx(), "InterestAmt") + "=" + line.getInterestAmt(); + description += ")"; + line.addDescription(description); + // + line.setStmtAmt(Env.ZERO); + line.setTrxAmt(Env.ZERO); + line.setChargeAmt(Env.ZERO); + line.setInterestAmt(Env.ZERO); + line.save(get_TrxName()); + // + if (line.getC_Payment_ID() != 0) + { + MPayment payment = new MPayment (getCtx(), line.getC_Payment_ID(), get_TrxName()); + payment.setIsReconciled(false); + payment.save(get_TrxName()); + } + } + } + addDescription(Msg.getMsg(getCtx(), "Voided")); + setStatementDifference(Env.ZERO); + + setProcessed(true); + setDocAction(DOCACTION_None); + return true; + } // voidIt + + /** + * Close Document. + * @return true if success + */ + public boolean closeIt() + { + log.info("closeIt - " + toString()); + + setDocAction(DOCACTION_None); + return true; + } // closeIt + + /** + * Reverse Correction + * @return false + */ + public boolean reverseCorrectIt() + { + log.info("reverseCorrectIt - " + toString()); + return false; + } // reverseCorrectionIt + + /** + * Reverse Accrual + * @return false + */ + public boolean reverseAccrualIt() + { + log.info("reverseAccrualIt - " + toString()); + return false; + } // reverseAccrualIt + + /** + * Re-activate + * @return false + */ + public boolean reActivateIt() + { + log.info("reActivateIt - " + toString()); + return false; + } // reActivateIt + + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getName()); + // : Total Lines = 123.00 (#1) + sb.append(": ") + .append(Msg.translate(getCtx(),"StatementDifference")).append("=").append(getStatementDifference()) + .append(" (#").append(getLines(false).length).append(")"); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner (Responsible) + * @return AD_User_ID + */ + public int getDoc_User_ID() + { + return getUpdatedBy(); + } // getDoc_User_ID + + /** + * Get Document Approval Amount. + * Statement Difference + * @return amount + */ + public BigDecimal getApprovalAmt() + { + return getStatementDifference(); + } // getApprovalAmt + + /** + * Get Document Currency + * @return C_Currency_ID + */ + public int getC_Currency_ID() + { + // MPriceList pl = MPriceList.get(getCtx(), getM_PriceList_ID()); + // return pl.getC_Currency_ID(); + return 0; + } // getC_Currency_ID + + } // MBankStatement diff --git a/base/src/org/compiere/model/MBankStatementLine.java b/base/src/org/compiere/model/MBankStatementLine.java new file mode 100644 index 0000000000..e7b34029ec --- /dev/null +++ b/base/src/org/compiere/model/MBankStatementLine.java @@ -0,0 +1,218 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Bank Statement Line Model + * + * @author Eldir Tomassen/Jorg Janke + * @version $Id: MBankStatementLine.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ + public class MBankStatementLine extends X_C_BankStatementLine + { + /** + * Standard Constructor + * @param ctx context + * @param C_BankStatementLine_ID id + * @param trxName transaction + */ + public MBankStatementLine (Properties ctx, int C_BankStatementLine_ID, String trxName) + { + super (ctx, C_BankStatementLine_ID, trxName); + if (C_BankStatementLine_ID == 0) + { + // setC_BankStatement_ID (0); // Parent + // setC_Charge_ID (0); + // setC_Currency_ID (0); // Bank Acct Currency + // setLine (0); // @SQL=SELECT NVL(MAX(Line),0)+10 AS DefaultValue FROM C_BankStatementLine WHERE C_BankStatement_ID=@C_BankStatement_ID@ + setStmtAmt(Env.ZERO); + setTrxAmt(Env.ZERO); + setInterestAmt(Env.ZERO); + setChargeAmt(Env.ZERO); + setIsReversal (false); + // setValutaDate (new Timestamp(System.currentTimeMillis())); // @StatementDate@ + // setDateAcct (new Timestamp(System.currentTimeMillis())); // @StatementDate@ + } + } // MBankStatementLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MBankStatementLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MBankStatementLine + + /** + * Parent Constructor + * @param statement Bank Statement that the line is part of + */ + public MBankStatementLine(MBankStatement statement) + { + this (statement.getCtx(), 0, statement.get_TrxName()); + setClientOrg(statement); + setC_BankStatement_ID(statement.getC_BankStatement_ID()); + setStatementLineDate(statement.getStatementDate()); + } // MBankStatementLine + + /** + * Parent Constructor + * @param statement Bank Statement that the line is part of + * @param lineNo position of the line within the statement + */ + public MBankStatementLine(MBankStatement statement, int lineNo) + { + this (statement); + setLine(lineNo); + } // MBankStatementLine + + + /** + * Set Statement Line Date and all other dates (Valuta, Acct) + * @param StatementLineDate date + */ + public void setStatementLineDate(Timestamp StatementLineDate) + { + super.setStatementLineDate(StatementLineDate); + setValutaDate (StatementLineDate); + setDateAcct (StatementLineDate); + } // setStatementLineDate + + /** + * Set Payment + * @param payment payment + */ + public void setPayment (MPayment payment) + { + setC_Payment_ID (payment.getC_Payment_ID()); + setC_Currency_ID (payment.getC_Currency_ID()); + // + BigDecimal amt = payment.getPayAmt(true); + setTrxAmt(amt); + setStmtAmt(amt); + // + setDescription(payment.getDescription()); + } // setPayment + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getChargeAmt().signum() != 0 && getC_Charge_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "C_Charge_ID")); + return false; + } + // Set Line No + if (getLine() == 0) + { + String sql = "SELECT COALESCE(MAX(Line),0)+10 AS DefaultValue FROM C_BankStatementLine WHERE C_BankStatement_ID=?"; + int ii = DB.getSQLValue (get_TrxName(), sql, getC_BankStatement_ID()); + setLine (ii); + } + + // Set References + if (getC_Payment_ID() != 0 && getC_BPartner_ID() == 0) + { + MPayment payment = new MPayment (getCtx(), getC_Payment_ID(), get_TrxName()); + setC_BPartner_ID(payment.getC_BPartner_ID()); + if (payment.getC_Invoice_ID() != 0) + setC_Invoice_ID(payment.getC_Invoice_ID()); + } + if (getC_Invoice_ID() != 0 && getC_BPartner_ID() == 0) + { + MInvoice invoice = new MInvoice (getCtx(), getC_Invoice_ID(), get_TrxName()); + setC_BPartner_ID(invoice.getC_BPartner_ID()); + } + + // Calculate Charge = Statement - trx - Interest + BigDecimal amt = getStmtAmt(); + amt = amt.subtract(getTrxAmt()); + amt = amt.subtract(getInterestAmt()); + if (amt.compareTo(getChargeAmt()) != 0) + setChargeAmt (amt); + // + + return true; + } // beforeSave + + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + updateHeader(); + return success; + } // afterSave + + /** + * After Delete + * @param success success + * @return success + */ + protected boolean afterDelete (boolean success) + { + updateHeader(); + return success; + } // afterSave + + /** + * Update Header + */ + private void updateHeader() + { + String sql = "UPDATE C_BankStatement bs" + + " SET StatementDifference=(SELECT SUM(StmtAmt) FROM C_BankStatementLine bsl " + + "WHERE bsl.C_BankStatement_ID=bs.C_BankStatement_ID AND bsl.IsActive='Y') " + + "WHERE C_BankStatement_ID=" + getC_BankStatement_ID(); + DB.executeUpdate(sql, get_TrxName()); + sql = "UPDATE C_BankStatement bs" + + " SET EndingBalance=BeginningBalance+StatementDifference " + + "WHERE C_BankStatement_ID=" + getC_BankStatement_ID(); + DB.executeUpdate(sql, get_TrxName()); + } // updateHeader + + } // MBankStatementLine diff --git a/base/src/org/compiere/model/MBankStatementLoader.java b/base/src/org/compiere/model/MBankStatementLoader.java new file mode 100644 index 0000000000..b4cbeb3c9f --- /dev/null +++ b/base/src/org/compiere/model/MBankStatementLoader.java @@ -0,0 +1,300 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.impexp.*; + + +/** + * Bank Statement Loader Model + * This class is responsible for creating an instance of the + * bank statement loader class to use. + * It also inserts the data into the I_BankStatement table. + * + * The loader objects can acces their configuration (e.g. file, URL, + * password etc) using the corresponding get methods provided by this class. + * As this class is derrived from PO, "Persistent Object" it has acces to + * the loader configuration that has been entered for this loader. + * How these values are interpreted is the responsibility of the loader. + * There are two file names provided, getFileName() and getLocalFileName(). + * The first one is the file name as entered on the loader configuration tab, + * the second one is the file name parameter from the loader process. + * Reccomended behaviour for a file based loader would be to use the file + * name from the process parameter if available, and resort to the file anme + * from the loader configuration as a second option. + * + * For a HTTP based loader the file name from the loader configuration should + * be used to construct the URL to connect to (combined with the other parameters). + * In this scenario the file name from the process parameter can be used to save + * the aquired statement data to disk. + * + * author Maarten Klinker, Eldir Tomassen + * @version $Id: MBankStatementLoader.java,v 1.3 2006/07/30 00:51:04 jjanke Exp $ + */ + public class MBankStatementLoader extends X_C_BankStatementLoader + { + /** Number of statement lines imported */ + private int loadCount = 0; + + /** Message will be handled by Adempiere (e.g. translated) */ + private String errorMessage = ""; + + /** Additional error description */ + private String errorDescription = ""; + + /** Loader object to use */ + private BankStatementLoaderInterface m_loader = null; + + /** File name from process parameter */ + private String localFileName = null; + + + + /** + * Create a Statement Loader + * Added for compatibility with new PO infrastructure (bug# 968136) + * @param ctx Current context + * @param C_BankStatementLoader_ID loader to use + * @param trxName transaction + */ + public MBankStatementLoader(Properties ctx, int C_BankStatementLoader_ID, String trxName) + { + super(ctx, C_BankStatementLoader_ID, trxName); + init(null); + } // MBankStatementLoader + + /** + * Create a Statement Loader + * @param ctx Current context + * @param C_BankStatementLoader_ID loader to use + * @param fileName input file + * @param trxName transaction + */ + public MBankStatementLoader(Properties ctx, int C_BankStatementLoader_ID, String fileName, String trxName) + { + super(ctx, C_BankStatementLoader_ID, trxName); + init(fileName); + + } // MBankStatementLoader + + /** + * Create a Statement Loader + * @param ctx Current context + * @param rs ResultSet + * @param trxName transaction + */ + public MBankStatementLoader(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + init(null); + } // MBankStatementLoader + + private void init(String fileName) + { + localFileName = fileName; + try + { + log.info( "MBankStatementLoader Class Name=" + getStmtLoaderClass()); + Class bsrClass = Class.forName(getStmtLoaderClass()); + m_loader = (BankStatementLoaderInterface) bsrClass.newInstance(); + } + catch(Exception e) + { + errorMessage = "ClassNotLoaded"; + errorDescription = e.getMessage(); + } + } + + /** + * Return Name + * @return Name + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MBankStatementLoader[") + .append(get_ID ()).append("-").append(getName()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Return Local File Name + * @return Name + */ + public String getLocalFileName() + { + return localFileName; + } // getLocalFileName + + /** + * Start loading Bankstatements + * @return true if loading completed succesfully + */ + public boolean loadLines() + { + boolean result = false; + log.info( "MBankStatementLoader.loadLines"); + if (m_loader == null) + { + errorMessage = "ClassNotLoaded"; + return result; + } + // Initialize the Loader + if (!m_loader.init(this)) + { + errorMessage = m_loader.getLastErrorMessage(); + errorDescription = m_loader.getLastErrorDescription(); + return result; + } + // Verify whether the data structure is valid + if (!m_loader.isValid()) + { + errorMessage = m_loader.getLastErrorMessage(); + errorDescription = m_loader.getLastErrorDescription(); + return result; + } + // Load statement lines + if (!m_loader.loadLines()) + { + errorMessage = m_loader.getLastErrorMessage(); + errorDescription = m_loader.getLastErrorDescription(); + return result; + } + result = true; + return result; + } // loadLines + + /** + * Load a bank statement into the I_BankStatement table + * @return Statement line was loaded succesfully + * This method is called by the BankStatementLoadere whenever a complete + * statement line has been read. + */ + public boolean saveLine() + { + log.info( "MBankStatementLoader.importLine"); + boolean result = false; + X_I_BankStatement imp = new X_I_BankStatement(getCtx(), 0, get_TrxName()); + if (m_loader == null) + { + errorMessage = "LoadError"; + return result; + } + // Bank Account fields + log.config( "MBankStatementLoader.importLine Bank Account=" + m_loader.getBankAccountNo()); + imp.setBankAccountNo(m_loader.getBankAccountNo()); + log.config( "MBankStatementLoader.importLine Routing No=" + m_loader.getRoutingNo()); + imp.setRoutingNo(m_loader.getRoutingNo()); + + // Statement fields + log.config( "MBankStatementLoader.importLine EFT Statement Reference No=" + m_loader.getStatementReference()); + imp.setEftStatementReference(m_loader.getStatementReference()); + log.config( "MBankStatementLoader.importLine EFT Statement Date=" + m_loader.getStatementDate()); + imp.setEftStatementDate(m_loader.getStatementDate()); + log.config( "MBankStatementLoader.importLine Statement Date=" + m_loader.getStatementDate()); + imp.setStatementDate(m_loader.getStatementDate()); + + // Statement Line fields + log.config( "MBankStatementLoader.importLine EFT Transaction ID=" + m_loader.getTrxID()); + imp.setEftTrxID(m_loader.getTrxID()); + log.config( "MBankStatementLoader.importLine Statement Line Date=" + m_loader.getStatementLineDate()); + imp.setStatementLineDate(m_loader.getStatementLineDate()); + imp.setStatementLineDate(m_loader.getStatementLineDate()); + imp.setEftStatementLineDate(m_loader.getStatementLineDate()); + log.config( "MBankStatementLoader.importLine Valuta Date=" + m_loader.getValutaDate()); + imp.setValutaDate(m_loader.getValutaDate()); + imp.setEftValutaDate(m_loader.getValutaDate()); + log.config( "MBankStatementLoader.importLine Statement Amount=" + m_loader.getStmtAmt()); + imp.setStmtAmt(m_loader.getStmtAmt()); + imp.setEftAmt(m_loader.getStmtAmt()); + log.config( "MBankStatementLoader.importLine Transaction Amount=" + m_loader.getTrxAmt()); + imp.setTrxAmt(m_loader.getTrxAmt()); + log.config( "MBankStatementLoader.importLine Interest Amount=" + m_loader.getInterestAmt()); + imp.setInterestAmt(m_loader.getInterestAmt()); + log.config( "MBankStatementLoader.importLine Reference No=" + m_loader.getReference()); + imp.setReferenceNo(m_loader.getReference()); + imp.setEftReference(m_loader.getReference()); + log.config( "MBankStatementLoader.importLine Check No=" + m_loader.getReference()); + imp.setEftCheckNo(m_loader.getCheckNo()); + log.config( "MBankStatementLoader.importLine Memo=" + m_loader.getMemo()); + imp.setMemo(m_loader.getMemo()); + imp.setEftMemo(m_loader.getMemo()); + log.config( "MBankStatementLoader.importLine Payee Name=" + m_loader.getPayeeName()); + imp.setEftPayee(m_loader.getPayeeName()); + log.config( "MBankStatementLoader.importLine Payee Account No=" + m_loader.getPayeeAccountNo()); + imp.setEftPayeeAccount(m_loader.getPayeeAccountNo()); + log.config( "MBankStatementLoader.importLine EFT Transaction Type=" + m_loader.getTrxType()); + imp.setEftTrxType(m_loader.getTrxType()); + log.config( "MBankStatementLoader.importLine Currency=" + m_loader.getCurrency()); + imp.setEftCurrency(m_loader.getCurrency()); + imp.setISO_Code(m_loader.getCurrency()); + log.config( "MBankStatementLoader.importLine Charge Name=" + m_loader.getChargeName()); + imp.setChargeName(m_loader.getChargeName()); + log.config( "MBankStatementLoader.importLine Charge Amount=" + m_loader.getChargeAmt()); + imp.setChargeAmt(m_loader.getChargeAmt()); + imp.setProcessed(false); + imp.setI_IsImported(false); + + result = imp.save(); + if (result) + { + loadCount ++; + } + else + { + errorMessage = "LoadError"; + } + imp = null; + return result; + } // importLine + + /** + * Return the most recent error + * @return Error message + * This error message will be handled as a Adempiere message, + * (e.g. it can be translated) + */ + public String getErrorMessage() + { + return errorMessage; + } // getErrorMessage + + /** + * Return the most recent error description + * @return Error discription + * This is an additional error description, it can be used to provided + * descriptive iformation, such as a file name or SQL error, that can not + * be translated by the Adempiere message system. + */ + public String getErrorDescription() + { + return errorDescription; + } // getErrorDescription + + /** + * The total number of statement lines loaded + * @return Number of imported statement lines + */ + public int getLoadCount() + { + return loadCount; + } // getLoadCount + + + } //MBankStatementLoader diff --git a/base/src/org/compiere/model/MBankStatementMatcher.java b/base/src/org/compiere/model/MBankStatementMatcher.java new file mode 100644 index 0000000000..8f1b99661f --- /dev/null +++ b/base/src/org/compiere/model/MBankStatementMatcher.java @@ -0,0 +1,146 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.impexp.*; +import org.compiere.util.*; + +/** + * Bank Statement Matcher Algorithm + * + * @author Jorg Janke + * @version $Id: MBankStatementMatcher.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MBankStatementMatcher extends X_C_BankStatementMatcher +{ + /** + * Get Bank Statement Matcher Algorithms + * @param ctx context + * @param trxName transaction + * @return matchers + */ + public static MBankStatementMatcher[] getMatchers (Properties ctx, String trxName) + { + ArrayList list = new ArrayList(); + String sql = MRole.getDefault(ctx, false).addAccessSQL( + "SELECT * FROM C_BankStatementMatcher ORDER BY SeqNo", + "C_BankStatementMatcher", MRole.SQL_NOTQUALIFIED, MRole.SQL_RO); + int AD_Client_ID = Env.getAD_Client_ID(ctx); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, trxName); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add (new MBankStatementMatcher(ctx, rs, trxName)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // Convert + MBankStatementMatcher[] retValue = new MBankStatementMatcher[list.size()]; + list.toArray(retValue); + return retValue; + } // getMatchers + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger(MBankStatementMatcher.class); + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param C_BankStatementMatcher_ID id + * @param trxName transaction + */ + public MBankStatementMatcher(Properties ctx, int C_BankStatementMatcher_ID, String trxName) + { + super(ctx, C_BankStatementMatcher_ID, trxName); + } // MBankStatementMatcher + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MBankStatementMatcher(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MBankStatementMatcher + + private BankStatementMatcherInterface m_matcher = null; + private Boolean m_matcherValid = null; + + /** + * Is Matcher Valid + * @return true if valid + */ + public boolean isMatcherValid() + { + if (m_matcherValid == null) + getMatcher(); + return m_matcherValid.booleanValue(); + } // isMatcherValid + + /** + * Get Matcher + * @return Matcher Instance + */ + public BankStatementMatcherInterface getMatcher() + { + if (m_matcher != null + || (m_matcherValid != null && m_matcherValid.booleanValue())) + return m_matcher; + + String className = getClassname(); + if (className == null || className.length() == 0) + return null; + + try + { + Class matcherClass = Class.forName(className); + m_matcher = (BankStatementMatcherInterface)matcherClass.newInstance(); + m_matcherValid = Boolean.TRUE; + } + catch (Exception e) + { + log.log(Level.SEVERE, className, e); + m_matcher = null; + m_matcherValid = Boolean.FALSE; + } + return m_matcher; + } // getMatcher + + +} // MBankStatementMatcher diff --git a/base/src/org/compiere/model/MCStage.java b/base/src/org/compiere/model/MCStage.java new file mode 100644 index 0000000000..d2d30891d3 --- /dev/null +++ b/base/src/org/compiere/model/MCStage.java @@ -0,0 +1,310 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Container Stage Model + * + * @author Jorg Janke + * @version $Id: MCStage.java,v 1.11 2006/09/23 10:44:05 comdivision Exp $ + */ +public class MCStage extends X_CM_CStage +{ + /** + * Get Stages + * @param project project + * @return stages + */ + public static MCStage[] getStages (MWebProject project) + { + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + String sql = "SELECT * FROM CM_CStage WHERE CM_WebProject_ID=? ORDER BY CM_CStage_ID"; + try + { + pstmt = DB.prepareStatement (sql, project.get_TrxName()); + pstmt.setInt (1, project.getCM_WebProject_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + list.add (new MCStage (project.getCtx(), rs, project.get_TrxName())); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MCStage[] retValue = new MCStage[list.size ()]; + list.toArray (retValue); + return retValue; + } // getStages + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MCStage.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param CM_CStage_ID id + * @param trxName tansaction + */ + public MCStage (Properties ctx, int CM_CStage_ID, String trxName) + { + super (ctx, CM_CStage_ID, trxName); + if (CM_CStage_ID == 0) + { + setIsValid(false); + setIsModified(false); + setIsSecure(false); + setIsSummary(false); + setIsIndexed(false); + } + } // MCStage + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MCStage (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MCStage + + /** Web Project */ + private MWebProject m_project = null; + + + /** + * Set Relative URL + * @param RelativeURL + */ + public void setRelativeURL (String RelativeURL) + { + if (RelativeURL != null) + { + if (RelativeURL.endsWith("/")) + RelativeURL = RelativeURL.substring(0, RelativeURL.length()-1); + int index = RelativeURL.lastIndexOf("/"); + if (index != -1) + RelativeURL = RelativeURL.substring(index+1); + } + super.setRelativeURL (RelativeURL); + } // setRelativeURL + + /** + * Get Web Project + * @return web project + */ + public MWebProject getWebProject() + { + if (m_project == null) + m_project = MWebProject.get(getCtx(), getCM_WebProject_ID()); + return m_project; + } // getWebProject + + /** + * Get AD_Tree_ID + * @return tree + */ + public int getAD_Tree_ID() + { + return getWebProject().getAD_TreeCMS_ID(); + } // getAD_Tree_ID; + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MCStage[") + .append (get_ID()).append ("-").append (getName()).append ("]"); + return sb.toString (); + } // toString + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Length >0 if not (Binary, Image, Text Long) + if ((!this.isSummary() || this.getContainerType().equals ("L")) && getCM_Template_ID()==0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "Template")); + return false; + } + // On Modification set isModified + if (is_ValueChanged("IsModified")) + setIsModified(true); + // Validate + setRelativeURL(getRelativeURL()); + return true; + } // beforeSave + + /** + * After Save. + * Insert + * - create tree + * @param newRecord insert + * @param success save success + * @return true if saved + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + // If Not Summary Node check whether all Elements and Templatetable Records exist. + if (!isSummary()) { + checkElements(); + checkTemplateTable(); + } + if (newRecord) + { + StringBuffer sb = new StringBuffer ("INSERT INTO AD_TreeNodeCMS " + + "(AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, " + + "AD_Tree_ID, Node_ID, Parent_ID, SeqNo) " + + "VALUES (") + .append(getAD_Client_ID()).append(",0, 'Y', SysDate, 0, SysDate, 0,") + .append(getAD_Tree_ID()).append(",").append(get_ID()) + .append(", 0, 999)"); + int no = DB.executeUpdate(sb.toString(), get_TrxName()); + if (no > 0) + log.fine("#" + no + " - TreeType=CMS"); + else + log.warning("#" + no + " - TreeType=CMS"); + return no > 0; + } + /*if (success) { + }*/ + return success; + } // afterSave + + /** + * After Delete + * @param success + * @return deleted + */ + protected boolean afterDelete (boolean success) + { + if (!success) + return success; + // + StringBuffer sb = new StringBuffer ("DELETE FROM AD_TreeNodeCMS ") + .append(" WHERE Node_ID=").append(get_IDOld()) + .append(" AND AD_Tree_ID=").append(getAD_Tree_ID()); + int no = DB.executeUpdate(sb.toString(), get_TrxName()); + if (no > 0) + log.fine("#" + no + " - TreeType=CMS"); + else + log.warning("#" + no + " - TreeType=CMS"); + return no > 0; + } // afterDelete + + /** + * Validate + * @return info + */ + public String validate() + { + return ""; + } // validate + + /** + * Check whether all Elements exist + * @return true if updated + */ + protected boolean checkElements () { + X_CM_Template thisTemplate = new X_CM_Template(getCtx(), this.getCM_Template_ID(), get_TrxName()); + StringBuffer thisElementList = new StringBuffer(thisTemplate.getElements()); + while (thisElementList.indexOf("\n")>=0) { + String thisElement = thisElementList.substring(0,thisElementList.indexOf("\n")); + thisElementList.delete(0,thisElementList.indexOf("\n")+1); + checkElement(thisElement); + } + String thisElement = thisElementList.toString(); + checkElement(thisElement); + return true; + } + + /** + * Check single Element, if not existing create it... + * @param elementName + */ + protected void checkElement(String elementName) { + int [] tableKeys = X_CM_CStage_Element.getAllIDs("CM_CStage_Element", "CM_CStage_ID=" + this.get_ID() + " AND Name like '" + elementName + "'", get_TrxName()); + if (tableKeys==null || tableKeys.length==0) { + X_CM_CStage_Element thisElement = new X_CM_CStage_Element(getCtx(), 0, get_TrxName()); + thisElement.setAD_Client_ID(getAD_Client_ID()); + thisElement.setAD_Org_ID(getAD_Org_ID()); + thisElement.setCM_CStage_ID(this.get_ID()); + thisElement.setContentHTML(" "); + thisElement.setName(elementName); + thisElement.save(get_TrxName()); + } + } + + /** + * Check whether all Template Table records exits + * @return true if updated + */ + protected boolean checkTemplateTable () { + int [] tableKeys = X_CM_TemplateTable.getAllIDs("CM_TemplateTable", "CM_Template_ID=" + this.getCM_Template_ID(), get_TrxName()); + if (tableKeys!=null) { + for (int i=0;i list = new ArrayList(); + String sql = "SELECT * FROM C_CashLine WHERE C_Cash_ID=? ORDER BY Line"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_Cash_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MCashLine (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + m_lines = new MCashLine[list.size ()]; + list.toArray (m_lines); + return m_lines; + } // getLines + + /** + * Get Cash Book + * @return cash book + */ + public MCashBook getCashBook() + { + if (m_book == null) + m_book = MCashBook.get(getCtx(), getC_CashBook_ID()); + return m_book; + } // getCashBook + + /** + * Get Document No + * @return name + */ + public String getDocumentNo() + { + return getName(); + } // getDocumentNo + + /** + * Get Document Info + * @return document info (untranslated) + */ + public String getDocumentInfo() + { + return Msg.getElement(getCtx(), "C_Cash_ID") + " " + getDocumentNo(); + } // getDocumentInfo + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + // ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.INVOICE, getC_Invoice_ID()); + // if (re == null) + return null; + // return re.getPDF(file); + } // createPDF + + /** + * Before Save + * @param newRecord + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + setAD_Org_ID(getCashBook().getAD_Org_ID()); + if (getAD_Org_ID() == 0) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@AD_Org_ID@")); + return false; + } + // Calculate End Balance + setEndingBalance(getBeginningBalance().add(getStatementDifference())); + return true; + } // beforeSave + + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // process + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info(toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info(toString()); + setDocAction(DOCACTION_Prepare); + return true; + } // invalidateIt + + /** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + + // Std Period open? + if (!MPeriod.isOpen(getCtx(), getDateAcct(), MDocType.DOCBASETYPE_CashJournal)) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + MCashLine[] lines = getLines(false); + if (lines.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + // Add up Amounts + BigDecimal difference = Env.ZERO; + int C_Currency_ID = getC_Currency_ID(); + for (int i = 0; i < lines.length; i++) + { + MCashLine line = lines[i]; + if (!line.isActive()) + continue; + if (C_Currency_ID == line.getC_Currency_ID()) + difference = difference.add(line.getAmount()); + else + { + BigDecimal amt = MConversionRate.convert(getCtx(), line.getAmount(), + line.getC_Currency_ID(), C_Currency_ID, getDateAcct(), 0, + getAD_Client_ID(), getAD_Org_ID()); + if (amt == null) + { + m_processMsg = "No Conversion Rate found - @C_CashLine_ID@= " + line.getLine(); + return DocAction.STATUS_Invalid; + } + difference = difference.add(amt); + } + } + setStatementDifference(difference); + // setEndingBalance(getBeginningBalance().add(getStatementDifference())); + // + m_justPrepared = true; + if (!DOCACTION_Complete.equals(getDocAction())) + setDocAction(DOCACTION_Complete); + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info(toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info(toString()); + setIsApproved(false); + return true; + } // rejectIt + + /** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + // Implicit Approval + if (!isApproved()) + approveIt(); + // + log.info(toString()); + + // Allocation Header + MAllocationHdr alloc = new MAllocationHdr(getCtx(), false, + getDateAcct(), getC_Currency_ID(), + Msg.translate(getCtx(), "C_Cash_ID") + ": " + getName(), get_TrxName()); + alloc.setAD_Org_ID(getAD_Org_ID()); + if (!alloc.save()) + { + m_processMsg = "Could not create Allocation Hdr"; + return DocAction.STATUS_Invalid; + } + // + MCashLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MCashLine line = lines[i]; + if (MCashLine.CASHTYPE_Invoice.equals(line.getCashType())) + { + boolean differentCurrency = getC_Currency_ID() != line.getC_Currency_ID(); + MAllocationHdr hdr = alloc; + if (differentCurrency) + { + hdr = new MAllocationHdr(getCtx(), false, + getDateAcct(), line.getC_Currency_ID(), + Msg.translate(getCtx(), "C_Cash_ID") + ": " + getName(), get_TrxName()); + hdr.setAD_Org_ID(getAD_Org_ID()); + if (!hdr.save()) + { + m_processMsg = "Could not create Allocation Hdr"; + return DocAction.STATUS_Invalid; + } + } + // Allocation Line + MAllocationLine aLine = new MAllocationLine (hdr, line.getAmount(), + line.getDiscountAmt(), line.getWriteOffAmt(), Env.ZERO); + aLine.setC_Invoice_ID(line.getC_Invoice_ID()); + aLine.setC_CashLine_ID(line.getC_CashLine_ID()); + if (!aLine.save()) + { + m_processMsg = "Could not create Allocation Line"; + return DocAction.STATUS_Invalid; + } + if (differentCurrency) + { + // Should start WF + hdr.processIt(DocAction.ACTION_Complete); + hdr.save(); + } + } + else if (MCashLine.CASHTYPE_BankAccountTransfer.equals(line.getCashType())) + { + // Payment just as intermediate info + MPayment pay = new MPayment (getCtx(), 0, get_TrxName()); + pay.setAD_Org_ID(getAD_Org_ID()); + String documentNo = getName(); + pay.setDocumentNo(documentNo); + pay.setR_PnRef(documentNo); + pay.set_Value("TrxType", "X"); // Transfer + pay.set_Value("TenderType", "X"); + // + pay.setC_BankAccount_ID(line.getC_BankAccount_ID()); + pay.setC_DocType_ID(true); // Receipt + pay.setDateTrx(getStatementDate()); + pay.setDateAcct(getDateAcct()); + pay.setAmount(line.getC_Currency_ID(), line.getAmount().negate()); // Transfer + pay.setDescription(line.getDescription()); + pay.setDocStatus(MPayment.DOCSTATUS_Closed); + pay.setDocAction(MPayment.DOCACTION_None); + pay.setPosted(true); + pay.setIsAllocated(true); // Has No Allocation! + pay.setProcessed(true); + if (!pay.save()) + { + m_processMsg = "Could not create Payment"; + return DocAction.STATUS_Invalid; + } + } + } + // Should start WF + alloc.processIt(DocAction.ACTION_Complete); + alloc.save(); + + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + m_processMsg = valid; + return DocAction.STATUS_Invalid; + } + // + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + /** + * Void Document. + * Same as Close. + * @return true if success + */ + public boolean voidIt() + { + log.info(toString()); + setDocAction(DOCACTION_None); + return false; + } // voidIt + + /** + * Close Document. + * Cancel not delivered Qunatities + * @return true if success + */ + public boolean closeIt() + { + log.info(toString()); + setDocAction(DOCACTION_None); + return true; + } // closeIt + + /** + * Reverse Correction + * @return true if success + */ + public boolean reverseCorrectIt() + { + log.info(toString()); + return false; + } // reverseCorrectionIt + + /** + * Reverse Accrual - none + * @return true if success + */ + public boolean reverseAccrualIt() + { + log.info(toString()); + return false; + } // reverseAccrualIt + + /** + * Re-activate + * @return true if success + */ + public boolean reActivateIt() + { + log.info(toString()); + setProcessed(false); + if (reverseCorrectIt()) + return true; + return false; + } // reActivateIt + + /** + * Set Processed + * @param processed processed + */ + public void setProcessed (boolean processed) + { + super.setProcessed (processed); + String sql = "UPDATE C_CashLine SET Processed='" + + (processed ? "Y" : "N") + + "' WHERE C_Cash_ID=" + getC_Cash_ID(); + int noLine = DB.executeUpdate (sql, get_TrxName()); + m_lines = null; + log.fine(processed + " - Lines=" + noLine); + } // setProcessed + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MCash["); + sb.append (get_ID ()) + .append ("-").append (getName()) + .append(", Balance=").append(getBeginningBalance()) + .append("->").append(getEndingBalance()) + .append ("]"); + return sb.toString (); + } // toString + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getName()); + // : Total Lines = 123.00 (#1) + sb.append(": ") + .append(Msg.translate(getCtx(),"BeginningBalance")).append("=").append(getBeginningBalance()) + .append(",") + .append(Msg.translate(getCtx(),"EndingBalance")).append("=").append(getEndingBalance()) + .append(" (#").append(getLines(false).length).append(")"); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner (Responsible) + * @return AD_User_ID + */ + public int getDoc_User_ID() + { + return getCreatedBy(); + } // getDoc_User_ID + + /** + * Get Document Approval Amount + * @return amount difference + */ + public BigDecimal getApprovalAmt() + { + return getStatementDifference(); + } // getApprovalAmt + + /** + * Get Currency + * @return Currency + */ + public int getC_Currency_ID () + { + return getCashBook().getC_Currency_ID(); + } // getC_Currency_ID + +} // MCash diff --git a/base/src/org/compiere/model/MCashBook.java b/base/src/org/compiere/model/MCashBook.java new file mode 100644 index 0000000000..84552c6c99 --- /dev/null +++ b/base/src/org/compiere/model/MCashBook.java @@ -0,0 +1,159 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Cash Book Model + * + * @author Jorg Janke + * @version $Id: MCashBook.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MCashBook extends X_C_CashBook +{ + /** + * Get MCashBook from Cache + * @param ctx context + * @param C_CashBook_ID id + * @return MCashBook + */ + public static MCashBook get (Properties ctx, int C_CashBook_ID) + { + Integer key = new Integer (C_CashBook_ID); + MCashBook retValue = (MCashBook) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MCashBook (ctx, C_CashBook_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** + * Get CashBook for Org and Currency + * @param ctx context + * @param AD_Org_ID org + * @param C_Currency_ID currency + * @return cash book or null + */ + public static MCashBook get (Properties ctx, int AD_Org_ID, int C_Currency_ID) + { + // Try from cache + Iterator it = s_cache.values().iterator(); + while (it.hasNext()) + { + MCashBook cb = (MCashBook)it.next(); + if (cb.getAD_Org_ID() == AD_Org_ID && cb.getC_Currency_ID() == C_Currency_ID) + return cb; + } + + // Get from DB + MCashBook retValue = null; + String sql = "SELECT * FROM C_CashBook " + + "WHERE AD_Org_ID=? AND C_Currency_ID=? " + + "ORDER BY IsDefault DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, AD_Org_ID); + pstmt.setInt (2, C_Currency_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + retValue = new MCashBook (ctx, rs, null); + Integer key = new Integer (retValue.getC_CashBook_ID()); + s_cache.put (key, retValue); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "get", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return retValue; + } // get + + + /** Cache */ + private static CCache s_cache + = new CCache("", 20); + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MCashBook.class); + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param C_CashBook_ID id + * @param trxName transaction + */ + public MCashBook (Properties ctx, int C_CashBook_ID, String trxName) + { + super (ctx, C_CashBook_ID, trxName); + } // MCashBook + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MCashBook (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MCashBook + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (newRecord & success) + insert_Accounting("C_CashBook_Acct", "C_AcctSchema_Default", null); + + return success; + } // afterSave + + /** + * Before Delete + * @return true + */ + protected boolean beforeDelete () + { + return delete_Accounting("C_Cashbook_Acct"); + } // beforeDelete + +} // MCashBook diff --git a/base/src/org/compiere/model/MCashLine.java b/base/src/org/compiere/model/MCashLine.java new file mode 100644 index 0000000000..76675f6306 --- /dev/null +++ b/base/src/org/compiere/model/MCashLine.java @@ -0,0 +1,387 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Cash Line Model + * + * @author Jorg Janke + * @version $Id: MCashLine.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MCashLine extends X_C_CashLine +{ + /** + * Standard Constructor + * @param ctx context + * @param C_CashLine_ID id + * @param trxName transaction + */ + public MCashLine (Properties ctx, int C_CashLine_ID, String trxName) + { + super (ctx, C_CashLine_ID, trxName); + if (C_CashLine_ID == 0) + { + // setLine (0); + // setCashType (CASHTYPE_GeneralExpense); + setAmount (Env.ZERO); + setDiscountAmt(Env.ZERO); + setWriteOffAmt(Env.ZERO); + setIsGenerated(false); + } + } // MCashLine + + /** + * Load Cosntructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MCashLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MCashLine + + /** + * Parent Cosntructor + * @param cash parent + */ + public MCashLine (MCash cash) + { + this (cash.getCtx(), 0, cash.get_TrxName()); + setClientOrg(cash); + setC_Cash_ID(cash.getC_Cash_ID()); + m_parent = cash; + m_cashBook = m_parent.getCashBook(); + } // MCashLine + + /** Parent */ + private MCash m_parent = null; + /** Cash Book */ + private MCashBook m_cashBook = null; + /** Bank Account */ + private MBankAccount m_bankAccount = null; + /** Invoice */ + private MInvoice m_invoice = null; + + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * Set Invoice - no discount + * @param invoice invoice + */ + public void setInvoice (MInvoice invoice) + { + setC_Invoice_ID(invoice.getC_Invoice_ID()); + setCashType (CASHTYPE_Invoice); + setC_Currency_ID(invoice.getC_Currency_ID()); + // Amount + MDocType dt = MDocType.get(getCtx(), invoice.getC_DocType_ID()); + BigDecimal amt = invoice.getGrandTotal(); + if (MDocType.DOCBASETYPE_APInvoice.equals(dt.getDocBaseType()) + || MDocType.DOCBASETYPE_ARCreditMemo.equals(dt.getDocBaseType()) ) + amt = amt.negate(); + setAmount (amt); + // + setDiscountAmt(Env.ZERO); + setWriteOffAmt(Env.ZERO); + setIsGenerated(true); + m_invoice = invoice; + } // setInvoiceLine + + /** + * Set Order - no discount + * @param order order + * @param trxName transaction + */ + public void setOrder (MOrder order, String trxName) + { + setCashType (CASHTYPE_Invoice); + setC_Currency_ID(order.getC_Currency_ID()); + // Amount + BigDecimal amt = order.getGrandTotal(); + setAmount (amt); + setDiscountAmt(Env.ZERO); + setWriteOffAmt(Env.ZERO); + setIsGenerated(true); + // + if (MOrder.DOCSTATUS_WaitingPayment.equals(order.getDocStatus())) + { + save(trxName); + order.setC_CashLine_ID(getC_CashLine_ID()); + order.processIt(MOrder.ACTION_WaitComplete); + order.save(trxName); + // Set Invoice + MInvoice[] invoices = order.getInvoices(); + int length = invoices.length; + if (length > 0) // get last invoice + { + m_invoice = invoices[length-1]; + setC_Invoice_ID (m_invoice.getC_Invoice_ID()); + } + } + } // setOrder + + + /** + * Get Statement Date from header + * @return date + */ + public Timestamp getStatementDate() + { + return getParent().getStatementDate(); + } // getStatementDate + + /** + * Create Line Reversal + * @return new reversed CashLine + */ + public MCashLine createReversal() + { + MCash parent = getParent(); + if (parent.isProcessed()) + { // saved + parent = MCash.get(getCtx(), parent.getAD_Org_ID(), + parent.getStatementDate(), parent.getC_Currency_ID(), get_TrxName()); + } + // + MCashLine reversal = new MCashLine (parent); + reversal.setClientOrg(this); + reversal.setC_BankAccount_ID(getC_BankAccount_ID()); + reversal.setC_Charge_ID(getC_Charge_ID()); + reversal.setC_Currency_ID(getC_Currency_ID()); + reversal.setC_Invoice_ID(getC_Invoice_ID()); + reversal.setCashType(getCashType()); + reversal.setDescription(getDescription()); + reversal.setIsGenerated(true); + // + reversal.setAmount(getAmount().negate()); + if (getDiscountAmt() == null) + setDiscountAmt(Env.ZERO); + else + reversal.setDiscountAmt(getDiscountAmt().negate()); + if (getWriteOffAmt() == null) + setWriteOffAmt(Env.ZERO); + else + reversal.setWriteOffAmt(getWriteOffAmt().negate()); + reversal.addDescription("(" + getLine() + ")"); + return reversal; + } // reverse + + + /** + * Get Cash (parent) + * @return cash + */ + public MCash getParent() + { + if (m_parent == null) + m_parent = new MCash (getCtx(), getC_Cash_ID(), get_TrxName()); + return m_parent; + } // getCash + + /** + * Get CashBook + * @return cash book + */ + public MCashBook getCashBook() + { + if (m_cashBook == null) + m_cashBook = MCashBook.get(getCtx(), getParent().getC_CashBook_ID()); + return m_cashBook; + } // getCashBook + + /** + * Get Bank Account + * @return bank account + */ + public MBankAccount getBankAccount() + { + if (m_bankAccount == null && getC_BankAccount_ID() != 0) + m_bankAccount = MBankAccount.get(getCtx(), getC_BankAccount_ID()); + return m_bankAccount; + } // getBankAccount + + /** + * Get Invoice + * @return invoice + */ + public MInvoice getInvoice() + { + if (m_invoice == null && getC_Invoice_ID() != 0) + m_invoice = MInvoice.get(getCtx(), getC_Invoice_ID()); + return m_invoice; + } // getInvoice + + /************************************************************************** + * Before Delete + * @return true/false + */ + protected boolean beforeDelete () + { + // Cannot Delete generated Invoices + Boolean generated = (Boolean)get_ValueOld("IsGenerated"); + if (generated != null && generated.booleanValue()) + { + if (get_ValueOld("C_Invoice_ID") != null) + { + log.warning("Cannot delete line with generated Invoice"); + return false; + } + } + return true; + } // beforeDelete + + /** + * After Delete + * @param success + * @return true/false + */ + protected boolean afterDelete (boolean success) + { + if (!success) + return success; + return updateHeader(); + } // afterDelete + + + /** + * Before Save + * @param newRecord + * @return true/false + */ + protected boolean beforeSave (boolean newRecord) + { + // Cannot change generated Invoices + if (is_ValueChanged("C_Invoice_ID")) + { + Object generated = get_ValueOld("IsGenerated"); + if (generated != null && ((Boolean)generated).booleanValue()) + { + log.warning("Cannot change line with generated Invoice"); + return false; + } + } + + // Verify CashType + if (CASHTYPE_Invoice.equals(getCashType()) && getC_Invoice_ID() == 0) + setCashType(CASHTYPE_GeneralExpense); + if (CASHTYPE_BankAccountTransfer.equals(getCashType()) && getC_BankAccount_ID() == 0) + setCashType(CASHTYPE_GeneralExpense); + if (CASHTYPE_Charge.equals(getCashType()) && getC_Charge_ID() == 0) + setCashType(CASHTYPE_GeneralExpense); + + boolean verify = newRecord + || is_ValueChanged("CashType") + || is_ValueChanged("C_Invoice_ID") + || is_ValueChanged("C_BankAccount_ID"); + if (verify) + { + // Verify Currency + if (CASHTYPE_BankAccountTransfer.equals(getCashType())) + setC_Currency_ID(getBankAccount().getC_Currency_ID()); + else if (CASHTYPE_Invoice.equals(getCashType())) + setC_Currency_ID(getInvoice().getC_Currency_ID()); + else // Cash + setC_Currency_ID(getCashBook().getC_Currency_ID()); + + // Set Organization + if (CASHTYPE_BankAccountTransfer.equals(getCashType())) + setAD_Org_ID(getBankAccount().getAD_Org_ID()); + // Cash Book + else if (CASHTYPE_Invoice.equals(getCashType())) + setAD_Org_ID(getCashBook().getAD_Org_ID()); + // otherwise (charge) - leave it + // Enforce Org + if (getAD_Org_ID() == 0) + setAD_Org_ID(getParent().getAD_Org_ID()); + } + + /** General fix of Currency + UPDATE C_CashLine cl SET C_Currency_ID = (SELECT C_Currency_ID FROM C_Invoice i WHERE i.C_Invoice_ID=cl.C_Invoice_ID) WHERE C_Currency_ID IS NULL AND C_Invoice_ID IS NOT NULL; + UPDATE C_CashLine cl SET C_Currency_ID = (SELECT C_Currency_ID FROM C_BankAccount b WHERE b.C_BankAccount_ID=cl.C_BankAccount_ID) WHERE C_Currency_ID IS NULL AND C_BankAccount_ID IS NOT NULL; + UPDATE C_CashLine cl SET C_Currency_ID = (SELECT b.C_Currency_ID FROM C_Cash c, C_CashBook b WHERE c.C_Cash_ID=cl.C_Cash_ID AND c.C_CashBook_ID=b.C_CashBook_ID) WHERE C_Currency_ID IS NULL; + **/ + + // Get Line No + if (getLine() == 0) + { + String sql = "SELECT COALESCE(MAX(Line),0)+10 FROM C_CashLine WHERE C_Cash_ID=?"; + int ii = DB.getSQLValue (get_TrxName(), sql, getC_Cash_ID()); + setLine (ii); + } + + return true; + } // beforeSave + + /** + * After Save + * @param newRecord + * @param success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + return updateHeader(); + } // afterSave + + /** + * Update Cash Header. + * Statement Difference, Ending Balance + * @return true if success + */ + private boolean updateHeader() + { + String sql = "UPDATE C_Cash c" + + " SET StatementDifference=" + + "(SELECT COALESCE(SUM(currencyConvert(cl.Amount, cl.C_Currency_ID, cb.C_Currency_ID, c.DateAcct, null, c.AD_Client_ID, c.AD_Org_ID)),0) " + + "FROM C_CashLine cl, C_CashBook cb " + + "WHERE cb.C_CashBook_ID=c.C_CashBook_ID" + + " AND cl.C_Cash_ID=c.C_Cash_ID) " + + "WHERE C_Cash_ID=" + getC_Cash_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + if (no != 1) + log.warning("Difference #" + no); + // Ending Balance + sql = "UPDATE C_Cash" + + " SET EndingBalance = BeginningBalance + StatementDifference " + + "WHERE C_Cash_ID=" + getC_Cash_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 1) + log.warning("Balance #" + no); + return no == 1; + } // updateHeader + +} // MCashLine diff --git a/base/src/org/compiere/model/MChangeNotice.java b/base/src/org/compiere/model/MChangeNotice.java new file mode 100644 index 0000000000..99437778e9 --- /dev/null +++ b/base/src/org/compiere/model/MChangeNotice.java @@ -0,0 +1,57 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Change Notice Model + * @author Jorg Janke + * @version $Id: MChangeNotice.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MChangeNotice extends X_M_ChangeNotice +{ + /** + * Standard Constructor + * @param ctx context + * @param M_ChangeNotice_ID id + * @param trxName trx + */ + public MChangeNotice (Properties ctx, int M_ChangeNotice_ID, String trxName) + { + super (ctx, M_ChangeNotice_ID, trxName); + if (M_ChangeNotice_ID == 0) + { + // setName (null); + setIsApproved (false); // N + setProcessed (false); + } + } // MChangeNotice + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MChangeNotice (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MChangeNotice + +} // MChangeNotice diff --git a/base/src/org/compiere/model/MChangeRequest.java b/base/src/org/compiere/model/MChangeRequest.java new file mode 100644 index 0000000000..4ee27783a0 --- /dev/null +++ b/base/src/org/compiere/model/MChangeRequest.java @@ -0,0 +1,111 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import org.compiere.util.*; + +/** + * Change Request Model + * @author Jorg Janke + * @version $Id: MChangeRequest.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MChangeRequest extends X_M_ChangeRequest +{ + /** + * Standard Constructor + * @param ctx context + * @param M_ChangeRequest_ID ix + * @param trxName trx + */ + public MChangeRequest (Properties ctx, int M_ChangeRequest_ID, String trxName) + { + super (ctx, M_ChangeRequest_ID, trxName); + if (M_ChangeRequest_ID == 0) + { + // setName (null); + setIsApproved(false); + setProcessed(false); + } + } // MChangeRequest + + /** + * CRM Request Constructor + * @param request request + * @param group request group + */ + public MChangeRequest (MRequest request, MGroup group) + { + this (request.getCtx(), 0, request.get_TrxName()); + setClientOrg(request); + setName(Msg.getElement(getCtx(), "R_Request_ID") + ": " + request.getDocumentNo()); + setHelp(request.getSummary()); + // + setM_BOM_ID(group.getM_BOM_ID()); + setM_ChangeNotice_ID(group.getM_ChangeNotice_ID()); + } // MChangeRequest + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MChangeRequest (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MChangeRequest + + /** + * Get CRM Requests of Change Requests + * @return requests + */ + public MRequest[] getRequests() + { + String sql = "SELECT * FROM R_Request WHERE M_ChangeRequest_ID=?"; + return null; + } // getRequests + + + /** + * Before Save + * @param newRecord new + * @return true/false + */ + protected boolean beforeSave (boolean newRecord) + { + // Have at least one + if (getM_BOM_ID() == 0 && getM_ChangeNotice_ID() == 0) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@NotFound@: @M_BOM_ID@ / @M_ChangeNotice_ID@")); + return false; + } + + // Derive ChangeNotice from BOM if defined + if (newRecord && getM_BOM_ID() != 0 && getM_ChangeNotice_ID() == 0) + { + MBOM bom = new MBOM (getCtx(), getM_BOM_ID(), get_TrxName()); + if (bom.getM_ChangeNotice_ID() != 0) + setM_BOM_ID(bom.getM_ChangeNotice_ID()); + } + + return true; + } // beforeSave + +} // MChangeRequest diff --git a/base/src/org/compiere/model/MCharge.java b/base/src/org/compiere/model/MCharge.java new file mode 100644 index 0000000000..433d4c08e0 --- /dev/null +++ b/base/src/org/compiere/model/MCharge.java @@ -0,0 +1,158 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Charge Model + * + * @author Jorg Janke + * @version $Id: MCharge.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MCharge extends X_C_Charge +{ + /** + * Get Charge Account + * @param C_Charge_ID charge + * @param as account schema + * @param amount amount for expense(+)/revenue(-) + * @return Charge Account or null + */ + public static MAccount getAccount (int C_Charge_ID, MAcctSchema as, BigDecimal amount) + { + if (C_Charge_ID == 0 || as == null) + return null; + + int acct_index = 1; // Expense (positive amt) + if (amount != null && amount.signum() < 0) + acct_index = 2; // Revenue (negative amt) + String sql = "SELECT CH_Expense_Acct, CH_Revenue_Acct FROM C_Charge_Acct WHERE C_Charge_ID=? AND C_AcctSchema_ID=?"; + int Account_ID = 0; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt (1, C_Charge_ID); + pstmt.setInt (2, as.getC_AcctSchema_ID()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + Account_ID = rs.getInt(acct_index); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + s_log.log(Level.SEVERE, sql, e); + return null; + } + // No account + if (Account_ID == 0) + { + s_log.severe ("NO account for C_Charge_ID=" + C_Charge_ID); + return null; + } + + // Return Account + MAccount acct = MAccount.get (as.getCtx(), Account_ID); + return acct; + } // getAccount + + /** + * Get MCharge from Cache + * @param ctx context + * @param C_Charge_ID id + * @return MCharge + */ + public static MCharge get (Properties ctx, int C_Charge_ID) + { + Integer key = new Integer (C_Charge_ID); + MCharge retValue = (MCharge)s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MCharge (ctx, C_Charge_ID, null); + if (retValue.get_ID() != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache + = new CCache ("C_Charge", 10); + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MCharge.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param C_Charge_ID id + * @param trxName transaction + */ + public MCharge (Properties ctx, int C_Charge_ID, String trxName) + { + super (ctx, C_Charge_ID, null); + if (C_Charge_ID == 0) + { + setChargeAmt (Env.ZERO); + setIsSameCurrency (false); + setIsSameTax (false); + setIsTaxIncluded (false); // N + // setName (null); + // setC_TaxCategory_ID (0); + } + } // MCharge + + /** + * Load Constructor + * @param ctx ctx + * @param rs result set + * @param trxName transaction + */ + public MCharge (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MCharge + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (newRecord & success) + insert_Accounting("C_Charge_Acct", "C_AcctSchema_Default", null); + + return success; + } // afterSave + + /** + * Before Delete + * @return true + */ + protected boolean beforeDelete () + { + return delete_Accounting("C_Charge_Acct"); + } // beforeDelete + +} // MCharge diff --git a/base/src/org/compiere/model/MChat.java b/base/src/org/compiere/model/MChat.java new file mode 100644 index 0000000000..e483580912 --- /dev/null +++ b/base/src/org/compiere/model/MChat.java @@ -0,0 +1,239 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.text.*; +import java.util.*; +import java.util.logging.*; +import org.apache.ecs.xhtml.*; +import org.compiere.util.*; + +/** + * Chat Model + * + * @author Jorg Janke + * @version $Id: MChat.java,v 1.4 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MChat extends X_CM_Chat +{ + /** + * Get Chats Of Table - of client in context + * @param ctx context + * @param AD_Table_ID table + * @return array of chats + */ + public static MChat[] getOfTable (Properties ctx, int AD_Table_ID) + { + int AD_Client_ID = Env.getAD_Client_ID(ctx); + ArrayList list = new ArrayList(); + // + String sql = "SELECT * FROM CM_Chat " + + "WHERE AD_Client_ID=? AND AD_Table_ID=? ORDER BY Record_ID"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, AD_Client_ID); + pstmt.setInt (2, AD_Table_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + list.add (new MChat (ctx, rs, null)); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + MChat[] retValue = new MChat[list.size()]; + list.toArray (retValue); + return retValue; + } // get + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MChat.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param CM_Chat_ID id + * @param trxName transcation + */ + public MChat (Properties ctx, int CM_Chat_ID, String trxName) + { + super (ctx, CM_Chat_ID, trxName); + if (CM_Chat_ID == 0) + { + // setAD_Table_ID (0); + // setRecord_ID (0); + setConfidentialType (CONFIDENTIALTYPE_PublicInformation); + // setDescription (null); + } + } // MChat + + /** + * Full Constructor + * @param ctx context + * @param AD_Table_ID table + * @param Record_ID record + * @param Description description + * @param trxName transaction + */ + public MChat (Properties ctx, int AD_Table_ID, int Record_ID, + String Description, String trxName) + { + this (ctx, 0, trxName); + setAD_Table_ID (AD_Table_ID); + setRecord_ID (Record_ID); + setDescription (Description); + } // MChat + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MChat (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MChat + + /** The Lines */ + private MChatEntry[] m_entries = null; + /** Date Format */ + private SimpleDateFormat m_format = null; + + + /** + * Get Entries + * @param reload reload data + * @return array of lines + */ + public MChatEntry[] getEntries (boolean reload) + { + if (m_entries != null && !reload) + return m_entries; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM CM_ChatEntry WHERE CM_Chat_ID=? ORDER BY Created"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getCM_Chat_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + list.add (new MChatEntry (getCtx(), rs, get_TrxName())); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + m_entries = new MChatEntry[list.size ()]; + list.toArray (m_entries); + return m_entries; + } // getEntries + + + /** + * Set Description + * + * @param Description + */ + public void setDescription (String Description) + { + if (Description != null && Description.length() > 0) + super.setDescription (Description); + else + super.setDescription (getAD_Table_ID() + "#" + getRecord_ID()); + } // setDescription + + /** + * Get History as htlp paragraph + * @param ConfidentialType confidentiality + * @return html paragraph + */ + public p getHistory (String ConfidentialType) + { + p history = new p(); + getEntries(false); + boolean first = true; + for (int i = 0; i < m_entries.length; i++) + { + MChatEntry entry = m_entries[i]; + if (!entry.isActive() || !entry.isConfidentialType(ConfidentialType)) + continue; + if (first) + first = false; + else + history.addElement(new hr()); + // User & Date + b b = new b(); + MUser user = MUser.get(getCtx(), entry.getCreatedBy()); + b.addElement(user.getName()); + b.addElement(" \t"); + Timestamp created = entry.getCreated(); + if (m_format == null) + m_format = DisplayType.getDateFormat(DisplayType.DateTime); + b.addElement(m_format.format(created)); + history.addElement(b); + // history.addElement(new br()); + // + p p = new p(); + String data = entry.getCharacterData(); + data = Util.maskHTML(data, true); + p.addElement(data); + history.addElement(p); + } // entry + // + return history; + } // getHistory + + +} // MChat diff --git a/base/src/org/compiere/model/MChatEntry.java b/base/src/org/compiere/model/MChatEntry.java new file mode 100644 index 0000000000..1e7055be3d --- /dev/null +++ b/base/src/org/compiere/model/MChatEntry.java @@ -0,0 +1,93 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Chat Entry Model + * + * @author Jorg Janke + * @version $Id: MChatEntry.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MChatEntry extends X_CM_ChatEntry +{ + /** + * Standard Constructor + * @param ctx cintext + * @param CM_ChatEntry_ID id + * @param trxName transaction + */ + public MChatEntry (Properties ctx, int CM_ChatEntry_ID, String trxName) + { + super (ctx, CM_ChatEntry_ID, trxName); + } // MChatEntry + + /** + * Parent Constructor + * @param chat parent + * @param data text + */ + public MChatEntry (MChat chat, String data) + { + this (chat.getCtx(), 0, chat.get_TrxName()); + setCM_Chat_ID(chat.getCM_Chat_ID()); + setConfidentialType(chat.getConfidentialType()); + setCharacterData(data); + } // MChatEntry + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MChatEntry (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MChatEntry + + /** + * Can be published + * @param ConfidentialType minimum confidential type + * @return true if withing confidentiality + */ + public boolean isConfidentialType(String ConfidentialType) + { + String ct = getConfidentialType(); + if (ConfidentialType == null + || CONFIDENTIALTYPE_PublicInformation.equals(ct)) + return true; + if (CONFIDENTIALTYPE_PartnerConfidential.equals(ct)) + { + return CONFIDENTIALTYPE_PartnerConfidential.equals(ConfidentialType); + } + else if (CONFIDENTIALTYPE_PrivateInformation.equals(ct)) + { + return CONFIDENTIALTYPE_Internal.equals(ConfidentialType) + || CONFIDENTIALTYPE_PrivateInformation.equals(ConfidentialType); + } + else if (CONFIDENTIALTYPE_Internal.equals(ct)) + { + return CONFIDENTIALTYPE_Internal.equals(ConfidentialType); + } + return false; + } // + +} // MChatEntry diff --git a/base/src/org/compiere/model/MChatType.java b/base/src/org/compiere/model/MChatType.java new file mode 100644 index 0000000000..25c3ddbb14 --- /dev/null +++ b/base/src/org/compiere/model/MChatType.java @@ -0,0 +1,75 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Chat Type Model + * + * @author Jorg Janke + * @version $Id: MChatType.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MChatType extends X_CM_ChatType +{ + /** + * Get MChatType from Cache + * @param ctx context + * @param CM_ChatType_ID id + * @return MChatType + */ + public static MChatType get (Properties ctx, int CM_ChatType_ID) + { + Integer key = new Integer (CM_ChatType_ID); + MChatType retValue = (MChatType)s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MChatType (ctx, CM_ChatType_ID, null); + if (retValue.get_ID () != CM_ChatType_ID) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache + = new CCache ("CM_ChatType", 20); + + /** + * Standard Constructor + * @param ctx context + * @param CM_ChatType_ID id + * @param trxName transaction + */ + public MChatType (Properties ctx, int CM_ChatType_ID, String trxName) + { + super (ctx, CM_ChatType_ID, trxName); + } // MChatType + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MChatType (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MChatType + +} // MChatType diff --git a/base/src/org/compiere/model/MClick.java b/base/src/org/compiere/model/MClick.java new file mode 100644 index 0000000000..d6ba740448 --- /dev/null +++ b/base/src/org/compiere/model/MClick.java @@ -0,0 +1,266 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.*; +import org.compiere.util.*; + +/** + * Actual Click + * + * @author Jorg Janke + * @version $Id: MClick.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MClick extends X_W_Click +{ + /** + * Get Unprocessed Clicks + * @param ctx context + * @return array of unprocessed clicks + */ + public static MClick[] getUnprocessed(Properties ctx) + { + ArrayList list = new ArrayList (); + String sql = "SELECT * FROM W_Click WHERE AD_Client_ID=? AND Processed = 'N'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, Env.getAD_Client_ID(ctx)); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + list.add (new MClick (ctx, rs, null)); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + MClick[] retValue = new MClick[list.size ()]; + list.toArray (retValue); + return retValue; + } // getUnprocessed + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MClick.class); + + + /************************************************************************** + * Actual Click + * @param ctx context + * @param W_Click_ID ID + * @param trxName transaction + */ + public MClick (Properties ctx, int W_Click_ID, String trxName) + { + super (ctx, W_Click_ID, trxName); + if (W_Click_ID == 0) + setProcessed (false); + } // MClick + + /** + * Actual Click + * @param ctx context + * @param TargetURL url + * @param trxName transaction + */ + public MClick (Properties ctx, String TargetURL, String trxName) + { + this (ctx, 0, trxName); + setTargetURL(TargetURL); + } // MClick + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MClick (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MClick + + /** + * Set Target URL. Reset Click Count + * @param TargetURL + */ + public void setTargetURL(String TargetURL) + { + super.setTargetURL(TargetURL); + super.setW_ClickCount_ID(0); + } // setTargetURL + + /** + * Find Click Count. + */ + public void setW_ClickCount_ID () + { + // clean up url + String url = getTargetURL(); + if (url == null || url.length() == 0) + return; + String exactURL = url; + // remove everything before first / . + if (url.startsWith("http://")) + url = url.substring(7); + int dot = url.indexOf('.'); + int slash = url.indexOf('/'); + while (dot > slash && slash != -1) + { + url = url.substring(slash+1); + dot = url.indexOf('.'); + slash = url.indexOf('/'); + } + // remove everything after / + if (slash != -1) + url = url.substring(0, slash); + log.fine(exactURL + " -> " + url); + int W_ClickCount_ID = search (url, exactURL); + // try minumum + if (W_ClickCount_ID == 0) + { + int lastDot = url.lastIndexOf('.'); + int firstDot = url.indexOf('.'); + while (lastDot != firstDot) + { + url = url.substring(firstDot+1); + lastDot = url.lastIndexOf('.'); + firstDot = url.indexOf('.'); + } + log.fine(exactURL + " -> " + url); + W_ClickCount_ID = search (url, exactURL); + } + // Not found + if (W_ClickCount_ID == 0) + { + log.warning ("Not found: " + url + + " (" + exactURL + ") Referrer=" + getReferrer()); + return; + } + // OK + setProcessed(true); + super.setW_ClickCount_ID (W_ClickCount_ID); + } // setW_ClickCount_ID + + /** + * Search for Click Count + * @param url url + * @param exactURL original url + * @return W_ClickCount_ID + */ + private int search (String url, String exactURL) + { + String sql = "SELECT W_ClickCount_ID, TargetURL FROM W_ClickCount WHERE TargetURL LIKE ?"; + int W_ClickCount_ID = 0; + int exactW_ClickCount_ID = 0; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setString(1, "%" + url + "%"); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + W_ClickCount_ID = rs.getInt(1); + if (exactURL.equals(rs.getString(2))) + { + exactW_ClickCount_ID = W_ClickCount_ID; + break; + } + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close(); + } + catch (SQLException ex1) + { + } + pstmt = null; + // Set Click Count + if (exactW_ClickCount_ID != 0) + W_ClickCount_ID = exactW_ClickCount_ID; + return W_ClickCount_ID; + } // search + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getW_ClickCount_ID() == 0) + setW_ClickCount_ID(); + return true; + } // beforeSave + + /************************************************************************** + * Test + * @param args ignored + */ + public static void main (String[] args) + { + Adempiere.startup(true); + Env.setContext(Env.getCtx(), "#AD_Client_ID", 1000000); + MClick[] clicks = getUnprocessed(Env.getCtx()); + int counter = 0; + for (int i = 0; i < clicks.length; i++) + { + MClick click = clicks[i]; + if (click.getW_ClickCount_ID() == 0) + { + click.setW_ClickCount_ID(); + if (click.getW_ClickCount_ID() != 0) + { + click.save(); + counter++; + } + } + } + System.out.println("#" + counter); + } // main + +} // MClick diff --git a/base/src/org/compiere/model/MClickCount.java b/base/src/org/compiere/model/MClickCount.java new file mode 100644 index 0000000000..03d7c6e08b --- /dev/null +++ b/base/src/org/compiere/model/MClickCount.java @@ -0,0 +1,175 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.text.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Click Count (header) + * + * @author Jorg Janke + * @version $Id: MClickCount.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MClickCount extends X_W_ClickCount +{ + /** + * Standard Constructor + * @param ctx context + * @param W_ClickCount_ID id + * @param trxName transaction + */ + public MClickCount (Properties ctx, int W_ClickCount_ID, String trxName) + { + super (ctx, W_ClickCount_ID, trxName); + if (W_ClickCount_ID == 0) + { + // setName (null); + // setTargetURL (null); + } + } // MClickCount + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MClickCount (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MClickCount + + /** + * Parent Constructor + * @param ad parent + */ + public MClickCount (MAdvertisement ad) + { + this (ad.getCtx(), 0, ad.get_TrxName()); + setName(ad.getName()); + setTargetURL("#"); + setC_BPartner_ID(ad.getC_BPartner_ID()); + } // MClickCount + + private SimpleDateFormat m_dateFormat = DisplayType.getDateFormat(DisplayType.Date); + private DecimalFormat m_intFormat = DisplayType.getNumberFormat(DisplayType.Integer); + + + /************************************************************************** + * Get Clicks + * @return clicks + */ + public MClick[] getMClicks() + { + ArrayList list = new ArrayList(); + /** @todo Clicks */ + // + MClick[] retValue = new MClick[list.size()]; + list.toArray(retValue); + return retValue; + } // getMClicks + + /** + * Get Count for date format + * @param DateFormat valid TRUNC date format + * @return count + */ + protected ValueNamePair[] getCount (String DateFormat) + { + ArrayList list = new ArrayList(); + String sql = "SELECT TRUNC(Created, '" + DateFormat + "'), Count(*) " + + "FROM W_Click " + + "WHERE W_ClickCount_ID=? " + + "GROUP BY TRUNC(Created, '" + DateFormat + "')"; + // + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getW_ClickCount_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + String value = m_dateFormat.format(rs.getTimestamp(1)); + String name = m_intFormat.format(rs.getInt(2)); + ValueNamePair pp = new ValueNamePair (value, name); + list.add(pp); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close(); + } + catch (SQLException ex1) + { + } + pstmt = null; + // + ValueNamePair[] retValue = new ValueNamePair[list.size()]; + list.toArray(retValue); + return retValue; + } // getCount + + /** + * Get Monthly Count + * @return monthly count + */ + public ValueNamePair[] getCountQuarter () + { + return getCount("Q"); + } // getCountQuarter + + /** + * Get Monthly Count + * @return monthly count + */ + public ValueNamePair[] getCountMonth () + { + return getCount("MM"); + } // getCountMonth + + /** + * Get Weekly Count + * @return weekly count + */ + public ValueNamePair[] getCountWeek () + { + return getCount("DY"); + } // getCountWeek + + /** + * Get Daily Count + * @return dailt count + */ + public ValueNamePair[] getCountDay () + { + return getCount("J"); + } // getCountDay + +} // MClickCount diff --git a/base/src/org/compiere/model/MColor.java b/base/src/org/compiere/model/MColor.java new file mode 100644 index 0000000000..f726011a98 --- /dev/null +++ b/base/src/org/compiere/model/MColor.java @@ -0,0 +1,187 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.awt.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.plaf.*; +import org.compiere.util.*; + +/** + * Color Persistent Object Model + * (DisplayType=27) + * + * @author Jorg Janke + * @version $Id: MColor.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MColor extends X_AD_Color +{ + /** + * Color Model + * @param ctx context + * @param AD_Color_ID color + * @param trxName transaction + */ + public MColor(Properties ctx, int AD_Color_ID, String trxName) + { + super (ctx, AD_Color_ID, trxName); + if (AD_Color_ID == 0) + setName("-/-"); + } // MColor + + /** + * String Representation + * @return string + */ + public String toString() + { + return "MColor[ID=" + get_ID() + " - " + getName() + "]"; + } // toString + + /** + * Load Special data (images, ..). + * To be extended by sub-classes + * @param rs result set + * @param index zero based index + * @return value + * @throws SQLException + */ + protected Object loadSpecial (ResultSet rs, int index) throws SQLException + { + log.config(p_info.getColumnName(index)); + if (index == get_ColumnIndex("ColorType")) + return rs.getString(index+1); + return null; + } // loadSpecial + + + /** + * Save Special Data. + * AD_Image_ID (Background) + * @param value value + * @param index index + * @return SQL code for INSERT VALUES clause + */ + protected String saveNewSpecial (Object value, int index) + { + String colName = p_info.getColumnName(index); + String colValue = value == null ? "null" : value.getClass().toString(); + log.fine(colName + "=" + colValue); + if (value == null) + return "NULL"; + return value.toString(); + } // saveNewSpecial + + + /************************************************************************** + * Get AdempiereColor. + * see org.compiere.grid.ed.VColor#getAdempiereColor + * @return AdempiereColor + */ + public AdempiereColor getAdempiereColor() + { + if (get_ID() == 0) + return null; + + // Color Type + String ColorType = (String)getColorType(); + if (ColorType == null) + { + log.log(Level.SEVERE, "MColor.getAdempiereColor - No ColorType"); + return null; + } + AdempiereColor cc = null; + // + if (ColorType.equals(AdempiereColor.TYPE_FLAT)) + { + cc = new AdempiereColor(getColor(true), true); + } + else if (ColorType.equals(AdempiereColor.TYPE_GRADIENT)) + { + int RepeatDistance = getRepeatDistance(); + String StartPoint = getStartPoint(); + int startPoint = StartPoint == null ? 0 : Integer.parseInt(StartPoint); + cc = new AdempiereColor(getColor(true), getColor(false), startPoint, RepeatDistance); + } + else if (ColorType.equals(AdempiereColor.TYPE_LINES)) + { + int LineWidth = getLineWidth(); + int LineDistance = getLineDistance(); + cc = new AdempiereColor(getColor(false), getColor(true), LineWidth, LineDistance); + } + else if (ColorType.equals(AdempiereColor.TYPE_TEXTURE)) + { + int AD_Image_ID = getAD_Image_ID(); + String url = getURL(AD_Image_ID); + if (url == null) + return null; + BigDecimal ImageAlpha = getImageAlpha(); + float compositeAlpha = ImageAlpha == null ? 0.7f : ImageAlpha.floatValue(); + cc = new AdempiereColor(url, getColor(true), compositeAlpha); + } + return cc; + } // getAdempiereColor + + /** + * Get Color + * @param primary true if primary false if secondary + * @return Color + */ + private Color getColor (boolean primary) + { + int red = primary ? getRed() : getRed_1(); + int green = primary ? getGreen() : getGreen_1(); + int blue = primary ? getBlue() : getBlue_1(); + // + return new Color (red, green, blue); + } // getColor + + /** + * Get URL from Image + * @param AD_Image_ID image + * @return URL as String or null + */ + private String getURL (int AD_Image_ID) + { + if (AD_Image_ID == 0) + return null; + // + String retValue = null; + String sql = "SELECT ImageURL FROM AD_Image WHERE AD_Image_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt (1, AD_Image_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + retValue = rs.getString(1); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + return retValue; + } // getURL + +} // MColor diff --git a/base/src/org/compiere/model/MColorSchema.java b/base/src/org/compiere/model/MColorSchema.java new file mode 100644 index 0000000000..031fe5cdb2 --- /dev/null +++ b/base/src/org/compiere/model/MColorSchema.java @@ -0,0 +1,206 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.awt.*; +import java.sql.*; +import java.util.*; +import java.math.*; + +import org.compiere.util.*; +import org.compiere.print.*; + +/** + * Performance Color Schema + * + * @author Jorg Janke + * @version $Id: MColorSchema.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MColorSchema extends X_PA_ColorSchema +{ + /** + * Get Color + * @param ctx context + * @param PA_ColorSchema_ID id + * @param target target value + * @param actual actual value + * @return color + */ + public static Color getColor (Properties ctx, int PA_ColorSchema_ID, + BigDecimal target, BigDecimal actual) + { + int percent = 0; + if (actual != null && actual.signum() != 0 + && target != null && target.signum() != 0) + { + BigDecimal pp = actual.multiply(Env.ONEHUNDRED) + .divide(target, 0, BigDecimal.ROUND_HALF_UP); + percent = pp.intValue(); + } + return getColor(ctx, PA_ColorSchema_ID, percent); + } // getColor + + /** + * Get Color + * @param ctx context + * @param PA_ColorSchema_ID id + * @param percent percent + * @return color + */ + public static Color getColor (Properties ctx, int PA_ColorSchema_ID, int percent) + { + MColorSchema cs = get(ctx, PA_ColorSchema_ID); + return cs.getColor(percent); + } // getColor + + + /** + * Get MColorSchema from Cache + * @param ctx context + * @param PA_ColorSchema_ID id + * @return MColorSchema + */ + public static MColorSchema get (Properties ctx, int PA_ColorSchema_ID) + { + if (PA_ColorSchema_ID == 0) + { + MColorSchema retValue = new MColorSchema(ctx, 0, null); + retValue.setDefault(); + return retValue; + } + Integer key = new Integer (PA_ColorSchema_ID); + MColorSchema retValue = (MColorSchema)s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MColorSchema (ctx, PA_ColorSchema_ID, null); + if (retValue.get_ID() != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache + = new CCache ("PA_ColorSchema", 20); + + /** + * Standard Constructor + * @param ctx context + * @param PA_ColorSchema_ID id + * @param trxName trx + */ + public MColorSchema (Properties ctx, int PA_ColorSchema_ID, String trxName) + { + super (ctx, PA_ColorSchema_ID, trxName); + if (PA_ColorSchema_ID == 0) + { + // setName (null); + // setMark1Percent (50); + // setAD_PrintColor1_ID (102); // red + // setMark2Percent (100); + // setAD_PrintColor2_ID (113); // yellow + } + } // MColorSchema + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MColorSchema (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MColorSchema + + /** + * Set Default. + * Red (50) - Yellow (100) - Green + */ + public void setDefault() + { + setName("Default"); + setMark1Percent (50); + setAD_PrintColor1_ID (102); // red + setMark2Percent (100); + setAD_PrintColor2_ID (113); // yellow + setMark3Percent (9999); + setAD_PrintColor3_ID (103); // green + } // setDefault + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getMark1Percent() > getMark2Percent()) + setMark1Percent(getMark2Percent()); + if (getMark2Percent() > getMark3Percent() && getMark3Percent() != 0) + setMark2Percent(getMark3Percent()); + if (getMark3Percent() > getMark4Percent() && getMark4Percent() != 0) + setMark4Percent(getMark4Percent()); + // + return true; + } // beforeSave + + /** + * Get Color + * @param percent percent + * @return color + */ + public Color getColor (int percent) + { + int AD_PrintColor_ID = 0; + if (percent <= getMark1Percent() || getMark2Percent() == 0) + AD_PrintColor_ID = getAD_PrintColor1_ID(); + else if (percent <= getMark2Percent() || getMark3Percent() == 0) + AD_PrintColor_ID = getAD_PrintColor2_ID(); + else if (percent <= getMark3Percent() || getMark4Percent() == 0) + AD_PrintColor_ID = getAD_PrintColor3_ID(); + else + AD_PrintColor_ID = getAD_PrintColor4_ID(); + if (AD_PrintColor_ID == 0) + { + if (getAD_PrintColor3_ID() != 0) + AD_PrintColor_ID = getAD_PrintColor3_ID(); + else if (getAD_PrintColor2_ID() != 0) + AD_PrintColor_ID = getAD_PrintColor2_ID(); + else if (getAD_PrintColor1_ID() != 0) + AD_PrintColor_ID = getAD_PrintColor1_ID(); + } + if (AD_PrintColor_ID == 0) + return Color.black; + // + MPrintColor pc = MPrintColor.get(getCtx(), AD_PrintColor_ID); + if (pc != null) + return pc.getColor(); + return Color.black; + } // getColor + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MColorSchema["); + sb.append (get_ID()).append ("-").append (getName()).append ("]"); + return sb.toString (); + } // toString + +} // MColorSchema diff --git a/base/src/org/compiere/model/MCommission.java b/base/src/org/compiere/model/MCommission.java new file mode 100644 index 0000000000..8c216f2796 --- /dev/null +++ b/base/src/org/compiere/model/MCommission.java @@ -0,0 +1,143 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Model for Commission. + * (has Lines) + * + * @author Jorg Janke + * @version $Id: MCommission.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MCommission extends X_C_Commission +{ + /** + * Standard Constructor + * @param ctx context + * @param C_Commission_ID id + * @param trxName transaction + */ + public MCommission(Properties ctx, int C_Commission_ID, String trxName) + { + super(ctx, C_Commission_ID, trxName); + if (C_Commission_ID == 0) + { + // setName (null); + // setC_BPartner_ID (0); + // setC_Charge_ID (0); + // setC_Commission_ID (0); + // setC_Currency_ID (0); + // + setDocBasisType (DOCBASISTYPE_Invoice); // I + setFrequencyType (FREQUENCYTYPE_Monthly); // M + setListDetails (false); + } + } // MCommission + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MCommission(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MCommission + + /** + * Get Lines + * @return array of lines + */ + public MCommissionLine[] getLines() + { + String sql = "SELECT * FROM C_CommissionLine WHERE C_Commission_ID=? ORDER BY Line"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_Commission_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MCommissionLine(getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + // Convert + MCommissionLine[] retValue = new MCommissionLine[list.size()]; + list.toArray(retValue); + return retValue; + } // getLines + + /** + * Set Date Last Run + * @param DateLastRun date + */ + public void setDateLastRun (Timestamp DateLastRun) + { + if (DateLastRun != null) + super.setDateLastRun(DateLastRun); + } // setDateLastRun + + /** + * Copy Lines From other Commission + * @param otherCom commission + * @return number of lines copied + */ + public int copyLinesFrom (MCommission otherCom) + { + if (otherCom == null) + return 0; + MCommissionLine[] fromLines = otherCom.getLines (); + int count = 0; + for (int i = 0; i < fromLines.length; i++) + { + MCommissionLine line = new MCommissionLine (getCtx(), 0, get_TrxName()); + PO.copyValues(fromLines[i], line, getAD_Client_ID(), getAD_Org_ID()); + line.setC_Commission_ID (getC_Commission_ID()); + line.setC_CommissionLine_ID (0); // new + if (line.save()) + count++; + } + if (fromLines.length != count) + log.log(Level.SEVERE, "copyLinesFrom - Line difference - From=" + fromLines.length + " <> Saved=" + count); + return count; + } // copyLinesFrom + +} // MCommission diff --git a/base/src/org/compiere/model/MCommissionAmt.java b/base/src/org/compiere/model/MCommissionAmt.java new file mode 100644 index 0000000000..78aed700c1 --- /dev/null +++ b/base/src/org/compiere/model/MCommissionAmt.java @@ -0,0 +1,188 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Commission Run Amounts + * + * @author Jorg Janke + * @version $Id: MCommissionAmt.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MCommissionAmt extends X_C_CommissionAmt +{ + /** + * Standard Constructor + * @param ctx context + * @param C_CommissionAmt_ID id + * @param trxName transaction + */ + public MCommissionAmt(Properties ctx, int C_CommissionAmt_ID, String trxName) + { + super(ctx, C_CommissionAmt_ID, trxName); + if (C_CommissionAmt_ID == 0) + { + // setC_CommissionRun_ID (0); + // setC_CommissionLine_ID (0); + setActualQty (Env.ZERO); + setCommissionAmt (Env.ZERO); + setConvertedAmt (Env.ZERO); + } + } // MCommissionAmt + + /** + * Parent Constructor + * @param run parent + * @param C_CommissionLine_ID line + */ + public MCommissionAmt (MCommissionRun run, int C_CommissionLine_ID) + { + this (run.getCtx(), 0, run.get_TrxName()); + setClientOrg (run); + setC_CommissionRun_ID (run.getC_CommissionRun_ID()); + setC_CommissionLine_ID (C_CommissionLine_ID); + } // MCommissionAmt + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MCommissionAmt(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MCommissionAmt + + /** + * Get Details + * @return array of details + */ + public MCommissionDetail[] getDetails() + { + String sql = "SELECT * FROM C_CommissionDetail WHERE C_CommissionAmt_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_CommissionAmt_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MCommissionDetail(getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + // Convert + MCommissionDetail[] retValue = new MCommissionDetail[list.size()]; + list.toArray(retValue); + return retValue; + } // getDetails + + /** + * Calculate Commission + */ + public void calculateCommission() + { + MCommissionDetail[] details = getDetails(); + BigDecimal ConvertedAmt = Env.ZERO; + BigDecimal ActualQty = Env.ZERO; + for (int i = 0; i < details.length; i++) + { + MCommissionDetail detail = details[i]; + BigDecimal amt = detail.getConvertedAmt(); + if (amt == null) + amt = Env.ZERO; + ConvertedAmt = ConvertedAmt.add(amt); + ActualQty = ActualQty.add(detail.getActualQty()); + } + setConvertedAmt(ConvertedAmt); + setActualQty(ActualQty); + // + MCommissionLine cl = new MCommissionLine(getCtx(), getC_CommissionLine_ID(), get_TrxName()); + // Qty + BigDecimal qty = getActualQty().subtract(cl.getQtySubtract()); + if (cl.isPositiveOnly() && qty.signum() < 0) + qty = Env.ZERO; + qty = qty.multiply(cl.getQtyMultiplier()); + // Amt + BigDecimal amt = getConvertedAmt().subtract(cl.getAmtSubtract()); + if (cl.isPositiveOnly() && amt.signum() < 0) + amt = Env.ZERO; + amt = amt.multiply(cl.getAmtMultiplier()); + // + setCommissionAmt(amt.add(qty)); + } // calculateCommission + + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!newRecord) + updateRunHeader(); + return success; + } // afterSave + + /** + * After Delete + * @param success success + * @return success + */ + protected boolean afterDelete (boolean success) + { + if (success) + updateRunHeader(); + return success; + } // afterDelete + + /** + * Update Amt Header + */ + private void updateRunHeader() + { + MCommissionRun run = new MCommissionRun(getCtx(), getC_CommissionRun_ID(),get_TrxName()); + run.updateFromAmt(); + run.save(); + } // updateRunHeader + +} // MCommissionAmt diff --git a/base/src/org/compiere/model/MCommissionDetail.java b/base/src/org/compiere/model/MCommissionDetail.java new file mode 100644 index 0000000000..2440171051 --- /dev/null +++ b/base/src/org/compiere/model/MCommissionDetail.java @@ -0,0 +1,138 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Commission Run Amount Detail Model + * + * @author Jorg Janke + * @version $Id: MCommissionDetail.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MCommissionDetail extends X_C_CommissionDetail +{ + /** + * Persistency Constructor + * @param ctx context + * @param ignored ignored + * @param trxName transaction + */ + public MCommissionDetail (Properties ctx, int ignored, String trxName) + { + super(ctx, 0, trxName); + if (ignored != 0) + throw new IllegalArgumentException("Multi-Key"); + } // MCommissionDetail + + /** + * Parent Constructor + * @param amt commission amt + * @param C_Currency_ID currency + * @param Amt amount + * @param Qty quantity + */ + public MCommissionDetail (MCommissionAmt amt, int C_Currency_ID, + BigDecimal Amt, BigDecimal Qty) + { + super (amt.getCtx(), 0, amt.get_TrxName()); + setClientOrg(amt); + setC_CommissionAmt_ID(amt.getC_CommissionAmt_ID()); + setC_Currency_ID (C_Currency_ID); + setActualAmt (Amt); + setActualQty (Qty); + setConvertedAmt (Env.ZERO); + } // MCommissionDetail + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MCommissionDetail(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MCommissionDetail + + /** + * Set Line IDs + * @param C_OrderLine_ID order + * @param C_InvoiceLine_ID invoice + */ + public void setLineIDs (int C_OrderLine_ID, int C_InvoiceLine_ID) + { + if (C_OrderLine_ID != 0) + setC_OrderLine_ID(C_OrderLine_ID); + if (C_InvoiceLine_ID != 0) + setC_InvoiceLine_ID(C_InvoiceLine_ID); + } // setLineIDs + + + /** + * Set Converted Amt + * @param date for conversion + */ + public void setConvertedAmt (Timestamp date) + { + BigDecimal amt = MConversionRate.convertBase(getCtx(), + getActualAmt(), getC_Currency_ID(), date, 0, // type + getAD_Client_ID(), getAD_Org_ID()); + if (amt != null) + setConvertedAmt(amt); + } // setConvertedAmt + + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!newRecord) + updateAmtHeader(); + return success; + } // afterSave + + /** + * After Delete + * @param success success + * @return success + */ + protected boolean afterDelete (boolean success) + { + if (success) + updateAmtHeader(); + return success; + } // afterDelete + + /** + * Update Amt Header + */ + private void updateAmtHeader() + { + MCommissionAmt amt = new MCommissionAmt(getCtx(), getC_CommissionAmt_ID(), get_TrxName()); + amt.calculateCommission(); + amt.save(); + } // updateAmtHeader + +} // MCommissionDetail diff --git a/base/src/org/compiere/model/MCommissionLine.java b/base/src/org/compiere/model/MCommissionLine.java new file mode 100644 index 0000000000..34cc42e14e --- /dev/null +++ b/base/src/org/compiere/model/MCommissionLine.java @@ -0,0 +1,67 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + + +/** + * Commission Line Model + * + * @author Jorg Janke + * @version $Id: MCommissionLine.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MCommissionLine extends X_C_CommissionLine +{ + /** + * Standard Constructor + * @param ctx context + * @param C_CommissionLine_ID id + * @param trxName transaction + */ + public MCommissionLine(Properties ctx, int C_CommissionLine_ID, String trxName) + { + super(ctx, C_CommissionLine_ID, trxName); + if (C_CommissionLine_ID == 0) + { + // setC_Commission_ID (0); + setLine (0); // @SQL=SELECT NVL(MAX(Line),0)+10 AS DefaultValue FROM C_CommissionLine WHERE C_Commission_ID=@C_Commission_ID@ + setAmtMultiplier (Env.ZERO); + setAmtSubtract (Env.ZERO); + setCommissionOrders (false); + setIsPositiveOnly (false); + setQtyMultiplier (Env.ZERO); + setQtySubtract (Env.ZERO); + } + } // MCommissionLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MCommissionLine(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MCommissionLine + + + +} // MCommissionLine diff --git a/base/src/org/compiere/model/MCommissionRun.java b/base/src/org/compiere/model/MCommissionRun.java new file mode 100644 index 0000000000..3b9d74e8e6 --- /dev/null +++ b/base/src/org/compiere/model/MCommissionRun.java @@ -0,0 +1,130 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Commission Run + * + * @author Jorg Janke + * @version $Id: MCommissionRun.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MCommissionRun extends X_C_CommissionRun +{ + /** + * Standard Constructor + * @param ctx context + * @param C_CommissionRun_ID id + * @param trxName transaction + */ + public MCommissionRun (Properties ctx, int C_CommissionRun_ID, String trxName) + { + super(ctx, C_CommissionRun_ID, trxName); + if (C_CommissionRun_ID == 0) + { + // setC_Commission_ID (0); + // setDocumentNo (null); + // setStartDate (new Timestamp(System.currentTimeMillis())); + setGrandTotal (Env.ZERO); + setProcessed (false); + } + } // MCommissionRun + + /** + * Parent Constructor + * @param commission parent + */ + public MCommissionRun (MCommission commission) + { + this (commission.getCtx(), 0, commission.get_TrxName()); + setClientOrg (commission); + setC_Commission_ID (commission.getC_Commission_ID()); + } // MCommissionRun + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MCommissionRun(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MCommissionRun + + /** + * Get Amounts + * @return array of amounts + */ + public MCommissionAmt[] getAmts() + { + String sql = "SELECT * FROM C_CommissionAmt WHERE C_CommissionRun_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_CommissionRun_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MCommissionAmt(getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + // Convert + MCommissionAmt[] retValue = new MCommissionAmt[list.size()]; + list.toArray(retValue); + return retValue; + } // getAmts + + /** + * Update From Amt + */ + public void updateFromAmt() + { + MCommissionAmt[] amts = getAmts(); + BigDecimal GrandTotal = Env.ZERO; + for (int i = 0; i < amts.length; i++) + { + MCommissionAmt amt = amts[i]; + GrandTotal = GrandTotal.add(amt.getCommissionAmt()); + } + setGrandTotal(GrandTotal); + } // updateFromAmt + +} // MCommissionRun diff --git a/base/src/org/compiere/model/MContactInterest.java b/base/src/org/compiere/model/MContactInterest.java new file mode 100644 index 0000000000..568c9b302c --- /dev/null +++ b/base/src/org/compiere/model/MContactInterest.java @@ -0,0 +1,248 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Business Partner Contact Interest. + * Adempiere compies with spamming laws. + * If the opt out date is set (by the user), + * you should not subscribe the user again. + * Internally, the isActive flag is used. + * + * @author Jorg Janke + * @version $Id: MContactInterest.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MContactInterest extends X_R_ContactInterest +{ + /** + * Get Contact Interest + * @param ctx context + * @param R_InterestArea_ID interest ares + * @param AD_User_ID user + * @param isActive create as active + * @param trxName transaction + * @return Contact Interest + */ + public static MContactInterest get (Properties ctx, + int R_InterestArea_ID, int AD_User_ID, boolean isActive, String trxName) + { + MContactInterest retValue = null; + String sql = "SELECT * FROM R_ContactInterest " + + "WHERE R_InterestArea_ID=? AND AD_User_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, R_InterestArea_ID); + pstmt.setInt(2, AD_User_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + retValue = new MContactInterest (ctx, rs, trxName); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (retValue == null) + { + retValue = new MContactInterest (ctx, R_InterestArea_ID, AD_User_ID, + isActive, trxName); + s_log.fine("NOT found - " + retValue); + } + else + s_log.fine("Found - " + retValue); + return retValue; + } // get + + + /************************************************************************** + * Persistency Constructor + * @param ctx context + * @param ignored ignored + * @param trxName transaction + */ + public MContactInterest (Properties ctx, int ignored, String trxName) + { + super(ctx, 0, trxName); + if (ignored != 0) + throw new IllegalArgumentException("Multi-Key"); + } // MContactInterest + + /** + * Constructor + * @param ctx context + * @param R_InterestArea_ID interest area + * @param AD_User_ID partner contact + * @param isActive create as active + * @param trxName transaction + */ + public MContactInterest (Properties ctx, int R_InterestArea_ID, int AD_User_ID, + boolean isActive, String trxName) + { + super(ctx, 0, trxName); + setR_InterestArea_ID (R_InterestArea_ID); + setAD_User_ID (AD_User_ID); + setIsActive(isActive); + } // MContactInterest + + /** + * Create & Load existing Persistent Object. + * @param ctx context + * @param rs load from current result set position (no navigation, not closed) + * @param trxName transaction + */ + public MContactInterest (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MContactInterest + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MContactInterest.class); + + /** + * Set OptOut Date + * User action only. + * @param OptOutDate date + */ + public void setOptOutDate (Timestamp OptOutDate) + { + if (OptOutDate == null) + OptOutDate = new Timestamp(System.currentTimeMillis()); + log.fine("" + OptOutDate); + super.setOptOutDate(OptOutDate); + setIsActive(false); + } // setOptOutDate + + /** + * Unsubscribe. + * User action only. + */ + public void unsubscribe() + { + setOptOutDate(null); + } // unsubscribe + + /** + * Is Opted Out + * @return true if opted out + */ + public boolean isOptOut() + { + return getOptOutDate() != null; + } // isOptOut + + /** + * Set Subscribe Date + * User action only. + * @param SubscribeDate date + */ + public void setSubscribeDate (Timestamp SubscribeDate) + { + if (SubscribeDate == null) + SubscribeDate = new Timestamp(System.currentTimeMillis()); + log.fine("" + SubscribeDate); + super.setSubscribeDate(SubscribeDate); + super.setOptOutDate(null); + setIsActive(true); + } // setSubscribeDate + + /** + * Subscribe + * User action only. + */ + public void subscribe() + { + setSubscribeDate(null); + if (!isActive()) + setIsActive(true); + } // subscribe + + /** + * Subscribe. + * User action only. + * @param subscribe subscribe + */ + public void subscribe (boolean subscribe) + { + if (subscribe) + setSubscribeDate(null); + else + setOptOutDate(null); + } // subscribe + + + /** + * Is Subscribed. + * Active is set internally, + * the opt out date is set by the user via the web UI. + * @return true if subscribed + */ + public boolean isSubscribed() + { + return isActive() && getOptOutDate() == null; + } // isSubscribed + + + /** + * String representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MContactInterest[") + .append("R_InterestArea_ID=").append(getR_InterestArea_ID()) + .append(",AD_User_ID=").append(getAD_User_ID()) + .append(",Subscribed=").append(isSubscribed()) + .append ("]"); + return sb.toString (); + } // toString + + /************************************************************************** + * @param args ignored + */ + public static void main (String[] args) + { + org.compiere.Adempiere.startup(true); + int R_InterestArea_ID = 1000002; + int AD_User_ID = 1000002; + MContactInterest ci = MContactInterest.get(Env.getCtx(), R_InterestArea_ID, AD_User_ID, false, null); + ci.subscribe(); + ci.save(); + // + ci = MContactInterest.get(Env.getCtx(), R_InterestArea_ID, AD_User_ID, false, null); + } // main + + +} // MContactInterest diff --git a/base/src/org/compiere/model/MContainer.java b/base/src/org/compiere/model/MContainer.java new file mode 100644 index 0000000000..a2acedd8a0 --- /dev/null +++ b/base/src/org/compiere/model/MContainer.java @@ -0,0 +1,532 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Container Model + * + * @author Yves Sandfort + * @version $Id: MContainer.java,v 1.20 2006/09/05 23:22:53 comdivision Exp $ + */ +public class MContainer extends X_CM_Container +{ + + /** + * Copy Stage into Container + * + * @param project WebProject + * @param stage Stage to copy from + * @param path Relative URL to it + * @return Container + */ + public static MContainer copy (MWebProject project, MCStage stage, + String path) + { + MContainer cc = getDirect (stage.getCtx(), stage.getCM_CStage_ID (), + stage.get_TrxName ()); + if (cc == null) // new + cc = new MContainer (stage.getCtx (), 0, stage.get_TrxName ()); + cc.setStage (project, stage, path); + cc.save (); + if (!stage.isSummary ()) + { + cc.updateElements (project, stage, stage.get_TrxName ()); + cc.updateTTables (project, stage, stage.get_TrxName ()); + } + return cc; + } // copy + + /** + * Get Container directly from DB (not cached) + * + * @param ctx context + * @param CM_Container_ID Container ID + * @param trxName transaction + * @return Container or null + */ + public static MContainer getDirect (Properties ctx, int CM_Container_ID, + String trxName) + { + MContainer cc = null; + PreparedStatement pstmt = null; + String sql = "SELECT * FROM CM_Container WHERE CM_Container_ID=?"; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, CM_Container_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + cc = new MContainer (ctx, rs, trxName); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return cc; + } // getDirect + + /** + * Get Containers + * + * @param project + * Project to use + * @return stages + */ + public static MContainer[] getContainers (MWebProject project) + { + ArrayList list = new ArrayList (); + PreparedStatement pstmt = null; + String sql = "SELECT * FROM CM_Container WHERE CM_WebProject_ID=? ORDER BY CM_Container_ID"; + try + { + pstmt = DB.prepareStatement (sql, project.get_TrxName ()); + pstmt.setInt (1, project.getCM_WebProject_ID ()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + list.add (new MContainer (project.getCtx (), rs, project + .get_TrxName ())); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MContainer[] retValue = new MContainer[list.size ()]; + list.toArray (retValue); + return retValue; + } // getContainers + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MContainer.class); + + + /*************************************************************************** + * Standard Constructor + * + * @param ctx context + * @param CM_Container_ID id + * @param trxName transaction + */ + public MContainer (Properties ctx, int CM_Container_ID, String trxName) + { + super (ctx, CM_Container_ID, trxName); + if (CM_Container_ID == 0) + { + setIsValid(false); + setIsIndexed(false); + setIsSecure(false); + setIsSummary(false); + } + } // MContainer + + /** + * Load Constructor + * + * @param ctx + * context + * @param rs + * result set + * @param trxName + * transaction + */ + public MContainer (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MContainer + + /** Web Project */ + private MWebProject m_project = null; + + /** Stage Source */ + private MCStage m_stage = null; + + /** Template */ + private MTemplate m_template = null; + + /** + * Get Web Project + * + * @return web project + */ + public MWebProject getWebProject () + { + if (m_project == null) + m_project = MWebProject.get (getCtx (), getCM_WebProject_ID ()); + return m_project; + } // getWebProject + + /** + * Get Template from Cache, or load it + * @return Template + */ + public MTemplate getTemplate() + { + if (getCM_Template_ID()>0 && m_template==null) + m_template = MTemplate.get(getCtx(), getCM_Template_ID(), null); + return m_template; + } // getTemplate + + /** + * Get AD_Tree_ID + * + * @return tree + */ + public int getAD_Tree_ID () + { + return getWebProject ().getAD_TreeCMC_ID (); + } // getAD_Tree_ID; + + /** + * Set/Copy Stage + * + * @param project + * parent + * @param stage + * stage + * @param path + * path + */ + protected void setStage (MWebProject project, MCStage stage, String path) + { + m_stage = stage; + PO.copyValues (stage, this); + setAD_Client_ID (project.getAD_Client_ID ()); + setAD_Org_ID (project.getAD_Org_ID ()); + setIsActive (stage.isActive ()); + setCM_ContainerLink_ID (stage.getCM_CStageLink_ID ()); + // + setRelativeURL (path + stage.getRelativeURL ()); + // + if (getMeta_Author () == null || getMeta_Author ().length () == 0) + setMeta_Author (project.getMeta_Author ()); + if (getMeta_Content () == null || getMeta_Content ().length () == 0) + setMeta_Content (project.getMeta_Content ()); + if (getMeta_Copyright () == null || getMeta_Copyright ().length () == 0) + setMeta_Copyright (project.getMeta_Copyright ()); + if (getMeta_Publisher () == null || getMeta_Publisher ().length () == 0) + setMeta_Publisher (project.getMeta_Publisher ()); + if (getMeta_RobotsTag () == null || getMeta_RobotsTag ().length () == 0) + setMeta_RobotsTag (project.getMeta_RobotsTag ()); + } // setStage + + /** + * Update Elements in Container from Stage + * + * @param project + * project + * @param stage + * stage + * @param trxName + * Transaction + */ + protected void updateElements (MWebProject project, MCStage stage, + String trxName) + { + org.compiere.cm.CacheHandler thisHandler = new org.compiere.cm.CacheHandler ( + org.compiere.cm.CacheHandler.convertJNPURLToCacheURL (getCtx () + .getProperty ("java.naming.provider.url")), log, getCtx (), + get_TrxName ()); + // First update the new ones... + int[] tableKeys = X_CM_CStage_Element.getAllIDs ("CM_CStage_Element", + "CM_CStage_ID=" + stage.get_ID (), trxName); + if (tableKeys != null && tableKeys.length > 0) + { + for (int i = 0; i < tableKeys.length; i++) + { + X_CM_CStage_Element thisStageElement = new X_CM_CStage_Element ( + project.getCtx (), tableKeys[i], trxName); + int[] thisContainerElementKeys = X_CM_Container_Element + .getAllIDs ("CM_Container_Element", "CM_Container_ID=" + + stage.get_ID () + " AND Name LIKE '" + + thisStageElement.getName () + "'", trxName); + X_CM_Container_Element thisContainerElement; + if (thisContainerElementKeys != null + && thisContainerElementKeys.length > 0) + { + thisContainerElement = new X_CM_Container_Element (project + .getCtx (), thisContainerElementKeys[0], trxName); + } + else + { + thisContainerElement = new X_CM_Container_Element (project + .getCtx (), 0, trxName); + } + thisContainerElement.setCM_Container_ID (stage.get_ID ()); + X_CM_CStage_Element stageElement = new X_CM_CStage_Element ( + project.getCtx (), tableKeys[i], trxName); + thisContainerElement.setName (stageElement.getName ()); + thisContainerElement.setDescription (stageElement.getDescription()); + thisContainerElement.setHelp (stageElement.getHelp ()); + thisContainerElement.setIsActive (stageElement.isActive ()); + thisContainerElement.setIsValid (stageElement.isValid ()); + String contentHTML = thisStageElement.getContentHTML (); + thisContainerElement.setContentHTML (contentHTML); + // PO.copyValues(new + // X_CM_CStage_Element(project.getCtx(),tableKeys[i],trxName), + // thisContainerElement); + thisContainerElement.save (trxName); + // Remove Container from cache + thisHandler.cleanContainerElement (thisContainerElement + .get_ID ()); + } + } + // Now we are checking the existing ones to delete the unneeded ones... + tableKeys = X_CM_Container_Element.getAllIDs ("CM_Container_Element", + "CM_Container_ID=" + stage.get_ID (), trxName); + if (tableKeys != null && tableKeys.length > 0) + { + for (int i = 0; i < tableKeys.length; i++) + { + X_CM_Container_Element thisContainerElement = new X_CM_Container_Element ( + project.getCtx (), tableKeys[i], trxName); + int[] thisCStageElementKeys = X_CM_CStage_Element + .getAllIDs ("CM_CStage_Element", "CM_CStage_ID=" + + stage.get_ID () + " AND Name LIKE '" + + thisContainerElement.getName () + "'", trxName); + // If we cannot find a representative in the Stage we will delete from production + if (thisCStageElementKeys == null + || thisCStageElementKeys.length < 1) + { + // First delete it from cache, then delete the record itself + thisHandler.cleanContainerElement (thisContainerElement + .get_ID ()); + thisContainerElement.delete (true); + } + } + } + } + + /** + * Update Elements in Container from Stage + * + * @param project + * project + * @param stage + * stage + * @param trxName + * Transaction + */ + protected void updateTTables (MWebProject project, MCStage stage, + String trxName) + { + int[] tableKeys = X_CM_CStageTTable.getAllIDs ("CM_CStageTTable", + "CM_CStage_ID=" + stage.get_ID (), trxName); + if (tableKeys != null && tableKeys.length > 0) + { + for (int i = 0; i < tableKeys.length; i++) + { + X_CM_CStageTTable thisStageTTable = new X_CM_CStageTTable ( + project.getCtx (), tableKeys[i], trxName); + int[] thisContainerTTableKeys = X_CM_ContainerTTable.getAllIDs ( + "CM_ContainerTTable", "CM_Container_ID=" + stage.get_ID () + + " AND CM_TemplateTable_ID=" + + thisStageTTable.getCM_TemplateTable_ID (), trxName); + X_CM_ContainerTTable thisContainerTTable; + if (thisContainerTTableKeys != null + && thisContainerTTableKeys.length > 0) + { + thisContainerTTable = new X_CM_ContainerTTable (project + .getCtx (), thisContainerTTableKeys[0], trxName); + } + else + { + thisContainerTTable = new X_CM_ContainerTTable (project + .getCtx (), 0, trxName); + } + thisContainerTTable.setCM_Container_ID (stage.get_ID ()); + PO.copyValues (new X_CM_CStageTTable (project.getCtx (), + tableKeys[i], trxName), thisContainerTTable); + thisContainerTTable.save (trxName); + } + } + } + + /** + * SaveNew getID + * + * @return ID + */ + protected int saveNew_getID () + { + if (m_stage != null) + return m_stage.getCM_CStage_ID (); + return 0; + } // saveNew_getID + + /** + * String Representation + * + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MContainer[").append (get_ID ()) + .append ("-").append (getName ()).append ("]"); + return sb.toString (); + } // toString + + /** + * After Save. Insert - create tree + * + * @param newRecord + * insert + * @param success + * save success + * @return true if saved + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + if (newRecord) + { + StringBuffer sb = new StringBuffer ( + "INSERT INTO AD_TreeNodeCMC " + + "(AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, " + + "AD_Tree_ID, Node_ID, Parent_ID, SeqNo) " + "VALUES (") + .append (getAD_Client_ID ()).append ( + ",0, 'Y', SysDate, 0, SysDate, 0,").append ( + getAD_Tree_ID ()).append (",").append (get_ID ()).append ( + ", 0, 999)"); + int no = DB.executeUpdate (sb.toString (), get_TrxName ()); + if (no > 0) + log.fine ("#" + no + " - TreeType=CMC"); + else + log.warning ("#" + no + " - TreeType=CMC"); + return no > 0; + } + return success; + } // afterSave + + protected MContainerElement[] getAllElements() + { + int elements[] = MContainerElement.getAllIDs("CM_Container_Element", "CM_Container_ID=" + get_ID(), get_TrxName()); + if (elements.length>0) + { + MContainerElement[] containerElements = new MContainerElement[elements.length]; + for (int i=0;i 0; + } + + /** + * After Delete + * + * @param success + * @return deleted + */ + protected boolean afterDelete (boolean success) + { + if (!success) + return success; + // + StringBuffer sb = new StringBuffer ("DELETE FROM AD_TreeNodeCMC ") + .append (" WHERE Node_ID=").append (get_IDOld ()).append ( + " AND AD_Tree_ID=").append (getAD_Tree_ID ()); + int no = DB.executeUpdate (sb.toString (), get_TrxName ()); + // If 0 than there is nothing to delete which is okay. + if (no > 0) + log.fine ("#" + no + " - TreeType=CMC"); + else + log.warning ("#" + no + " - TreeType=CMC"); + return true; + } // afterDelete + + /** + * reIndex + * @param newRecord + */ + public void reIndex(boolean newRecord) + { + String [] toBeIndexed = new String[8]; + toBeIndexed[0] = this.getName(); + toBeIndexed[1] = this.getDescription(); + toBeIndexed[2] = this.getRelativeURL(); + toBeIndexed[3] = this.getMeta_Author(); + toBeIndexed[4] = this.getMeta_Copyright(); + toBeIndexed[5] = this.getMeta_Description(); + toBeIndexed[6] = this.getMeta_Keywords(); + toBeIndexed[7] = this.getMeta_Publisher(); + MIndex.reIndex (newRecord, toBeIndexed, getCtx(), getAD_Client_ID(), get_Table_ID(), get_ID(), getCM_WebProject_ID(), this.getUpdated()); + MContainerElement[] theseElements = getAllElements(); + if (theseElements!=null) + for (int i=0;i fifo = new ArrayList(); + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, product.getM_Product_ID()); + if (AD_Org_ID != 0) + pstmt.setInt (2, AD_Org_ID); + else if (M_AttributeSetInstance_ID != 0) + pstmt.setInt (2, M_AttributeSetInstance_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + BigDecimal movementQty = rs.getBigDecimal(1); + int M_Transaction_ID = rs.getInt(10); + if (M_Transaction_ID == oldTransaction_ID) + continue; // assuming same price for receipt + M_Transaction_ID = oldTransaction_ID; + // + BigDecimal matchQty = rs.getBigDecimal(2); + if (matchQty == null) // out (negative) + { + if (fifo.size() > 0) + { + QtyCost pp = (QtyCost)fifo.get(0); + pp.Qty = pp.Qty.add(movementQty); + BigDecimal remainder = pp.Qty; + if (remainder.signum() == 0) + fifo.remove(0); + else + { + while (remainder.signum() != 0) + { + if (fifo.size() == 1) // Last + { + pp.Cost = Env.ZERO; + remainder = Env.ZERO; + } + else + { + fifo.remove(0); + pp = (QtyCost)fifo.get(0); + pp.Qty = pp.Qty.add(movementQty); + remainder = pp.Qty; + } + } + } + } + else + { + QtyCost pp = new QtyCost (movementQty, Env.ZERO); + fifo.add(pp); + } + s_log.finer("Movement=" + movementQty + ", Size=" + fifo.size()); + continue; + } + // Assumption: everything is matched + BigDecimal price = rs.getBigDecimal(4); + int C_Currency_ID = rs.getInt(5); + Timestamp DateAcct = rs.getTimestamp(6); + int C_ConversionType_ID = rs.getInt(7); + int Client_ID = rs.getInt(8); + int Org_ID = rs.getInt(9); + BigDecimal cost = MConversionRate.convert(product.getCtx(), price, + C_Currency_ID, as.getC_Currency_ID(), + DateAcct, C_ConversionType_ID, Client_ID, Org_ID); + + // Add Stock + boolean used = false; + if (fifo.size() == 1) + { + QtyCost pp = (QtyCost)fifo.get(0); + if (pp.Qty.signum() < 0) + { + pp.Qty = pp.Qty.add(movementQty); + if (pp.Qty.signum() == 0) + fifo.remove(0); + else + pp.Cost = cost; + used = true; + } + + } + if (!used) + { + QtyCost pp = new QtyCost (movementQty, cost); + fifo.add(pp); + } + s_log.finer("Movement=" + movementQty + ", Size=" + fifo.size()); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (fifo.size() == 0) + return null; + QtyCost pp = (QtyCost)fifo.get(0); + s_log.finer(product.getName() + " = " + pp.Cost); + return pp.Cost; + } // calculateFiFo + + /** + * Calculate LiFo costs + * @param product product + * @param M_AttributeSetInstance_ID asi + * @param as acct schema + * @param AD_Org_ID org + * @return costs or null + */ + public static BigDecimal calculateLiFo (MProduct product, int M_AttributeSetInstance_ID, + MAcctSchema as, int AD_Org_ID) + { + String sql = "SELECT t.MovementQty, mi.Qty, il.QtyInvoiced, il.PriceActual," + + " i.C_Currency_ID, i.DateAcct, i.C_ConversionType_ID, i.AD_Client_ID, i.AD_Org_ID, t.M_Transaction_ID " + + "FROM M_Transaction t" + + " INNER JOIN M_MatchInv mi ON (t.M_InOutLine_ID=mi.M_InOutLine_ID)" + + " INNER JOIN C_InvoiceLine il ON (mi.C_InvoiceLine_ID=il.C_InvoiceLine_ID)" + + " INNER JOIN C_Invoice i ON (il.C_Invoice_ID=i.C_Invoice_ID) " + + "WHERE t.M_Product_ID=?"; + if (AD_Org_ID != 0) + sql += " AND t.AD_Org_ID=?"; + else if (M_AttributeSetInstance_ID != 0) + sql += " AND t.M_AttributeSetInstance_ID=?"; + // Starting point? + sql += " ORDER BY t.M_Transaction_ID DESC"; + + PreparedStatement pstmt = null; + // + int oldTransaction_ID = 0; + ArrayList lifo = new ArrayList(); + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, product.getM_Product_ID()); + if (AD_Org_ID != 0) + pstmt.setInt (2, AD_Org_ID); + else if (M_AttributeSetInstance_ID != 0) + pstmt.setInt (2, M_AttributeSetInstance_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + BigDecimal movementQty = rs.getBigDecimal(1); + int M_Transaction_ID = rs.getInt(10); + if (M_Transaction_ID == oldTransaction_ID) + continue; // assuming same price for receipt + M_Transaction_ID = oldTransaction_ID; + // + BigDecimal matchQty = rs.getBigDecimal(2); + if (matchQty == null) // out (negative) + { + if (lifo.size() > 0) + { + QtyCost pp = (QtyCost)lifo.get(lifo.size()-1); + pp.Qty = pp.Qty.add(movementQty); + BigDecimal remainder = pp.Qty; + if (remainder.signum() == 0) + lifo.remove(lifo.size()-1); + else + { + while (remainder.signum() != 0) + { + if (lifo.size() == 1) // Last + { + pp.Cost = Env.ZERO; + remainder = Env.ZERO; + } + else + { + lifo.remove(lifo.size()-1); + pp = (QtyCost)lifo.get(lifo.size()-1); + pp.Qty = pp.Qty.add(movementQty); + remainder = pp.Qty; + } + } + } + } + else + { + QtyCost pp = new QtyCost (movementQty, Env.ZERO); + lifo.add(pp); + } + s_log.finer("Movement=" + movementQty + ", Size=" + lifo.size()); + continue; + } + // Assumption: everything is matched + BigDecimal price = rs.getBigDecimal(4); + int C_Currency_ID = rs.getInt(5); + Timestamp DateAcct = rs.getTimestamp(6); + int C_ConversionType_ID = rs.getInt(7); + int Client_ID = rs.getInt(8); + int Org_ID = rs.getInt(9); + BigDecimal cost = MConversionRate.convert(product.getCtx(), price, + C_Currency_ID, as.getC_Currency_ID(), + DateAcct, C_ConversionType_ID, Client_ID, Org_ID); + // + QtyCost pp = new QtyCost (movementQty, cost); + lifo.add(pp); + s_log.finer("Movement=" + movementQty + ", Size=" + lifo.size()); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (lifo.size() == 0) + return null; + QtyCost pp = (QtyCost)lifo.get(lifo.size()-1); + s_log.finer(product.getName() + " = " + pp.Cost); + return pp.Cost; + } // calculateLiFo + + + /************************************************************************** + * MCost Qty-Cost Pair + */ + static class QtyCost + { + /** + * Constructor + * @param qty qty + * @param cost cost + */ + public QtyCost (BigDecimal qty, BigDecimal cost) + { + Qty = qty; + Cost = cost; + } + /** Qty */ + public BigDecimal Qty = null; + /** Cost */ + public BigDecimal Cost = null; + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("Qty=").append(Qty) + .append (",Cost=").append (Cost); + return sb.toString (); + } // toString + } // QtyCost + + + /** + * Get/Create Cost Record. + * CostingLevel is not validated + * @param product product + * @param M_AttributeSetInstance_ID costing level asi + * @param as accounting schema + * @param AD_Org_ID costing level org + * @param M_CostElement_ID element + * @return cost price or null + */ + public static MCost get (MProduct product, int M_AttributeSetInstance_ID, + MAcctSchema as, int AD_Org_ID, int M_CostElement_ID) + { + MCost cost = null; + String sql = "SELECT * " + + "FROM M_Cost c " + + "WHERE AD_Client_ID=? AND AD_Org_ID=?" + + " AND M_Product_ID=?" + + " AND M_AttributeSetInstance_ID=?" + + " AND M_CostType_ID=? AND C_AcctSchema_ID=?" + + " AND M_CostElement_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, product.get_TrxName()); + pstmt.setInt (1, product.getAD_Client_ID()); + pstmt.setInt (2, AD_Org_ID); + pstmt.setInt (3, product.getM_Product_ID()); + pstmt.setInt (4, M_AttributeSetInstance_ID); + pstmt.setInt (5, as.getM_CostType_ID()); + pstmt.setInt (6, as.getC_AcctSchema_ID()); + pstmt.setInt (7, M_CostElement_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + cost = new MCost (product.getCtx(), rs, product.get_TrxName()); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // New + if (cost == null) + cost = new MCost (product, M_AttributeSetInstance_ID, + as, AD_Org_ID, M_CostElement_ID); + return cost; + } // get + + /** + * Get Costs + * @param ctx context + * @param AD_Client_ID client + * @param AD_Org_ID org + * @param M_Product_ID product + * @param M_CostType_ID cost type + * @param C_AcctSchema_ID as + * @param M_CostElement_ID cost element + * @param M_AttributeSetInstance_ID asi + * @return cost or null + */ + public static MCost get (Properties ctx, int AD_Client_ID, int AD_Org_ID, int M_Product_ID, + int M_CostType_ID, int C_AcctSchema_ID, int M_CostElement_ID, + int M_AttributeSetInstance_ID) + { + MCost retValue = null; + String sql = "SELECT * FROM M_Cost " + + "WHERE AD_Client_ID=? AND AD_Org_ID=? AND M_Product_ID=?" + + " AND M_CostType_ID=? AND C_AcctSchema_ID=? AND M_CostElement_ID=?" + + " AND M_AttributeSetInstance_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, AD_Client_ID); + pstmt.setInt (2, AD_Org_ID); + pstmt.setInt (3, M_Product_ID); + pstmt.setInt (4, M_CostType_ID); + pstmt.setInt (5, C_AcctSchema_ID); + pstmt.setInt (6, M_CostElement_ID); + pstmt.setInt (7, M_AttributeSetInstance_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + retValue = new MCost (ctx, rs, null); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return retValue; + } // get + + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MCost.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param ignored multi-key + * @param trxName trx + */ + public MCost (Properties ctx, int ignored, String trxName) + { + super (ctx, ignored, trxName); + if (ignored == 0) + { + // setC_AcctSchema_ID (0); + // setM_CostElement_ID (0); + // setM_CostType_ID (0); + // setM_Product_ID (0); + setM_AttributeSetInstance_ID(0); + // + setCurrentCostPrice (Env.ZERO); + setFutureCostPrice (Env.ZERO); + setCurrentQty (Env.ZERO); + setCumulatedAmt (Env.ZERO); + setCumulatedQty (Env.ZERO); + } + else + throw new IllegalArgumentException("Multi-Key"); + } // MCost + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MCost (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + m_manual = false; + } // MCost + + /** + * Parent Constructor + * @param product Product + * @param M_AttributeSetInstance_ID asi + * @param as Acct Schema + * @param AD_Org_ID org + * @param M_CostElement_ID cost element + */ + public MCost (MProduct product, int M_AttributeSetInstance_ID, + MAcctSchema as, int AD_Org_ID, int M_CostElement_ID) + { + this (product.getCtx(), 0, product.get_TrxName()); + setClientOrg(product.getAD_Client_ID(), AD_Org_ID); + setC_AcctSchema_ID(as.getC_AcctSchema_ID()); + setM_CostType_ID(as.getM_CostType_ID()); + setM_Product_ID(product.getM_Product_ID()); + setM_AttributeSetInstance_ID(M_AttributeSetInstance_ID); + setM_CostElement_ID(M_CostElement_ID); + // + m_manual = false; + } // MCost + + /** Data is entered Manually */ + private boolean m_manual = true; + + /** + * Add Cumulative Amt/Qty and Current Qty + * @param amt amt + * @param qty qty + */ + public void add (BigDecimal amt, BigDecimal qty) + { + setCumulatedAmt(getCumulatedAmt().add(amt)); + setCumulatedQty(getCumulatedQty().add(qty)); + setCurrentQty(getCurrentQty().add(qty)); + } // add + + /** + * Add Amt/Qty and calculate weighted average. + * ((OldAvg*OldQty)+(Price*Qty)) / (OldQty+Qty) + * @param amt total amt (price * qty) + * @param qty qty + */ + public void setWeightedAverage (BigDecimal amt, BigDecimal qty) + { + BigDecimal oldSum = getCurrentCostPrice().multiply(getCurrentQty()); + BigDecimal newSum = amt; // is total already + BigDecimal sumAmt = oldSum.add(newSum); + BigDecimal sumQty = getCurrentQty().add(qty); + if (sumQty.signum() != 0) + { + BigDecimal cost = sumAmt.divide(sumQty, getPrecision(), BigDecimal.ROUND_HALF_UP); + setCurrentCostPrice(cost); + } + // + setCumulatedAmt(getCumulatedAmt().add(amt)); + setCumulatedQty(getCumulatedQty().add(qty)); + setCurrentQty(getCurrentQty().add(qty)); + } // setWeightedAverage + + /** + * Get Costing Precision + * @return precision (6) + */ + private int getPrecision() + { + MAcctSchema as = MAcctSchema.get(getCtx(), getC_AcctSchema_ID()); + if (as != null) + return as.getCostingPrecision(); + return 6; + } // gerPrecision + + /** + * Set Current Cost Price + * @param currentCostPrice if null set to 0 + */ + public void setCurrentCostPrice (BigDecimal currentCostPrice) + { + if (currentCostPrice != null) + super.setCurrentCostPrice (currentCostPrice); + else + super.setCurrentCostPrice (Env.ZERO); + } // setCurrentCostPrice + + /** + * Get History Average (Amt/Qty) + * @return average if amt/aty <> 0 otherwise null + */ + public BigDecimal getHistoryAverage() + { + BigDecimal retValue = null; + if (getCumulatedQty().signum() != 0 + && getCumulatedAmt().signum() != 0) + retValue = getCumulatedAmt() + .divide(getCumulatedQty(), getPrecision(), BigDecimal.ROUND_HALF_UP); + return retValue; + } // getHistoryAverage + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MCost["); + sb.append ("AD_Client_ID=").append (getAD_Client_ID()); + if (getAD_Org_ID() != 0) + sb.append (",AD_Org_ID=").append (getAD_Org_ID()); + sb.append (",M_Product_ID=").append (getM_Product_ID()); + if (getM_AttributeSetInstance_ID() != 0) + sb.append (",AD_ASI_ID=").append (getM_AttributeSetInstance_ID()); + // sb.append (",C_AcctSchema_ID=").append (getC_AcctSchema_ID()); + // sb.append (",M_CostType_ID=").append (getM_CostType_ID()); + sb.append (",M_CostElement_ID=").append (getM_CostElement_ID()); + // + sb.append (", CurrentCost=").append (getCurrentCostPrice()) + .append (", C.Amt=").append (getCumulatedAmt()) + .append (",C.Qty=").append (getCumulatedQty()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Get Cost Element + * @return cost element + */ + public MCostElement getCostElement() + { + int M_CostElement_ID = getM_CostElement_ID(); + if (M_CostElement_ID == 0) + return null; + return MCostElement.get(getCtx(), M_CostElement_ID); + } // getCostElement + + /** + * Before Save + * @param newRecord new + * @return true if can be saved + */ + protected boolean beforeSave (boolean newRecord) + { + MCostElement ce = getCostElement(); + // Check if data entry makes sense + if (m_manual) + { + MAcctSchema as = new MAcctSchema (getCtx(), getC_AcctSchema_ID(), null); + String CostingLevel = as.getCostingLevel(); + MProduct product = MProduct.get(getCtx(), getM_Product_ID()); + MProductCategoryAcct pca = MProductCategoryAcct.get (getCtx(), + product.getM_Product_Category_ID(), as.getC_AcctSchema_ID(), null); + if (pca.getCostingLevel() != null) + CostingLevel = pca.getCostingLevel(); + if (MAcctSchema.COSTINGLEVEL_Client.equals(CostingLevel)) + { + if (getAD_Org_ID() != 0 || getM_AttributeSetInstance_ID() != 0) + { + log.saveError("CostingLevelClient", ""); + return false; + } + } + else if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(CostingLevel)) + { + if (getM_AttributeSetInstance_ID() == 0 + && ce.isCostingMethod()) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "M_AttributeSetInstance_ID")); + return false; + } + if (getAD_Org_ID() != 0) + setAD_Org_ID(0); + } + } + + // Cannot enter calculated + if (m_manual && ce != null && ce.isCalculated()) + { + log.saveError("Error", Msg.getElement(getCtx(), "IsCalculated")); + return false; + } + // Percentage + if (ce != null) + { + if (ce.isCalculated() + || MCostElement.COSTELEMENTTYPE_Material.equals(ce.getCostElementType()) + && getPercent() != 0) + setPercent(0); + } + if (getPercent() != 0) + { + if (getCurrentCostPrice().signum() != 0) + setCurrentCostPrice(Env.ZERO); + if (getFutureCostPrice().signum() != 0) + setFutureCostPrice(Env.ZERO); + if (getCumulatedAmt().signum() != 0) + setCumulatedAmt(Env.ZERO); + if (getCumulatedQty().signum() != 0) + setCumulatedQty(Env.ZERO); + } + return true; + } // beforeSave + + + /** + * Before Delete + * @return true + */ + protected boolean beforeDelete () + { + return true; + } // beforeDelete + + /** + * Test + * @param args ignored + */ + public static void main (String[] args) + { + /** + DELETE M_Cost c + WHERE EXISTS (SELECT * FROM M_CostElement ce + WHERE c.M_CostElement_ID=ce.M_CostElement_ID AND ce.IsCalculated='Y') + / + UPDATE M_Cost + SET CumulatedAmt=0, CumulatedQty=0 + / + UPDATE M_CostDetail + SET Processed='N' + WHERE Processed='Y' + / + COMMIT + / + **/ + + Adempiere.startup(true); + MClient client = MClient.get(Env.getCtx(), 11); // GardenWorld + create(client); + + } // main + + +} // MCost diff --git a/base/src/org/compiere/model/MCostDetail.java b/base/src/org/compiere/model/MCostDetail.java new file mode 100644 index 0000000000..14991934ca --- /dev/null +++ b/base/src/org/compiere/model/MCostDetail.java @@ -0,0 +1,989 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Cost Detail Model + * + * @author Jorg Janke + * @version $Id: MCostDetail.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MCostDetail extends X_M_CostDetail +{ + /** + * Create New Order Cost Detail for Purchase Orders. + * Called from Doc_MatchPO + * @param as accounting schema + * @param AD_Org_ID org + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID asi + * @param C_OrderLine_ID order + * @param M_CostElement_ID optional cost element for Freight + * @param Amt amt total amount + * @param Qty qty + * @param Description optional description + * @param trxName transaction + * @return true if created + */ + public static boolean createOrder (MAcctSchema as, int AD_Org_ID, + int M_Product_ID, int M_AttributeSetInstance_ID, + int C_OrderLine_ID, int M_CostElement_ID, + BigDecimal Amt, BigDecimal Qty, + String Description, String trxName) + { + // Delete Unprocessed zero Differences + String sql = "DELETE M_CostDetail " + + "WHERE Processed='N' AND COALESCE(DeltaAmt,0)=0 AND COALESCE(DeltaQty,0)=0" + + " AND C_OrderLine_ID=" + C_OrderLine_ID + + " AND M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID; + int no = DB.executeUpdate(sql, trxName); + if (no != 0) + s_log.config("Deleted #" + no); + MCostDetail cd = get (as.getCtx(), "C_OrderLine_ID=? AND M_AttributeSetInstance_ID=?", + C_OrderLine_ID, M_AttributeSetInstance_ID, trxName); + // + if (cd == null) // createNew + { + cd = new MCostDetail (as, AD_Org_ID, + M_Product_ID, M_AttributeSetInstance_ID, + M_CostElement_ID, + Amt, Qty, Description, trxName); + cd.setC_OrderLine_ID (C_OrderLine_ID); + } + else + { + cd.setDeltaAmt(cd.getAmt().subtract(Amt)); + cd.setDeltaQty(cd.getQty().subtract(Qty)); + if (cd.isDelta()) + cd.setProcessed(false); + else + return true; // nothing to do + } + boolean ok = cd.save(); + if (ok && !cd.isProcessed()) + { + MClient client = MClient.get(as.getCtx(), as.getAD_Client_ID()); + if (client.isCostImmediate()) + cd.process(); + } + s_log.config("(" + ok + ") " + cd); + return ok; + } // createOrder + + /** + * Create New Invoice Cost Detail for AP Invoices. + * Called from Doc_Invoice - for Invoice Adjustments + * @param as accounting schema + * @param AD_Org_ID org + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID asi + * @param C_InvoiceLine_ID invoice + * @param M_CostElement_ID optional cost element for Freight + * @param Amt amt + * @param Qty qty + * @param Description optional description + * @param trxName transaction + * @return true if created + */ + public static boolean createInvoice (MAcctSchema as, int AD_Org_ID, + int M_Product_ID, int M_AttributeSetInstance_ID, + int C_InvoiceLine_ID, int M_CostElement_ID, + BigDecimal Amt, BigDecimal Qty, + String Description, String trxName) + { + // Delete Unprocessed zero Differences + String sql = "DELETE M_CostDetail " + + "WHERE Processed='N' AND COALESCE(DeltaAmt,0)=0 AND COALESCE(DeltaQty,0)=0" + + " AND C_InvoiceLine_ID=" + C_InvoiceLine_ID + + " AND M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID; + int no = DB.executeUpdate(sql, trxName); + if (no != 0) + s_log.config("Deleted #" + no); + MCostDetail cd = get (as.getCtx(), "C_InvoiceLine_ID=? AND M_AttributeSetInstance_ID=?", + C_InvoiceLine_ID, M_AttributeSetInstance_ID, trxName); + // + if (cd == null) // createNew + { + cd = new MCostDetail (as, AD_Org_ID, + M_Product_ID, M_AttributeSetInstance_ID, + M_CostElement_ID, + Amt, Qty, Description, trxName); + cd.setC_InvoiceLine_ID (C_InvoiceLine_ID); + } + else + { + cd.setDeltaAmt(cd.getAmt().subtract(Amt)); + cd.setDeltaQty(cd.getQty().subtract(Qty)); + if (cd.isDelta()) + cd.setProcessed(false); + else + return true; // nothing to do + } + boolean ok = cd.save(); + if (ok && !cd.isProcessed()) + { + MClient client = MClient.get(as.getCtx(), as.getAD_Client_ID()); + if (client.isCostImmediate()) + cd.process(); + } + s_log.config("(" + ok + ") " + cd); + return ok; + } // createInvoice + + /** + * Create New Shipment Cost Detail for SO Shipments. + * Called from Doc_MInOut - for SO Shipments + * @param as accounting schema + * @param AD_Org_ID org + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID asi + * @param M_InOutLine_ID shipment + * @param M_CostElement_ID optional cost element for Freight + * @param Amt amt + * @param Qty qty + * @param Description optional description + * @param IsSOTrx sales order + * @param trxName transaction + * @return true if no error + */ + public static boolean createShipment (MAcctSchema as, int AD_Org_ID, + int M_Product_ID, int M_AttributeSetInstance_ID, + int M_InOutLine_ID, int M_CostElement_ID, + BigDecimal Amt, BigDecimal Qty, + String Description, boolean IsSOTrx, String trxName) + { + // Delete Unprocessed zero Differences + String sql = "DELETE M_CostDetail " + + "WHERE Processed='N' AND COALESCE(DeltaAmt,0)=0 AND COALESCE(DeltaQty,0)=0" + + " AND M_InOutLine_ID=" + M_InOutLine_ID + + " AND M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID; + int no = DB.executeUpdate(sql, trxName); + if (no != 0) + s_log.config("Deleted #" + no); + MCostDetail cd = get (as.getCtx(), "M_InOutLine_ID=? AND M_AttributeSetInstance_ID=?", + M_InOutLine_ID, M_AttributeSetInstance_ID, trxName); + // + if (cd == null) // createNew + { + cd = new MCostDetail (as, AD_Org_ID, + M_Product_ID, M_AttributeSetInstance_ID, + M_CostElement_ID, + Amt, Qty, Description, trxName); + cd.setM_InOutLine_ID(M_InOutLine_ID); + cd.setIsSOTrx(IsSOTrx); + } + else + { + cd.setDeltaAmt(cd.getAmt().subtract(Amt)); + cd.setDeltaQty(cd.getQty().subtract(Qty)); + if (cd.isDelta()) + cd.setProcessed(false); + else + return true; // nothing to do + } + boolean ok = cd.save(); + if (ok && !cd.isProcessed()) + { + MClient client = MClient.get(as.getCtx(), as.getAD_Client_ID()); + if (client.isCostImmediate()) + cd.process(); + } + s_log.config("(" + ok + ") " + cd); + return ok; + } // createShipment + + /** + * Create New Order Cost Detail for Physical Inventory. + * Called from Doc_Inventory + * @param as accounting schema + * @param AD_Org_ID org + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID asi + * @param M_InventoryLine_ID order + * @param M_CostElement_ID optional cost element + * @param Amt amt total amount + * @param Qty qty + * @param Description optional description + * @param trxName transaction + * @return true if no error + */ + public static boolean createInventory (MAcctSchema as, int AD_Org_ID, + int M_Product_ID, int M_AttributeSetInstance_ID, + int M_InventoryLine_ID, int M_CostElement_ID, + BigDecimal Amt, BigDecimal Qty, + String Description, String trxName) + { + // Delete Unprocessed zero Differences + String sql = "DELETE M_CostDetail " + + "WHERE Processed='N' AND COALESCE(DeltaAmt,0)=0 AND COALESCE(DeltaQty,0)=0" + + " AND M_InventoryLine_ID=" + M_InventoryLine_ID + + " AND M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID; + int no = DB.executeUpdate(sql, trxName); + if (no != 0) + s_log.config("Deleted #" + no); + MCostDetail cd = get (as.getCtx(), "M_InventoryLine_ID=? AND M_AttributeSetInstance_ID=?", + M_InventoryLine_ID, M_AttributeSetInstance_ID, trxName); + // + if (cd == null) // createNew + { + cd = new MCostDetail (as, AD_Org_ID, + M_Product_ID, M_AttributeSetInstance_ID, + M_CostElement_ID, + Amt, Qty, Description, trxName); + cd.setM_InventoryLine_ID(M_InventoryLine_ID); + } + else + { + cd.setDeltaAmt(cd.getAmt().subtract(Amt)); + cd.setDeltaQty(cd.getQty().subtract(Qty)); + if (cd.isDelta()) + cd.setProcessed(false); + else + return true; // nothing to do + } + boolean ok = cd.save(); + if (ok && !cd.isProcessed()) + { + MClient client = MClient.get(as.getCtx(), as.getAD_Client_ID()); + if (client.isCostImmediate()) + cd.process(); + } + s_log.config("(" + ok + ") " + cd); + return ok; + } // createInventory + + /** + * Create New Order Cost Detail for Movements. + * Called from Doc_Movement + * @param as accounting schema + * @param AD_Org_ID org + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID asi + * @param M_MovementLine_ID movement + * @param M_CostElement_ID optional cost element for Freight + * @param Amt amt total amount + * @param Qty qty + * @param from if true the from (reduction) + * @param Description optional description + * @param trxName transaction + * @return true if no error + */ + public static boolean createMovement (MAcctSchema as, int AD_Org_ID, + int M_Product_ID, int M_AttributeSetInstance_ID, + int M_MovementLine_ID, int M_CostElement_ID, + BigDecimal Amt, BigDecimal Qty, boolean from, + String Description, String trxName) + { + // Delete Unprocessed zero Differences + String sql = "DELETE M_CostDetail " + + "WHERE Processed='N' AND COALESCE(DeltaAmt,0)=0 AND COALESCE(DeltaQty,0)=0" + + " AND M_MovementLine_ID=" + M_MovementLine_ID + + " AND IsSOTrx=" + (from ? "'Y'" : "'N'") + + " AND M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID; + int no = DB.executeUpdate(sql, trxName); + if (no != 0) + s_log.config("Deleted #" + no); + MCostDetail cd = get (as.getCtx(), "M_MovementLine_ID=? AND M_AttributeSetInstance_ID=? AND IsSOTrx=" + + (from ? "'Y'" : "'N'"), + M_MovementLine_ID, M_AttributeSetInstance_ID, trxName); + // + if (cd == null) // createNew + { + cd = new MCostDetail (as, AD_Org_ID, + M_Product_ID, M_AttributeSetInstance_ID, + M_CostElement_ID, + Amt, Qty, Description, trxName); + cd.setM_MovementLine_ID (M_MovementLine_ID); + cd.setIsSOTrx(from); + } + else + { + cd.setDeltaAmt(cd.getAmt().subtract(Amt)); + cd.setDeltaQty(cd.getQty().subtract(Qty)); + if (cd.isDelta()) + cd.setProcessed(false); + else + return true; // nothing to do + } + boolean ok = cd.save(); + if (ok && !cd.isProcessed()) + { + MClient client = MClient.get(as.getCtx(), as.getAD_Client_ID()); + if (client.isCostImmediate()) + cd.process(); + } + s_log.config("(" + ok + ") " + cd); + return ok; + } // createMovement + + /** + * Create New Order Cost Detail for Production. + * Called from Doc_Production + * @param as accounting schema + * @param AD_Org_ID org + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID asi + * @param M_ProductionLine_ID production line + * @param M_CostElement_ID optional cost element + * @param Amt amt total amount + * @param Qty qty + * @param Description optional description + * @param trxName transaction + * @return true if no error + */ + public static boolean createProduction (MAcctSchema as, int AD_Org_ID, + int M_Product_ID, int M_AttributeSetInstance_ID, + int M_ProductionLine_ID, int M_CostElement_ID, + BigDecimal Amt, BigDecimal Qty, + String Description, String trxName) + { + // Delete Unprocessed zero Differences + String sql = "DELETE M_CostDetail " + + "WHERE Processed='N' AND COALESCE(DeltaAmt,0)=0 AND COALESCE(DeltaQty,0)=0" + + " AND M_ProductionLine_ID=" + M_ProductionLine_ID + + " AND M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID; + int no = DB.executeUpdate(sql, trxName); + if (no != 0) + s_log.config("Deleted #" + no); + MCostDetail cd = get (as.getCtx(), "M_ProductionLine_ID=? AND M_AttributeSetInstance_ID=?", + M_ProductionLine_ID, M_AttributeSetInstance_ID, trxName); + // + if (cd == null) // createNew + { + cd = new MCostDetail (as, AD_Org_ID, + M_Product_ID, M_AttributeSetInstance_ID, + M_CostElement_ID, + Amt, Qty, Description, trxName); + cd.setM_ProductionLine_ID(M_ProductionLine_ID); + } + else + { + cd.setDeltaAmt(cd.getAmt().subtract(Amt)); + cd.setDeltaQty(cd.getQty().subtract(Qty)); + if (cd.isDelta()) + cd.setProcessed(false); + else + return true; // nothing to do + } + boolean ok = cd.save(); + if (ok && !cd.isProcessed()) + { + MClient client = MClient.get(as.getCtx(), as.getAD_Client_ID()); + if (client.isCostImmediate()) + cd.process(); + } + s_log.config("(" + ok + ") " + cd); + return ok; + } // createProduction + + + /************************************************************************** + * Get Cost Detail + * @param ctx context + * @param whereClause where clause + * @param ID 1st parameter + * @param ID2 2nd parameter + * @param trxName trx + * @return cost detail + */ + private static MCostDetail get (Properties ctx, String whereClause, + int ID, int ID2, String trxName) + { + String sql = "SELECT * FROM M_CostDetail WHERE " + whereClause; + MCostDetail retValue = null; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, ID); + pstmt.setInt (2, ID2); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = new MCostDetail (ctx, rs, trxName); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql + " - " + ID, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return retValue; + } // get + + /** + * Process Cost Details for product + * @param product product + * @param trxName transaction + * @return true if no error + */ + public static boolean processProduct (MProduct product, String trxName) + { + String sql = "SELECT * FROM M_CostDetail " + + "WHERE M_Product_ID=?" + + " AND Processed='N' " + + "ORDER BY C_AcctSchema_ID, M_CostElement_ID, AD_Org_ID, M_AttributeSetInstance_ID, Created"; + int counterOK = 0; + int counterError = 0; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, product.getM_Product_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MCostDetail cd = new MCostDetail(product.getCtx(), rs, trxName); + if (cd.process()) // saves + counterOK++; + else + counterError++; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + counterError++; + } + + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + s_log.config("OK=" + counterOK + ", Errors=" + counterError); + return counterError == 0; + } // processProduct + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MCostDetail.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_CostDetail_ID id + * @param trxName trx + */ + public MCostDetail (Properties ctx, int M_CostDetail_ID, String trxName) + { + super (ctx, M_CostDetail_ID, trxName); + if (M_CostDetail_ID == 0) + { + // setC_AcctSchema_ID (0); + // setM_Product_ID (0); + setM_AttributeSetInstance_ID (0); + // setC_OrderLine_ID (0); + // setM_InOutLine_ID(0); + // setC_InvoiceLine_ID (0); + setProcessed (false); + setAmt (Env.ZERO); + setQty (Env.ZERO); + setIsSOTrx (false); + setDeltaAmt (Env.ZERO); + setDeltaQty (Env.ZERO); + } + } // MCostDetail + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MCostDetail (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MCostDetail + + /** + * New Constructor + * @param as accounting schema + * @param AD_Org_ID org + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID asi + * @param M_CostElement_ID optional cost element for Freight + * @param Amt amt + * @param Qty qty + * @param Description optional description + * @param trxName transaction + */ + public MCostDetail (MAcctSchema as, int AD_Org_ID, + int M_Product_ID, int M_AttributeSetInstance_ID, + int M_CostElement_ID, BigDecimal Amt, BigDecimal Qty, + String Description, String trxName) + { + this (as.getCtx(), 0, trxName); + setClientOrg(as.getAD_Client_ID(), AD_Org_ID); + setC_AcctSchema_ID (as.getC_AcctSchema_ID()); + setM_Product_ID (M_Product_ID); + setM_AttributeSetInstance_ID (M_AttributeSetInstance_ID); + // + setM_CostElement_ID(M_CostElement_ID); + // + setAmt (Amt); + setQty (Qty); + setDescription(Description); + } // MCostDetail + + /** + * Set Amt + * @param Amt amt + */ + public void setAmt (BigDecimal Amt) + { + if (isProcessed()) + throw new IllegalStateException("Cannot change Amt - processed"); + if (Amt == null) + super.setAmt (Env.ZERO); + else + super.setAmt (Amt); + } // setAmt + + /** + * Set Qty + * @param Qty qty + */ + public void setQty (BigDecimal Qty) + { + if (isProcessed()) + throw new IllegalStateException("Cannot change Qty - processed"); + if (Qty == null) + super.setQty (Env.ZERO); + else + super.setQty (Qty); + } // setQty + + /** + * Is Order + * @return true if order line + */ + public boolean isOrder() + { + return getC_OrderLine_ID() != 0; + } // isOrder + + /** + * Is Invoice + * @return true if invoice line + */ + public boolean isInvoice() + { + return getC_InvoiceLine_ID() != 0; + } // isInvoice + + /** + * Is Shipment + * @return true if sales order shipment + */ + public boolean isShipment() + { + return isSOTrx() && getM_InOutLine_ID() != 0; + } // isShipment + + /** + * Is this a Delta Record (previously processed)? + * @return true if delta is not null + */ + public boolean isDelta() + { + return !(getDeltaAmt().signum() == 0 + && getDeltaQty().signum() == 0); + } // isDelta + + + /** + * After Save + * @param newRecord new + * @param success success + * @return true + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + return true; + } // afterSave + + /** + * Before Delete + * @return false if processed + */ + protected boolean beforeDelete () + { + return !isProcessed(); + } // beforeDelete + + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MCostDetail["); + sb.append (get_ID()); + if (getC_OrderLine_ID() != 0) + sb.append (",C_OrderLine_ID=").append (getC_OrderLine_ID()); + if (getM_InOutLine_ID() != 0) + sb.append (",M_InOutLine_ID=").append (getM_InOutLine_ID()); + if (getC_InvoiceLine_ID() != 0) + sb.append (",C_InvoiceLine_ID=").append (getC_InvoiceLine_ID()); + if (getC_ProjectIssue_ID() != 0) + sb.append (",C_ProjectIssue_ID=").append (getC_ProjectIssue_ID()); + if (getM_MovementLine_ID() != 0) + sb.append (",M_MovementLine_ID=").append (getM_MovementLine_ID()); + if (getM_InventoryLine_ID() != 0) + sb.append (",M_InventoryLine_ID=").append (getM_InventoryLine_ID()); + if (getM_ProductionLine_ID() != 0) + sb.append (",M_ProductionLine_ID=").append (getM_ProductionLine_ID()); + sb.append(",Amt=").append(getAmt()) + .append(",Qty=").append(getQty()); + if (isDelta()) + sb.append(",DeltaAmt=").append(getDeltaAmt()) + .append(",DeltaQty=").append(getDeltaQty()); + sb.append ("]"); + return sb.toString (); + } // toString + + + /************************************************************************** + * Process Cost Detail Record. + * The record is saved if processed. + * @return true if processed + */ + public synchronized boolean process() + { + if (isProcessed()) + { + log.info("already processed"); + return true; + } + boolean ok = false; + + // get costing level for product + MAcctSchema as = new MAcctSchema (getCtx(), getC_AcctSchema_ID(), null); + String CostingLevel = as.getCostingLevel(); + MProduct product = MProduct.get(getCtx(), getM_Product_ID()); + MProductCategoryAcct pca = MProductCategoryAcct.get (getCtx(), + product.getM_Product_Category_ID(), getC_AcctSchema_ID(), null); + if (pca.getCostingLevel() != null) + CostingLevel = pca.getCostingLevel(); + // Org Element + int Org_ID = getAD_Org_ID(); + int M_ASI_ID = getM_AttributeSetInstance_ID(); + if (MAcctSchema.COSTINGLEVEL_Client.equals(CostingLevel)) + { + Org_ID = 0; + M_ASI_ID = 0; + } + else if (MAcctSchema.COSTINGLEVEL_Organization.equals(CostingLevel)) + M_ASI_ID = 0; + else if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(CostingLevel)) + Org_ID = 0; + + // Create Material Cost elements + if (getM_CostElement_ID() == 0) + { + MCostElement[] ces = MCostElement.getCostingMethods(this); + for (int i = 0; i < ces.length; i++) + { + MCostElement ce = ces[i]; + ok = process (as, product, ce, Org_ID, M_ASI_ID); + if (!ok) + break; + } + } // Material Cost elements + else + { + MCostElement ce = MCostElement.get(getCtx(), getM_CostElement_ID()); + ok = process (as, product, ce, Org_ID, M_ASI_ID); + } + + // Save it + if (ok) + { + setDeltaAmt(null); + setDeltaQty(null); + setProcessed(true); + ok = save(); + } + log.info(ok + " - " + toString()); + return ok; + } // process + + /** + * Process cost detail for cost record + * @param as accounting schema + * @param product product + * @param ce cost element + * @param Org_ID org - corrected for costing level + * @param M_ASI_ID - asi corrected for costing level + * @return true if cost ok + */ + private boolean process (MAcctSchema as, MProduct product, MCostElement ce, + int Org_ID, int M_ASI_ID) + { + MCost cost = MCost.get(product, M_ASI_ID, as, + Org_ID, ce.getM_CostElement_ID()); + // if (cost == null) + // cost = new MCost(product, M_ASI_ID, + // as, Org_ID, ce.getM_CostElement_ID()); + + BigDecimal qty = getQty(); + BigDecimal amt = getAmt(); + int precision = as.getCostingPrecision(); + BigDecimal price = amt; + if (qty.signum() != 0) + price = amt.divide(qty, precision, BigDecimal.ROUND_HALF_UP); + + /** All Costing Methods + if (ce.isAverageInvoice()) + else if (ce.isAveragePO()) + else if (ce.isFifo()) + else if (ce.isLifo()) + else if (ce.isLastInvoice()) + else if (ce.isLastPOPrice()) + else if (ce.isStandardCosting()) + else if (ce.isUserDefined()) + else if (!ce.isCostingMethod()) + **/ + + // *** Purchase Order Detail Record *** + if (getC_OrderLine_ID() != 0) + { + if (ce.isAveragePO()) + { + cost.setWeightedAverage(amt, qty); + log.finer("PO - AveragePO - " + cost); + } + else if (ce.isLastPOPrice()) + { + if (qty.signum() != 0) + cost.setCurrentCostPrice(price); + else + { + BigDecimal cCosts = cost.getCurrentCostPrice().add(amt); + cost.setCurrentCostPrice(cCosts); + } + cost.add(amt, qty); + log.finer("PO - LastPO - " + cost); + } + else if (ce.isUserDefined()) + { + // Interface + log.finer("PO - UserDef - " + cost); + } + else if (!ce.isCostingMethod()) + { + log.finer("PO - " + ce + " - " + cost); + } + // else + // log.warning("PO - " + ce + " - " + cost); + } + + // *** AP Invoice Detail Record *** + else if (getC_InvoiceLine_ID() != 0) + { + if (ce.isAverageInvoice()) + { + cost.setWeightedAverage(amt, qty); + log.finer("Inv - AverageInv - " + cost); + } + else if (ce.isFifo() + || ce.isLifo()) + { + // Real ASI - costing level Org + MCostQueue cq = MCostQueue.get(product, getM_AttributeSetInstance_ID(), + as, Org_ID, ce.getM_CostElement_ID(), get_TrxName()); + cq.setCosts(amt, qty, precision); + cq.save(); + // Get Costs - costing level Org/ASI + MCostQueue[] cQueue = MCostQueue.getQueue(product, M_ASI_ID, + as, Org_ID, ce, get_TrxName()); + if (cQueue != null && cQueue.length > 0) + cost.setCurrentCostPrice(cQueue[0].getCurrentCostPrice()); + cost.add(amt, qty); + log.finer("Inv - FiFo/LiFo - " + cost); + } + else if (ce.isLastInvoice()) + { + if (qty.signum() != 0) + cost.setCurrentCostPrice(price); + else + { + BigDecimal cCosts = cost.getCurrentCostPrice().add(amt); + cost.setCurrentCostPrice(cCosts); + } + cost.add(amt, qty); + log.finer("Inv - LastInv - " + cost); + } + else if (ce.isStandardCosting()) + { + if (cost.getCurrentCostPrice().signum() == 0) + { + cost.setCurrentCostPrice(price); + // seed initial price + if (cost.getCurrentCostPrice().signum() == 0 + && cost.get_ID() == 0) + cost.setCurrentCostPrice( + MCost.getSeedCosts(product, M_ASI_ID, + as, Org_ID, ce.getCostingMethod(), getC_OrderLine_ID())); + } + cost.add(amt, qty); + log.finer("Inv - Standard - " + cost); + } + else if (ce.isUserDefined()) + { + // Interface + cost.add(amt, qty); + log.finer("Inv - UserDef - " + cost); + } + else if (!ce.isCostingMethod()) // Cost Adjustments + { + BigDecimal cCosts = cost.getCurrentCostPrice().add(amt); + cost.setCurrentCostPrice(cCosts); + cost.add(amt, qty); + log.finer("Inv - none - " + cost); + } + // else + // log.warning("Inv - " + ce + " - " + cost); + } + + // *** Qty Adjustment Detail Record *** + else if (getM_InOutLine_ID() != 0 // AR Shipment Detail Record + || getM_MovementLine_ID() != 0 + || getM_InventoryLine_ID() != 0 + || getM_ProductionLine_ID() != 0 + || getC_ProjectIssue_ID() != 0) + { + boolean addition = qty.signum() > 0; + // + if (ce.isAverageInvoice()) + { + if (addition) + cost.setWeightedAverage(amt, qty); + else + cost.setCurrentQty(cost.getCurrentQty().add(qty)); + log.finer("QtyAdjust - AverageInv - " + cost); + } + else if (ce.isAveragePO()) + { + if (addition) + cost.setWeightedAverage(amt, qty); + else + cost.setCurrentQty(cost.getCurrentQty().add(qty)); + log.finer("QtyAdjust - AveragePO - " + cost); + } + else if (ce.isFifo() || ce.isLifo()) + { + if (addition) + { + // Real ASI - costing level Org + MCostQueue cq = MCostQueue.get(product, getM_AttributeSetInstance_ID(), + as, Org_ID, ce.getM_CostElement_ID(), get_TrxName()); + cq.setCosts(amt, qty, precision); + cq.save(); + } + else + { + // Adjust Queue - costing level Org/ASI + MCostQueue.adjustQty(product, M_ASI_ID, + as, Org_ID, ce, qty.negate(), get_TrxName()); + } + // Get Costs - costing level Org/ASI + MCostQueue[] cQueue = MCostQueue.getQueue(product, M_ASI_ID, + as, Org_ID, ce, get_TrxName()); + if (cQueue != null && cQueue.length > 0) + cost.setCurrentCostPrice(cQueue[0].getCurrentCostPrice()); + cost.setCurrentQty(cost.getCurrentQty().add(qty)); + log.finer("QtyAdjust - FiFo/Lifo - " + cost); + } + else if (ce.isLastInvoice()) + { + cost.setCurrentQty(cost.getCurrentQty().add(qty)); + log.finer("QtyAdjust - LastInv - " + cost); + } + else if (ce.isLastPOPrice()) + { + cost.setCurrentQty(cost.getCurrentQty().add(qty)); + log.finer("QtyAdjust - LastPO - " + cost); + } + else if (ce.isStandardCosting()) + { + if (addition) + { + cost.add(amt, qty); + // Initial + if (cost.getCurrentCostPrice().signum() == 0 + && cost.get_ID() == 0) + cost.setCurrentCostPrice(price); + } + else + cost.setCurrentQty(cost.getCurrentQty().add(qty)); + log.finer("QtyAdjust - Standard - " + cost); + } + else if (ce.isUserDefined()) + { + // Interface + if (addition) + cost.add(amt, qty); + else + cost.setCurrentQty(cost.getCurrentQty().add(qty)); + log.finer("QtyAdjust - UserDef - " + cost); + } + else if (!ce.isCostingMethod()) + { + // Should not happen + log.finer("QtyAdjust - ?none? - " + cost); + } + else + log.warning("QtyAdjust - " + ce + " - " + cost); + } + else // unknown or no id + { + log.warning("Unknown Type: " + toString()); + return false; + } + + return cost.save(); + } // process + +} // MCostDetail diff --git a/base/src/org/compiere/model/MCostQueue.java b/base/src/org/compiere/model/MCostQueue.java new file mode 100644 index 0000000000..8156512ca3 --- /dev/null +++ b/base/src/org/compiere/model/MCostQueue.java @@ -0,0 +1,391 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import java.math.*; + +import org.compiere.util.*; + +/** + * Cost Queue Model + * + * @author Jorg Janke + * @version $Id: MCostQueue.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MCostQueue extends X_M_CostQueue +{ + /** + * Get/Create Cost Queue Record. + * CostingLevel is not validated + * @param product product + * @param M_AttributeSetInstance_ID real asi + * @param as accounting schema + * @param AD_Org_ID real org + * @param M_CostElement_ID element + * @param trxName transaction + * @return cost queue or null + */ + public static MCostQueue get (MProduct product, int M_AttributeSetInstance_ID, + MAcctSchema as, int AD_Org_ID, int M_CostElement_ID, String trxName) + { + MCostQueue costQ = null; + String sql = "SELECT * FROM M_CostQueue " + + "WHERE AD_Client_ID=? AND AD_Org_ID=?" + + " AND M_Product_ID=?" + + " AND M_AttributeSetInstance_ID=?" + + " AND M_CostType_ID=? AND C_AcctSchema_ID=?" + + " AND M_CostElement_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, product.getAD_Client_ID()); + pstmt.setInt (2, AD_Org_ID); + pstmt.setInt (3, product.getM_Product_ID()); + pstmt.setInt (4, M_AttributeSetInstance_ID); + pstmt.setInt (5, as.getM_CostType_ID()); + pstmt.setInt (6, as.getC_AcctSchema_ID()); + pstmt.setInt (7, M_CostElement_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + costQ = new MCostQueue (product.getCtx(), rs, trxName); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // New + if (costQ == null) + costQ = new MCostQueue (product, M_AttributeSetInstance_ID, + as, AD_Org_ID, M_CostElement_ID, trxName); + return costQ; + } // get + + /** + * Get Cost Queue Records in Lifo/Fifo order + * @param product product + * @param M_ASI_ID costing level ASI + * @param as accounting schema + * @param Org_ID costing level org + * @param ce Cost Element + * @param trxName transaction + * @return cost queue or null + */ + public static MCostQueue[] getQueue (MProduct product, int M_ASI_ID, + MAcctSchema as, int Org_ID, MCostElement ce, String trxName) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_CostQueue " + + "WHERE AD_Client_ID=? AND AD_Org_ID=?" + + " AND M_Product_ID=?" + + " AND M_CostType_ID=? AND C_AcctSchema_ID=?" + + " AND M_CostElement_ID=?"; + if (M_ASI_ID != 0) + sql += " AND M_AttributeSetInstance_ID=?"; + sql += " AND CurrentQty<>0 " + + "ORDER BY M_AttributeSetInstance_ID "; + if (!ce.isFifo()) + sql += "DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, product.getAD_Client_ID()); + pstmt.setInt (2, Org_ID); + pstmt.setInt (3, product.getM_Product_ID()); + pstmt.setInt (4, as.getM_CostType_ID()); + pstmt.setInt (5, as.getC_AcctSchema_ID()); + pstmt.setInt (6, ce.getM_CostElement_ID()); + if (M_ASI_ID != 0) + pstmt.setInt (7, M_ASI_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MCostQueue (product.getCtx(), rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MCostQueue[] costQ = new MCostQueue[list.size()]; + list.toArray(costQ); + return costQ; + } // getQueue + + + /** + * Adjust Qty based on in Lifo/Fifo order + * @param product product + * @param M_ASI_ID costing level ASI + * @param as accounting schema + * @param Org_ID costing level org + * @param ce Cost Element + * @param Qty quantity to be reduced + * @param trxName transaction + * @return cost price reduced or null of error + */ + public static BigDecimal adjustQty (MProduct product, int M_ASI_ID, + MAcctSchema as, int Org_ID, MCostElement ce, BigDecimal Qty, + String trxName) + { + if (Qty.signum() == 0) + return Env.ZERO; + MCostQueue[] costQ = getQueue(product, M_ASI_ID, + as, Org_ID, ce, trxName); + BigDecimal remainingQty = Qty; + for (int i = 0; i < costQ.length; i++) + { + MCostQueue queue = costQ[i]; + // Negative Qty i.e. add + if (remainingQty.signum() < 0) + { + BigDecimal oldQty = queue.getCurrentQty(); + BigDecimal newQty = oldQty.subtract(remainingQty); + queue.setCurrentQty(newQty); + if (queue.save()) + { + s_log.fine("Qty=" + remainingQty + + "(!), ASI=" + queue.getM_AttributeSetInstance_ID() + + " - " + oldQty + " -> " + newQty); + return queue.getCurrentCostPrice(); + } + else + return null; + } + + // Positive queue + if (queue.getCurrentQty().signum() > 0) + { + BigDecimal reduction = remainingQty; + if (reduction.compareTo(queue.getCurrentQty()) > 0) + reduction = queue.getCurrentQty(); + BigDecimal oldQty = queue.getCurrentQty(); + BigDecimal newQty = oldQty.subtract(reduction); + queue.setCurrentQty(newQty); + if (queue.save()) + { + s_log.fine("Qty=" + reduction + + ", ASI=" + queue.getM_AttributeSetInstance_ID() + + " - " + oldQty + " -> " + newQty); + remainingQty = remainingQty.subtract(reduction); + } + else + return null; + // + if (remainingQty.signum() == 0) + { + return queue.getCurrentCostPrice(); + } + } + } // for queue + + s_log.fine("RemainingQty=" + remainingQty); + return null; + } // adjustQty + + /** + * Calculate Cost based on Qty based on in Lifo/Fifo order + * @param product product + * @param M_ASI_ID costing level ASI + * @param as accounting schema + * @param Org_ID costing level org + * @param ce Cost Element + * @param Qty quantity to be reduced + * @param trxName transaction + * @return cost for qty or null of error + */ + public static BigDecimal getCosts (MProduct product, int M_ASI_ID, + MAcctSchema as, int Org_ID, MCostElement ce, BigDecimal Qty, + String trxName) + { + if (Qty.signum() == 0) + return Env.ZERO; + MCostQueue[] costQ = getQueue(product, M_ASI_ID, + as, Org_ID, ce, trxName); + // + BigDecimal cost = Env.ZERO; + BigDecimal remainingQty = Qty; + BigDecimal firstPrice = null; + BigDecimal lastPrice = null; + // + for (int i = 0; i < costQ.length; i++) + { + MCostQueue queue = costQ[i]; + // Negative Qty i.e. add + if (remainingQty.signum() <= 0) + { + BigDecimal oldQty = queue.getCurrentQty(); + lastPrice = queue.getCurrentCostPrice(); + BigDecimal costBatch = lastPrice.multiply(remainingQty); + cost = cost.add(costBatch); + s_log.config("ASI=" + queue.getM_AttributeSetInstance_ID() + + " - Cost=" + lastPrice + " * Qty=" + remainingQty + "(!) = " + costBatch); + return cost; + } + + // Positive queue + if (queue.getCurrentQty().signum() > 0) + { + BigDecimal reduction = remainingQty; + if (reduction.compareTo(queue.getCurrentQty()) > 0) + reduction = queue.getCurrentQty(); + BigDecimal oldQty = queue.getCurrentQty(); + lastPrice = queue.getCurrentCostPrice(); + BigDecimal costBatch = lastPrice.multiply(reduction); + cost = cost.add(costBatch); + s_log.fine("ASI=" + queue.getM_AttributeSetInstance_ID() + + " - Cost=" + lastPrice + " * Qty=" + reduction + " = " + costBatch); + remainingQty = remainingQty.subtract(reduction); + // Done + if (remainingQty.signum() == 0) + { + s_log.config("Cost=" + cost); + return cost; + } + if (firstPrice == null) + firstPrice = lastPrice; + } + } // for queue + + if (lastPrice == null) + { + lastPrice = MCost.getSeedCosts(product, M_ASI_ID, as, Org_ID, + ce.getCostingMethod(), 0); + if (lastPrice == null) + { + s_log.info("No Price found"); + return null; + } + s_log.info("No Cost Queue"); + } + BigDecimal costBatch = lastPrice.multiply(remainingQty); + s_log.fine("RemainingQty=" + remainingQty + " * LastPrice=" + lastPrice + " = " + costBatch); + cost = cost.add(costBatch); + s_log.config("Cost=" + cost); + return cost; + } // getCosts + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MCostQueue.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param ignored multi-key + * @param trxName trx + */ + public MCostQueue (Properties ctx, int ignored, String trxName) + { + super (ctx, ignored, trxName); + if (ignored == 0) + { + // setC_AcctSchema_ID (0); + // setM_AttributeSetInstance_ID (0); + // setM_CostElement_ID (0); + // setM_CostType_ID (0); + // setM_Product_ID (0); + setCurrentCostPrice (Env.ZERO); + setCurrentQty (Env.ZERO); + } + else + throw new IllegalArgumentException("Multi-Key"); + } // MCostQueue + + /** + * Load Cosntructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MCostQueue (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MCostQueue + + /** + * Parent Constructor + * @param product Product + * @param M_AttributeSetInstance_ID asi + * @param as Acct Schema + * @param AD_Org_ID org + * @param M_CostElement_ID cost element + * @param trxName transaction + */ + public MCostQueue (MProduct product, int M_AttributeSetInstance_ID, + MAcctSchema as, int AD_Org_ID, int M_CostElement_ID, String trxName) + { + this (product.getCtx(), 0, trxName); + setClientOrg(product.getAD_Client_ID(), AD_Org_ID); + setC_AcctSchema_ID(as.getC_AcctSchema_ID()); + setM_CostType_ID(as.getM_CostType_ID()); + setM_Product_ID(product.getM_Product_ID()); + setM_AttributeSetInstance_ID(M_AttributeSetInstance_ID); + setM_CostElement_ID(M_CostElement_ID); + } // MCostQueue + + /** + * Update Record. + * ((OldAvg*OldQty)+(Price*Qty)) / (OldQty+Qty) + * @param amt total Amount + * @param qty quantity + * @param precision costing precision + */ + public void setCosts (BigDecimal amt, BigDecimal qty, int precision) + { + BigDecimal oldSum = getCurrentCostPrice().multiply(getCurrentQty()); + BigDecimal newSum = amt; // is total already + BigDecimal sumAmt = oldSum.add(newSum); + BigDecimal sumQty = getCurrentQty().add(qty); + if (sumQty.signum() != 0) + { + BigDecimal cost = sumAmt.divide(sumQty, precision, BigDecimal.ROUND_HALF_UP); + setCurrentCostPrice(cost); + } + // + setCurrentQty(getCurrentQty().add(qty)); + } // update + +} // MCostQueue diff --git a/base/src/org/compiere/model/MCounterCount.java b/base/src/org/compiere/model/MCounterCount.java new file mode 100644 index 0000000000..f4ed83a276 --- /dev/null +++ b/base/src/org/compiere/model/MCounterCount.java @@ -0,0 +1,58 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.util.*; +import java.sql.*; + +/** + * Web Counter (header) + * + * @author Jorg Janke + * @version $Id: MCounterCount.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MCounterCount extends X_W_CounterCount +{ + /** + * Standard Constructor + * @param ctx context + * @param W_CounterCount_ID id + * @param trxName transaction + */ + public MCounterCount (Properties ctx, int W_CounterCount_ID, String trxName) + { + super (ctx, W_CounterCount_ID, trxName); + if (W_CounterCount_ID == 0) + { + setCounter (0); + // setName (null); + // setPageURL (null); + } + } // MCounterCount + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MCounterCount (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MCounterCount + +} // MCounterCount diff --git a/base/src/org/compiere/model/MDesktop.java b/base/src/org/compiere/model/MDesktop.java new file mode 100644 index 0000000000..8a899eb38e --- /dev/null +++ b/base/src/org/compiere/model/MDesktop.java @@ -0,0 +1,246 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Desktop Model + * + * @author Jorg Janke + * @version $Id: MDesktop.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MDesktop +{ + /** + * Desktop Model + * @param ctx context + */ + public MDesktop(Properties ctx) + { + m_ctx = ctx; + } // MDesktop + + /** Properties */ + private Properties m_ctx; + + /** List of workbenches */ + private ArrayList m_workbenches = new ArrayList(); + + private int AD_Desktop_ID; + private String Name; + private String Description; + private String Help; + private int AD_Column_ID; + private int AD_Image_ID; + private int AD_Color_ID; + private int PA_Goal_ID; + + /** Logger */ + private CLogger log = CLogger.getCLogger(getClass()); + + /** + * Init Desktop + * @param ad_Desktop_ID desktop + * @return true if initialized + */ + public boolean initDesktop (int ad_Desktop_ID) + { + AD_Desktop_ID = ad_Desktop_ID; + // Get WB info + String sql = null; + if (Env.isBaseLanguage(m_ctx, "AD_Desktop")) + sql = "SELECT Name,Description,Help," // 1..3 + + " AD_Column_ID,AD_Image_ID,AD_Color_ID,PA_Goal_ID " // 4..7 + + "FROM AD_Desktop " + + "WHERE AD_Desktop_ID=? AND IsActive='Y'"; + else + sql = "SELECT t.Name,t.Description,t.Help," + + " w.AD_Column_ID,w.AD_Image_ID,w.AD_Color_ID,w.PA_Goal_ID " + + "FROM AD_Desktop w, AD_Desktop_Trl t " + + "WHERE w.AD_Desktop_ID=? AND w.IsActive='Y'" + + " AND w.AD_Desktop_ID=t.AD_Desktop_ID" + + " AND t.AD_Language='" + Env.getAD_Language(m_ctx) + "'"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Desktop_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + Name = rs.getString(1); + Description = rs.getString(2); + if (Description == null) + Description = ""; + Help = rs.getString(3); + if (Help == null) + Help = ""; + // + AD_Column_ID = rs.getInt(4); + AD_Image_ID = rs.getInt(5); + AD_Color_ID = rs.getInt(6); + PA_Goal_ID = rs.getInt(7); + } + else + AD_Desktop_ID = 0; + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + + if (AD_Desktop_ID == 0) + return false; + return initDesktopWorkbenches(); + } // initDesktop + + /** + * String Representation + * @return info + */ + public String toString() + { + return "MDesktop ID=" + AD_Desktop_ID + " " + Name; + } + + /************************************************************************** + * Get AD_Desktop_ID + * @return desktop + */ + public int getAD_Desktop_ID() + { + return AD_Desktop_ID; + } + /** + * Get Name + * @return name + */ + public String getName() + { + return Name; + } + /** + * Get Description + * @return description + */ + public String getDescription() + { + return Description; + } + /** + * Get Help + * @return help + */ + public String getHelp() + { + return Help; + } + /** + * Get AD_Column_ID + * @return column + */ + public int getAD_Column_ID() + { + return AD_Column_ID; + } + /** + * Get AD_Image_ID + * @return image + */ + public int getAD_Image_ID() + { + return AD_Image_ID; + } + /** + * Get AD_Color_ID + * @return color + */ + public int getAD_Color_ID() + { + return AD_Color_ID; + } + /** + * Get PA_Goal_ID + * @return goal + */ + public int getPA_Goal_ID() + { + return PA_Goal_ID; + } + + /*************************************************************************/ + + /** + * Init Workbench Windows + * @return true if initilized + */ + private boolean initDesktopWorkbenches() + { + String sql = "SELECT AD_Workbench_ID " + + "FROM AD_DesktopWorkbench " + + "WHERE AD_Desktop_ID=? AND IsActive='Y' " + + "ORDER BY SeqNo"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Desktop_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + int AD_Workbench_ID = rs.getInt(1); + m_workbenches.add (new Integer(AD_Workbench_ID)); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "MWorkbench.initDesktopWorkbenches", e); + return false; + } + return true; + } // initDesktopWorkbenches + + /** + * Get Window Count + * @return no of windows + */ + public int getWindowCount() + { + return m_workbenches.size(); + } // getWindowCount + + /** + * Get AD_Workbench_ID of index + * @param index index + * @return -1 if not valid + */ + public int getAD_Workbench_ID (int index) + { + if (index < 0 || index > m_workbenches.size()) + return -1; + Integer id = (Integer)m_workbenches.get(index); + return id.intValue(); + } // getAD_Workbench_ID + +} // MDesktop diff --git a/base/src/org/compiere/model/MDiscountSchema.java b/base/src/org/compiere/model/MDiscountSchema.java new file mode 100644 index 0000000000..8ccb7e3f25 --- /dev/null +++ b/base/src/org/compiere/model/MDiscountSchema.java @@ -0,0 +1,338 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Discount Schema Model + * + * @author Jorg Janke + * @version $Id: MDiscountSchema.java,v 1.3 2006/07/30 00:51:04 jjanke Exp $ + */ +public class MDiscountSchema extends X_M_DiscountSchema +{ + /** + * Get Discount Schema from Cache + * @param ctx context + * @param M_DiscountSchema_ID id + * @return MDiscountSchema + */ + public static MDiscountSchema get (Properties ctx, int M_DiscountSchema_ID) + { + Integer key = new Integer (M_DiscountSchema_ID); + MDiscountSchema retValue = (MDiscountSchema) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MDiscountSchema (ctx, M_DiscountSchema_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache + = new CCache("M_DiscountSchema", 20); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_DiscountSchema_ID id + * @param trxName transaction + */ + public MDiscountSchema (Properties ctx, int M_DiscountSchema_ID, String trxName) + { + super (ctx, M_DiscountSchema_ID, trxName); + if (M_DiscountSchema_ID == 0) + { + // setName(); + setDiscountType (DISCOUNTTYPE_FlatPercent); + setFlatDiscount(Env.ZERO); + setIsBPartnerFlatDiscount (false); + setIsQuantityBased (true); // Y + setCumulativeLevel(CUMULATIVELEVEL_Line); + // setValidFrom (new Timestamp(System.currentTimeMillis())); + } + } // MDiscountSchema + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MDiscountSchema (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MDiscountSchema + + /** Breaks */ + private MDiscountSchemaBreak[] m_breaks = null; + /** Lines */ + private MDiscountSchemaLine[] m_lines = null; + + /** + * Get Breaks + * @param reload reload + * @return breaks + */ + public MDiscountSchemaBreak[] getBreaks(boolean reload) + { + if (m_breaks != null && !reload) + return m_breaks; + + String sql = "SELECT * FROM M_DiscountSchemaBreak WHERE M_DiscountSchema_ID=? ORDER BY SeqNo"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getM_DiscountSchema_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MDiscountSchemaBreak(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_breaks = new MDiscountSchemaBreak[list.size ()]; + list.toArray (m_breaks); + return m_breaks; + } // getBreaks + + /** + * Get Lines + * @param reload reload + * @return lines + */ + public MDiscountSchemaLine[] getLines(boolean reload) + { + if (m_lines != null && !reload) + return m_lines; + + String sql = "SELECT * FROM M_DiscountSchemaLine WHERE M_DiscountSchema_ID=? ORDER BY SeqNo"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getM_DiscountSchema_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MDiscountSchemaLine(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_lines = new MDiscountSchemaLine[list.size ()]; + list.toArray (m_lines); + return m_lines; + } // getBreaks + + /** + * Calculate Discounted Price + * @param Qty quantity + * @param Price price + * @param M_Product_ID product + * @param M_Product_Category_ID category + * @param BPartnerFlatDiscount flat discount + * @return discount or zero + */ + public BigDecimal calculatePrice (BigDecimal Qty, BigDecimal Price, + int M_Product_ID, int M_Product_Category_ID, + BigDecimal BPartnerFlatDiscount) + { + log.fine("Price=" + Price + ",Qty=" + Qty); + if (Price == null || Env.ZERO.compareTo(Price) == 0) + return Price; + // + BigDecimal discount = calculateDiscount(Qty, Price, + M_Product_ID, M_Product_Category_ID, BPartnerFlatDiscount); + // nothing to calculate + if (discount == null || discount.signum() == 0) + return Price; + // + BigDecimal onehundred = new BigDecimal(100); + BigDecimal multiplier = (onehundred).subtract(discount); + multiplier = multiplier.divide(onehundred, 6, BigDecimal.ROUND_HALF_UP); + BigDecimal newPrice = Price.multiply(multiplier); + log.fine("=>" + newPrice); + return newPrice; + } // calculatePrice + + /** + * Calculate Discount Percentage + * @param Qty quantity + * @param Price price + * @param M_Product_ID product + * @param M_Product_Category_ID category + * @param BPartnerFlatDiscount flat discount + * @return discount or zero + */ + public BigDecimal calculateDiscount (BigDecimal Qty, BigDecimal Price, + int M_Product_ID, int M_Product_Category_ID, + BigDecimal BPartnerFlatDiscount) + { + if (BPartnerFlatDiscount == null) + BPartnerFlatDiscount = Env.ZERO; + + // + if (DISCOUNTTYPE_FlatPercent.equals(getDiscountType())) + { + if (isBPartnerFlatDiscount()) + return BPartnerFlatDiscount; + return getFlatDiscount(); + } + // Not supported + else if (DISCOUNTTYPE_Formula.equals(getDiscountType()) + || DISCOUNTTYPE_Pricelist.equals(getDiscountType())) + { + log.info ("Not supported (yet) DiscountType=" + getDiscountType()); + return Env.ZERO; + } + + // Price Breaks + getBreaks(false); + boolean found = false; + BigDecimal Amt = Price.multiply(Qty); + if (isQuantityBased()) + log.finer("Qty=" + Qty + ",M_Product_ID=" + M_Product_ID + ",M_Product_Category_ID=" + M_Product_Category_ID); + else + log.finer("Amt=" + Amt + ",M_Product_ID=" + M_Product_ID + ",M_Product_Category_ID=" + M_Product_Category_ID); + for (int i = 0; i < m_breaks.length; i++) + { + MDiscountSchemaBreak br = m_breaks[i]; + if (!br.isActive()) + continue; + + if (isQuantityBased()) + { + if (!br.applies(Qty, M_Product_ID, M_Product_Category_ID)) + { + log.finer("No: " + br); + continue; + } + log.finer("Yes: " + br); + } + else + { + if (!br.applies(Amt, M_Product_ID, M_Product_Category_ID)) + { + log.finer("No: " + br); + continue; + } + log.finer("Yes: " + br); + } + + // Line applies + BigDecimal discount = null; + if (br.isBPartnerFlatDiscount()) + discount = BPartnerFlatDiscount; + else + discount = br.getBreakDiscount(); + log.fine("Discount=>" + discount); + return discount; + } // for all breaks + + return Env.ZERO; + } // calculateDiscount + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getValidFrom() == null) + setValidFrom (TimeUtil.getDay(null)); + + return true; + } // beforeSave + + /** + * Renumber + * @return lines updated + */ + public int reSeq() + { + int count = 0; + // Lines + MDiscountSchemaLine[] lines = getLines(true); + for (int i = 0; i < lines.length; i++) + { + int line = (i+1) * 10; + if (line != lines[i].getSeqNo()) + { + lines[i].setSeqNo(line); + if (lines[i].save()) + count++; + } + } + m_lines = null; + + // Breaks + MDiscountSchemaBreak[] breaks = getBreaks(true); + for (int i = 0; i < breaks.length; i++) + { + int line = (i+1) * 10; + if (line != breaks[i].getSeqNo()) + { + breaks[i].setSeqNo(line); + if (breaks[i].save()) + count++; + } + } + m_breaks = null; + return count; + } // reSeq + +} // MDiscountSchema diff --git a/base/src/org/compiere/model/MDiscountSchemaBreak.java b/base/src/org/compiere/model/MDiscountSchemaBreak.java new file mode 100644 index 0000000000..43f507b785 --- /dev/null +++ b/base/src/org/compiere/model/MDiscountSchemaBreak.java @@ -0,0 +1,110 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; + + +/** + * Discount Break Schema (Model) + * + * @author Jorg Janke + * @version $Id: MDiscountSchemaBreak.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MDiscountSchemaBreak extends X_M_DiscountSchemaBreak +{ + + /** + * Standard Constructor + * @param ctx context + * @param M_DiscountSchemaBreak_ID id + * @param trxName transaction + */ + public MDiscountSchemaBreak (Properties ctx, int M_DiscountSchemaBreak_ID, String trxName) + { + super (ctx, M_DiscountSchemaBreak_ID, trxName); + } // MDiscountSchemaBreak + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MDiscountSchemaBreak (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MDiscountSchemaBreak + + + /** + * Criteria apply + * @param Value amt or qty + * @param M_Product_ID product + * @param M_Product_Category_ID category + * @return true if criteria met + */ + public boolean applies (BigDecimal Value, int M_Product_ID, int M_Product_Category_ID) + { + if (!isActive()) + return false; + + // below break value + if (Value.compareTo(getBreakValue()) < 0) + return false; + + // No Product / Category + if (getM_Product_ID() == 0 + && getM_Product_Category_ID() == 0) + return true; + + // Product + if (getM_Product_ID() == M_Product_ID) + return true; + + // Category + if (M_Product_Category_ID != 0) + return getM_Product_Category_ID() == M_Product_Category_ID; + + // Look up Category of Product + return MProductCategory.isCategory(getM_Product_Category_ID(), M_Product_ID); + } // applies + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MDiscountSchemaBreak["); + sb.append(get_ID()).append("-Seq=").append(getSeqNo()); + if (getM_Product_Category_ID() != 0) + sb.append(",M_Product_Category_ID=").append(getM_Product_Category_ID()); + if (getM_Product_ID() != 0) + sb.append(",M_Product_ID=").append(getM_Product_ID()); + sb.append(",Break=").append(getBreakValue()); + if (isBPartnerFlatDiscount()) + sb.append(",FlatDiscount"); + else + sb.append(",Discount=").append(getBreakDiscount()); + sb.append ("]"); + return sb.toString (); + } // toString + +} // MDiscountSchemaBreak diff --git a/base/src/org/compiere/model/MDiscountSchemaLine.java b/base/src/org/compiere/model/MDiscountSchemaLine.java new file mode 100644 index 0000000000..3efc9659ec --- /dev/null +++ b/base/src/org/compiere/model/MDiscountSchemaLine.java @@ -0,0 +1,54 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Discount Schema Line (Price List) Model + * + * @author Jorg Janke + * @version $Id: MDiscountSchemaLine.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MDiscountSchemaLine extends X_M_DiscountSchemaLine +{ + + /** + * Standard Constructor + * @param ctx context + * @param M_DiscountSchemaLine_ID id + * @param trxName transaction + */ + public MDiscountSchemaLine (Properties ctx, int M_DiscountSchemaLine_ID, String trxName) + { + super (ctx, M_DiscountSchemaLine_ID, trxName); + } // MDiscountSchemaLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MDiscountSchemaLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MDiscountSchemaLine + +} // MDiscountSchemaLine diff --git a/base/src/org/compiere/model/MDistribution.java b/base/src/org/compiere/model/MDistribution.java new file mode 100644 index 0000000000..3f1b396b4b --- /dev/null +++ b/base/src/org/compiere/model/MDistribution.java @@ -0,0 +1,441 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * GL Distribution Model + * + * @author Jorg Janke + * @version $Id: MDistribution.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MDistribution extends X_GL_Distribution +{ + /** + * Get Distribution for combination + * @param acct account (ValidCombination) + * @param PostingType only posting type + * @param C_DocType_ID only document type + * @return array of distributions + */ + public static MDistribution[] get (MAccount acct, + String PostingType, int C_DocType_ID) + { + return get (acct.getCtx(), acct.getC_AcctSchema_ID(), + PostingType, C_DocType_ID, + acct.getAD_Org_ID(), acct.getAccount_ID(), + acct.getM_Product_ID(), acct.getC_BPartner_ID(), acct.getC_Project_ID(), + acct.getC_Campaign_ID(), acct.getC_Activity_ID(), acct.getAD_OrgTrx_ID(), + acct.getC_SalesRegion_ID(), acct.getC_LocTo_ID(), acct.getC_LocFrom_ID(), + acct.getUser1_ID(), acct.getUser2_ID()); + } // get + + /** + * Get Distributions for combination + * @param ctx context + * @param C_AcctSchema_ID schema + * @param PostingType posting type + * @param C_DocType_ID document type + * @param AD_Org_ID org + * @param Account_ID account + * @param M_Product_ID product + * @param C_BPartner_ID partner + * @param C_Project_ID project + * @param C_Campaign_ID campaign + * @param C_Activity_ID activity + * @param AD_OrgTrx_ID trx org + * @param C_SalesRegion_ID + * @param C_LocTo_ID location to + * @param C_LocFrom_ID location from + * @param User1_ID user 1 + * @param User2_ID user 2 + * @return array of distributions or null + */ + public static MDistribution[] get (Properties ctx, int C_AcctSchema_ID, + String PostingType, int C_DocType_ID, + int AD_Org_ID, int Account_ID, + int M_Product_ID, int C_BPartner_ID, int C_Project_ID, + int C_Campaign_ID, int C_Activity_ID, int AD_OrgTrx_ID, + int C_SalesRegion_ID, int C_LocTo_ID, int C_LocFrom_ID, + int User1_ID, int User2_ID) + { + MDistribution[] acctList = get (ctx, Account_ID); + if (acctList == null || acctList.length == 0) + return null; + // + ArrayList list = new ArrayList(); + for (int i = 0; i < acctList.length; i++) + { + MDistribution distribution = acctList[i]; + if (!distribution.isActive() || !distribution.isValid()) + continue; + // Mandatory Acct Schema + if (distribution.getC_AcctSchema_ID() != C_AcctSchema_ID) + continue; + // Only Posting Type / DocType + if (distribution.getPostingType() != null && !distribution.getPostingType().equals(PostingType)) + continue; + if (distribution.getC_DocType_ID() != 0 && distribution.getC_DocType_ID() != C_DocType_ID) + continue; + + // Optional Elements - "non-Any" + if (!distribution.isAnyOrg() && distribution.getAD_Org_ID() != AD_Org_ID) + continue; + if (!distribution.isAnyAcct() && distribution.getAccount_ID() != Account_ID) + continue; + if (!distribution.isAnyProduct() && distribution.getM_Product_ID() != M_Product_ID) + continue; + if (!distribution.isAnyBPartner() && distribution.getC_BPartner_ID() != C_BPartner_ID) + continue; + if (!distribution.isAnyProject() && distribution.getC_Project_ID() != C_Project_ID) + continue; + if (!distribution.isAnyCampaign() && distribution.getC_Campaign_ID() != C_Campaign_ID) + continue; + if (!distribution.isAnyActivity() && distribution.getC_Activity_ID() != C_Activity_ID) + continue; + if (!distribution.isAnyOrgTrx() && distribution.getAD_OrgTrx_ID() != AD_OrgTrx_ID) + continue; + if (!distribution.isAnySalesRegion() && distribution.getC_SalesRegion_ID() != C_SalesRegion_ID) + continue; + if (!distribution.isAnyLocTo() && distribution.getC_LocTo_ID() != C_LocTo_ID) + continue; + if (!distribution.isAnyLocFrom() && distribution.getC_LocFrom_ID() != C_LocFrom_ID) + continue; + if (!distribution.isAnyUser1() && distribution.getUser1_ID() != User1_ID) + continue; + if (!distribution.isAnyUser2() && distribution.getUser2_ID() != User2_ID) + continue; + // + list.add (distribution); + } // for all distributions with acct + // + MDistribution[] retValue = new MDistribution[list.size ()]; + list.toArray (retValue); + return retValue; + } // get + + /** + * Get Distributions for Account + * @param ctx context + * @param Account_ID id + * @return array of distributions + */ + public static MDistribution[] get (Properties ctx, int Account_ID) + { + Integer key = new Integer (Account_ID); + MDistribution[] retValue = (MDistribution[])s_accounts.get(key); + if (retValue != null) + return retValue; + + String sql = "SELECT * FROM GL_Distribution " + + "WHERE Account_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, Account_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MDistribution (ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + retValue = new MDistribution[list.size ()]; + list.toArray (retValue); + s_accounts.put(key, retValue); + return retValue; + } // get + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MDistribution.class); + /** Distributions by Account */ + private static CCache s_accounts + = new CCache("GL_Distribution", 100); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param GL_Distribution_ID id + * @param trxName transaction + */ + public MDistribution (Properties ctx, int GL_Distribution_ID, String trxName) + { + super (ctx, GL_Distribution_ID, trxName); + if (GL_Distribution_ID == 0) + { + // setC_AcctSchema_ID (0); + // setName (null); + // + setAnyAcct (true); // Y + setAnyActivity (true); // Y + setAnyBPartner (true); // Y + setAnyCampaign (true); // Y + setAnyLocFrom (true); // Y + setAnyLocTo (true); // Y + setAnyOrg (true); // Y + setAnyOrgTrx (true); // Y + setAnyProduct (true); // Y + setAnyProject (true); // Y + setAnySalesRegion (true); // Y + setAnyUser1 (true); // Y + setAnyUser2 (true); // Y + // + setIsValid (false); // N + setPercentTotal (Env.ZERO); + } + } // MDistribution + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MDistribution (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MDistribution + + /** The Lines */ + private MDistributionLine[] m_lines = null; + + /** + * Get Lines and calculate total + * @param reload reload data + * @return array of lines + */ + public MDistributionLine[] getLines (boolean reload) + { + if (m_lines != null && !reload) + return m_lines; + + BigDecimal PercentTotal = Env.ZERO; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM GL_DistributionLine " + + "WHERE GL_Distribution_ID=? ORDER BY Line"; + boolean hasNullRemainder = false; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getGL_Distribution_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MDistributionLine dl = new MDistributionLine (getCtx(), rs, get_TrxName()); + if (dl.isActive()) + { + PercentTotal = PercentTotal.add(dl.getPercent()); + hasNullRemainder = Env.ZERO.compareTo(dl.getPercent()) == 0; + } + dl.setParent(this); + list.add (dl); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getLines", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // Update Ratio when saved and difference + if (hasNullRemainder) + PercentTotal = Env.ONEHUNDRED; + if (get_ID() != 0 && PercentTotal.compareTo(getPercentTotal()) != 0) + { + setPercentTotal(PercentTotal); + save(); + } + // return + m_lines = new MDistributionLine[list.size ()]; + list.toArray (m_lines); + return m_lines; + } // getLines + + /** + * Validate Distribution + * @return error message or null + */ + public String validate() + { + String retValue = null; + getLines(true); + if (m_lines.length == 0) + retValue = "@NoLines@"; + else if (getPercentTotal().compareTo(Env.ONEHUNDRED) != 0) + retValue = "@PercentTotal@ <> 100"; + else + { + // More then one line with 0 + int lineFound = -1; + for (int i = 0; i < m_lines.length; i++) + { + if (m_lines[i].getPercent().compareTo(Env.ZERO) == 0) + { + if (lineFound >= 0 && m_lines[i].getPercent().compareTo(Env.ZERO) == 0) + { + retValue = "@Line@ " + lineFound + + " + " + m_lines[i].getLine() + ": == 0"; + break; + } + lineFound = m_lines[i].getLine(); + } + } // for all lines + } + + setIsValid (retValue == null); + return retValue; + } // validate + + + /** + * Distribute Amount to Lines + * @param acct account + * @param Amt amount + * @param C_Currency_ID currency + */ + public void distribute (MAccount acct, BigDecimal Amt, int C_Currency_ID) + { + log.info("distribute - Amt=" + Amt + " - " + acct); + getLines(false); + int precision = MCurrency.getStdPrecision(getCtx(), C_Currency_ID); + // First Round + BigDecimal total = Env.ZERO; + int indexBiggest = -1; + int indexZeroPercent = -1; + for (int i = 0; i < m_lines.length; i++) + { + MDistributionLine dl = m_lines[i]; + if (!dl.isActive()) + continue; + dl.setAccount(acct); + // Calculate Amount + dl.calculateAmt (Amt, precision); + total = total.add(dl.getAmt()); + // log.fine("distribute - Line=" + dl.getLine() + " - " + dl.getPercent() + "% " + dl.getAmt() + " - Total=" + total); + // Remainder + if (dl.getPercent().compareTo(Env.ZERO) == 0) + indexZeroPercent = i; + if (indexZeroPercent == -1) + { + if (indexBiggest == -1) + indexBiggest = i; + else if (dl.getAmt().compareTo(m_lines[indexBiggest].getAmt()) > 0) + indexBiggest = i; + } + } + // Adjust Remainder + BigDecimal difference = Amt.subtract(total); + if (difference.compareTo(Env.ZERO) != 0) + { + if (indexZeroPercent != -1) + { + // log.fine("distribute - Difference=" + difference + " - 0%Line=" + m_lines[indexZeroPercent]); + m_lines[indexZeroPercent].setAmt (difference); + } + else if (indexBiggest != -1) + { + // log.fine("distribute - Difference=" + difference + " - MaxLine=" + m_lines[indexBiggest] + " - " + m_lines[indexBiggest].getAmt()); + m_lines[indexBiggest].setAmt (m_lines[indexBiggest].getAmt().add(difference)); + } + else + log.warning("distribute - Remaining Difference=" + difference); + } + // + if (CLogMgt.isLevelFinest()) + { + for (int i = 0; i < m_lines.length; i++) + { + if (m_lines[i].isActive()) + log.fine("distribute = Amt=" + m_lines[i].getAmt() + " - " + m_lines[i].getAccount()); + } + } + } // distribute + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Reset not selected Any + if (isAnyAcct() && getAccount_ID() != 0) + setAccount_ID(0); + if (isAnyActivity() && getC_Activity_ID() != 0) + setC_Activity_ID(0); + if (isAnyBPartner() && getC_BPartner_ID() != 0) + setC_BPartner_ID(0); + if (isAnyCampaign() && getC_Campaign_ID() != 0) + setC_Campaign_ID(0); + if (isAnyLocFrom() && getC_LocFrom_ID() != 0) + setC_LocFrom_ID(0); + if (isAnyLocTo() && getC_LocTo_ID() != 0) + setC_LocTo_ID(0); + if (isAnyOrg() && getOrg_ID() != 0) + setOrg_ID(0); + if (isAnyOrgTrx() && getAD_OrgTrx_ID() != 0) + setAD_OrgTrx_ID(0); + if (isAnyProduct() && getM_Product_ID() != 0) + setM_Product_ID(0); + if (isAnyProject() && getC_Project_ID() != 0) + setC_Project_ID(0); + if (isAnySalesRegion() && getC_SalesRegion_ID() != 0) + setC_SalesRegion_ID(0); + if (isAnyUser1() && getUser1_ID() != 0) + setUser1_ID(0); + if (isAnyUser2() && getUser2_ID() != 0) + setUser2_ID(0); + return true; + } // beforeSave + +} // MDistribution diff --git a/base/src/org/compiere/model/MDistributionLine.java b/base/src/org/compiere/model/MDistributionLine.java new file mode 100644 index 0000000000..cecde49b72 --- /dev/null +++ b/base/src/org/compiere/model/MDistributionLine.java @@ -0,0 +1,242 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * GL Distribution Line Model + * + * @author Jorg Janke + * @version $Id: MDistributionLine.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MDistributionLine extends X_GL_DistributionLine +{ + /** + * Standard Constructor + * @param ctx context + * @param GL_DistributionLine_ID id + * @param trxName transaction + */ + public MDistributionLine (Properties ctx, int GL_DistributionLine_ID, String trxName) + { + super (ctx, GL_DistributionLine_ID, trxName); + if (GL_DistributionLine_ID == 0) + { + // setGL_Distribution_ID (0); // Parent + // setLine (0); + // + setOverwriteAcct (false); + setOverwriteActivity (false); + setOverwriteBPartner (false); + setOverwriteCampaign (false); + setOverwriteLocFrom (false); + setOverwriteLocTo (false); + setOverwriteOrg (false); + setOverwriteOrgTrx (false); + setOverwriteProduct (false); + setOverwriteProject (false); + setOverwriteSalesRegion (false); + setOverwriteUser1 (false); + setOverwriteUser2 (false); + // + setPercent (Env.ZERO); + } + } // MDistributionLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MDistributionLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MDistributionLine + + /** The Parent */ + private MDistribution m_parent = null; + /** The Amount */ + private BigDecimal m_amt = null; + /** The Base Account */ + private MAccount m_account = null; + + /** + * Get Parent + * @return Returns the parent. + */ + public MDistribution getParent () + { + if (m_parent == null) + m_parent = new MDistribution (getCtx(), getGL_Distribution_ID(), get_TrxName()); + return m_parent; + } // getParent + + /** + * Set Parent + * @param parent The parent to set. + */ + public void setParent (MDistribution parent) + { + m_parent = parent; + } // setParent + + /** + * Set Account + * @param acct account + */ + public void setAccount (MAccount acct) + { + m_account = acct; + } // setAccount + + /** + * Get Account Combination based on Account and Overwrite + * @return account + */ + public MAccount getAccount() + { + MAccount acct = MAccount.get(getCtx(), + m_account.getAD_Client_ID(), + isOverwriteOrg() && getOrg_ID() != 0 ? getOrg_ID() : m_account.getAD_Org_ID(), + m_account.getC_AcctSchema_ID(), + isOverwriteAcct() && getAccount_ID() != 0 ? getAccount_ID() : m_account.getAccount_ID(), + m_account.getC_SubAcct_ID(), + // + isOverwriteProduct() ? getM_Product_ID() : m_account.getM_Product_ID(), + isOverwriteBPartner() ? getC_BPartner_ID() : m_account.getC_BPartner_ID(), + isOverwriteOrgTrx() ? getAD_OrgTrx_ID() : m_account.getAD_OrgTrx_ID(), + isOverwriteLocFrom() ? getC_LocFrom_ID() : m_account.getC_LocFrom_ID(), + isOverwriteLocTo() ? getC_LocTo_ID() : m_account.getC_LocTo_ID(), + isOverwriteSalesRegion() ? getC_SalesRegion_ID() : m_account.getC_SalesRegion_ID(), + isOverwriteProject() ? getC_Project_ID() : m_account.getC_Project_ID(), + isOverwriteCampaign() ? getC_Campaign_ID() : m_account.getC_Campaign_ID(), + isOverwriteActivity() ? getC_Activity_ID() : m_account.getC_Activity_ID(), + isOverwriteUser1() ? getUser1_ID() : m_account.getUser1_ID(), + isOverwriteUser2() ? getUser2_ID() : m_account.getUser2_ID(), + m_account.getUserElement1_ID(), + m_account.getUserElement2_ID()); + return acct; + } // setAccount + + + /************************************************************************** + * Get Distribution Amount + * @return Returns the amt. + */ + public BigDecimal getAmt () + { + return m_amt; + } // getAmt + + /** + * Set Distribution Amount + * @param amt The amt to set. + */ + public void setAmt (BigDecimal amt) + { + m_amt = amt; + } // setAmt + + /** + * Set Distribution Amount + * @param amt The amt to set to be multiplied by percent. + * @param precision precision + */ + public void calculateAmt (BigDecimal amt, int precision) + { + m_amt = amt.multiply(getPercent()); + m_amt = m_amt.divide(Env.ONEHUNDRED, precision, BigDecimal.ROUND_HALF_UP); + } // setAmt + + + + /************************************************************************** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getLine() == 0) + { + String sql = "SELECT COALESCE(MAX(Line),0)+10 FROM GL_DistributionLine WHERE GL_Distribution_ID=?"; + int ii = DB.getSQLValue (get_TrxName(), sql, getGL_Distribution_ID()); + setLine (ii); + } + // Reset not selected Overwrite + if (!isOverwriteAcct() && getAccount_ID() != 0) + setAccount_ID(0); + if (!isOverwriteActivity() && getC_Activity_ID() != 0) + setC_Activity_ID(0); + if (!isOverwriteBPartner() && getC_BPartner_ID() != 0) + setC_BPartner_ID(0); + if (!isOverwriteCampaign() && getC_Campaign_ID() != 0) + setC_Campaign_ID(0); + if (!isOverwriteLocFrom() && getC_LocFrom_ID() != 0) + setC_LocFrom_ID(0); + if (!isOverwriteLocTo() && getC_LocTo_ID() != 0) + setC_LocTo_ID(0); + if (!isOverwriteOrg() && getOrg_ID() != 0) + setOrg_ID(0); + if (!isOverwriteOrgTrx() && getAD_OrgTrx_ID() != 0) + setAD_OrgTrx_ID(0); + if (!isOverwriteProduct() && getM_Product_ID() != 0) + setM_Product_ID(0); + if (!isOverwriteProject() && getC_Project_ID() != 0) + setC_Project_ID(0); + if (!isOverwriteSalesRegion() && getC_SalesRegion_ID() != 0) + setC_SalesRegion_ID(0); + if (!isOverwriteUser1() && getUser1_ID() != 0) + setUser1_ID(0); + if (!isOverwriteUser2() && getUser2_ID() != 0) + setUser2_ID(0); + + // Account Overwrite cannot be 0 + if (isOverwriteAcct() && getAccount_ID() == 0) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@Account_ID@ = 0")); + return false; + } + // Org Overwrite cannot be 0 + if (isOverwriteOrg() && getOrg_ID() == 0) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@Org_ID@ = 0")); + return false; + } + return true; + } // beforeSave + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + getParent(); + m_parent.validate(); + m_parent.save(); + return success; + } // afterSave + +} // MDistributionLine diff --git a/base/src/org/compiere/model/MDistributionList.java b/base/src/org/compiere/model/MDistributionList.java new file mode 100644 index 0000000000..a83ace4504 --- /dev/null +++ b/base/src/org/compiere/model/MDistributionList.java @@ -0,0 +1,113 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Material Distribution List + * + * @author Jorg Janke + * @version $Id: MDistributionList.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MDistributionList extends X_M_DistributionList +{ + /** + * Standard Constructor + * @param ctx context + * @param M_DistributionList_ID id + * @param trxName transaction + */ + public MDistributionList (Properties ctx, int M_DistributionList_ID, String trxName) + { + super (ctx, M_DistributionList_ID, trxName); + } // MDistributionList + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MDistributionList (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MDistributionList + + /** + * Get Distibution Lines. + * Add/Correct also Total Ratio + * @return array of lines + */ + public MDistributionListLine[] getLines() + { + ArrayList list = new ArrayList(); + BigDecimal ratioTotal = Env.ZERO; + // + String sql = "SELECT * FROM M_DistributionListLine WHERE M_DistributionList_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getM_DistributionList_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MDistributionListLine line = new MDistributionListLine(getCtx(), rs, get_TrxName()); + list.add(line); + BigDecimal ratio = line.getRatio(); + if (ratio != null) + ratioTotal = ratioTotal.add(ratio); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getLines", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // Update Ratio + if (ratioTotal.compareTo(getRatioTotal()) != 0) + { + log.info("getLines - Set RatioTotal from " + getRatioTotal() + " to " + ratioTotal); + setRatioTotal(ratioTotal); + save(); + } + + MDistributionListLine[] retValue = new MDistributionListLine[list.size ()]; + list.toArray (retValue); + return retValue; + } // getLines + + + +} // MDistributionList diff --git a/base/src/org/compiere/model/MDistributionListLine.java b/base/src/org/compiere/model/MDistributionListLine.java new file mode 100644 index 0000000000..fb6774e67d --- /dev/null +++ b/base/src/org/compiere/model/MDistributionListLine.java @@ -0,0 +1,81 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + + +/** + * Distribution List Line + * + * @author Jorg Janke + * @version $Id: MDistributionListLine.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MDistributionListLine extends X_M_DistributionListLine +{ + /** + * Standard Constructor + * @param ctx context + * @param M_DistributionListLine_ID id + * @param trxName transaction + */ + public MDistributionListLine (Properties ctx, int M_DistributionListLine_ID, String trxName) + { + super (ctx, M_DistributionListLine_ID, trxName); + } // MDistributionListLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MDistributionListLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MDistributionListLine + + + /** + * Get Min Qty + * @return min Qty or 0 + */ + public BigDecimal getMinQty () + { + BigDecimal minQty = super.getMinQty (); + if (minQty == null) + return Env.ZERO; + return minQty; + } // getMinQty + + + /** + * Get Ratio + * @return ratio or 0 + */ + public BigDecimal getRatio () + { + BigDecimal ratio = super.getRatio(); + if (ratio == null) + return Env.ZERO; + return ratio; + } // getRatio + +} // MDistributionListLine diff --git a/base/src/org/compiere/model/MDistributionRun.java b/base/src/org/compiere/model/MDistributionRun.java new file mode 100644 index 0000000000..8c45ca935d --- /dev/null +++ b/base/src/org/compiere/model/MDistributionRun.java @@ -0,0 +1,102 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Distribution Run Model + * + * @author Jorg Janke + * @version $Id: MDistributionRun.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MDistributionRun extends X_M_DistributionRun +{ + + /** + * Standard Constructor + * @param ctx context + * @param M_DistributionRun_ID id + * @param trxName transaction + */ + public MDistributionRun (Properties ctx, int M_DistributionRun_ID, String trxName) + { + super (ctx, M_DistributionRun_ID, trxName); + } // MDistributionRun + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MDistributionRun (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MDistributionRun + + /** Cached Lines */ + private MDistributionRunLine[] m_lines = null; + + /** + * Get active, non zero lines + * @param reload true if reload + * @return lines + */ + public MDistributionRunLine[] getLines (boolean reload) + { + if (!reload && m_lines != null) + return m_lines; + // + String sql = "SELECT * FROM M_DistributionRunLine " + + "WHERE M_DistributionRun_ID=? AND IsActive='Y' AND TotalQty IS NOT NULL AND TotalQty<> 0 ORDER BY Line"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getM_DistributionRun_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MDistributionRunLine(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_lines = new MDistributionRunLine[list.size()]; + list.toArray (m_lines); + return m_lines; + } // getLines + +} // MDistributionRun diff --git a/base/src/org/compiere/model/MDistributionRunDetail.java b/base/src/org/compiere/model/MDistributionRunDetail.java new file mode 100644 index 0000000000..8b104bfb7e --- /dev/null +++ b/base/src/org/compiere/model/MDistributionRunDetail.java @@ -0,0 +1,194 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Distribution Run Detail + * + * @author Jorg Janke + * @version $Id: MDistributionRunDetail.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MDistributionRunDetail extends X_T_DistributionRunDetail +{ + /** + * Get Distribution Dun details + * @param ctx context + * @param M_DistributionRun_ID id + * @param orderBP if true ordered by Business Partner otherwise Run Line + * @param trxName transaction + * @return array of details + */ + static public MDistributionRunDetail[] get (Properties ctx, int M_DistributionRun_ID, + boolean orderBP, String trxName) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM T_DistributionRunDetail WHERE M_DistributionRun_ID=? "; + if (orderBP) + sql += "ORDER BY C_BPartner_ID, C_BPartner_Location_ID"; + else + sql += "ORDER BY M_DistributionRunLine_ID"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_DistributionRun_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MDistributionRunDetail(ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MDistributionRunDetail[] retValue = new MDistributionRunDetail[list.size()]; + list.toArray (retValue); + return retValue; + } // get + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MDistributionRunDetail.class); + + /** + * Standard Constructor + * @param ctx context + * @param T_DistributionRunDetail_ID id + * @param trxName trx + */ + public MDistributionRunDetail (Properties ctx, int T_DistributionRunDetail_ID, String trxName) + { + super (ctx, T_DistributionRunDetail_ID, trxName); + } // MDistributionRunDetail + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MDistributionRunDetail (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // DistributionRunDetail + + /** Precision */ + private int m_precision = 0; + + /** + * Round MinQty & Qty + * @param precision precision (saved) + */ + public void round (int precision) + { + boolean dirty = false; + m_precision = precision; + BigDecimal min = getMinQty(); + if (min.scale() > m_precision) + { + setMinQty(min.setScale(m_precision, BigDecimal.ROUND_HALF_UP)); + dirty = true; + } + BigDecimal qty = getQty(); + if (qty.scale() > m_precision) + { + setQty(qty.setScale(m_precision, BigDecimal.ROUND_HALF_UP)); + dirty = true; + } + if (dirty) + save(); + } // round + + /** + * We can adjust Allocation Qty + * @return true if qty > min + */ + public boolean isCanAdjust() + { + return (getQty().compareTo(getMinQty()) > 0); + } // isCanAdjust + + /** + * Get Actual Allocation Qty + * @return the greater of the min/qty + */ + public BigDecimal getActualAllocation() + { + if (getQty().compareTo(getMinQty()) > 0) + return getQty(); + else + return getMinQty(); + } // getActualAllocation + + /** + * Adjust the Quantity maintaining UOM precision + * @param difference difference + * @return remaining difference (because under Min or rounding) + */ + public BigDecimal adjustQty (BigDecimal difference) + { + BigDecimal diff = difference.setScale(m_precision, BigDecimal.ROUND_HALF_UP); + BigDecimal qty = getQty(); + BigDecimal max = getMinQty().subtract(qty); + BigDecimal remaining = Env.ZERO; + if (max.compareTo(diff) > 0) // diff+max are negative + { + remaining = diff.subtract(max); + setQty(qty.add(max)); + } + else + setQty(qty.add(diff)); + log.fine("Qty=" + qty + ", Min=" + getMinQty() + + ", Max=" + max + ", Diff=" + diff + ", newQty=" + getQty() + + ", Remaining=" + remaining); + return remaining; + } // adjustQty + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MDistributionRunDetail[") + .append (get_ID ()) + .append (";M_DistributionListLine_ID=").append (getM_DistributionListLine_ID()) + .append(";Qty=").append(getQty()) + .append(";Ratio=").append(getRatio()) + .append(";MinQty=").append(getMinQty()) + .append ("]"); + return sb.toString (); + } // toString + +} // DistributionRunDetail diff --git a/base/src/org/compiere/model/MDistributionRunLine.java b/base/src/org/compiere/model/MDistributionRunLine.java new file mode 100644 index 0000000000..f9f74d374b --- /dev/null +++ b/base/src/org/compiere/model/MDistributionRunLine.java @@ -0,0 +1,255 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Distribution Run List Line Model + * + * @author Jorg Janke + * @version $Id: MDistributionRunLine.java,v 1.4 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MDistributionRunLine extends X_M_DistributionRunLine +{ + + /** + * Standard Constructor + * @param ctx context + * @param M_DistributionRunLine_ID id + * @param trxName transaction + */ + public MDistributionRunLine (Properties ctx, int M_DistributionRunLine_ID, String trxName) + { + super (ctx, M_DistributionRunLine_ID, trxName); + } // MDistributionRunLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MDistributionRunLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MDistributionRunLine + + /** Product */ + private MProduct m_product = null; + /** Actual Qty */ + private BigDecimal m_actualQty = Env.ZERO; + /** Actual Min */ + private BigDecimal m_actualMin = Env.ZERO; + /** Actual Allocation */ + private BigDecimal m_actualAllocation = Env.ZERO; + /** Last Allocation Difference */ + private BigDecimal m_lastDifference = Env.ZERO; + /** Max Allocation */ + private BigDecimal m_maxAllocation = Env.ZERO; + + + /** + * Get Actual Qty + * @return actual Qty + */ + public BigDecimal getActualQty() + { + return m_actualQty; + } // getActualQty + + /** + * Add to Actual Qty + * @param add number to add + */ + public void addActualQty(BigDecimal add) + { + m_actualQty = m_actualQty.add(add); + } // addActualQty + + /** + * Get Actual Min Qty + * @return actual Min Qty + */ + public BigDecimal getActualMin() + { + return m_actualMin; + } // getActualMin + + /** + * Add to Actual Min Qty + * @param add number to add + */ + public void addActualMin(BigDecimal add) + { + m_actualMin = m_actualMin.add(add); + } // addActualMin + + /** + * Is Actual Min Greater than Total + * @return true if act min > total + */ + public boolean isActualMinGtTotal() + { + return m_actualMin.compareTo(getTotalQty()) > 0; + } // isActualMinGtTotal + + + /** + * Get Actual Allocation Qty + * @return actual Allocation Qty + */ + public BigDecimal getActualAllocation() + { + return m_actualAllocation; + } // getActualAllocation + + /** + * Add to Actual Min Qty + * @param add number to add + */ + public void addActualAllocation(BigDecimal add) + { + m_actualAllocation = m_actualAllocation.add(add); + } // addActualAllocation + + /** + * Is Actual Allocation equals Total + * @return true if act allocation = total + */ + public boolean isActualAllocationEqTotal() + { + return m_actualAllocation.compareTo(getTotalQty()) == 0; + } // isActualAllocationEqTotal + + /** + * Get Allocation Difference + * @return Total - Allocation Qty + */ + public BigDecimal getActualAllocationDiff() + { + return getTotalQty().subtract(m_actualAllocation); + } // getActualAllocationDiff + + + /** + * Get Last Allocation Difference + * @return difference + */ + public BigDecimal getLastDifference() + { + return m_lastDifference; + } // getLastDifference + + /** + * Set Last Allocation Difference + * @param difference difference + */ + public void setLastDifference(BigDecimal difference) + { + m_lastDifference = difference; + } // setLastDifference + + /** + * Get Max Allocation + * @return max allocation + */ + public BigDecimal getMaxAllocation() + { + return m_maxAllocation; + } // getMaxAllocation + + /** + * Set Max Allocation if greater + * @param max allocation + * @param set set to max + */ + public void setMaxAllocation (BigDecimal max, boolean set) + { + if (set || max.compareTo(m_maxAllocation) > 0) + m_maxAllocation = max; + } // setMaxAllocation + + /** + * Reset Calculations + */ + public void resetCalculations() + { + m_actualQty = Env.ZERO; + m_actualMin = Env.ZERO; + m_actualAllocation = Env.ZERO; + // m_lastDifference = Env.ZERO; + m_maxAllocation = Env.ZERO; + + } // resetCalculations + + + /************************************************************************** + * Get Product + * @return product + */ + public MProduct getProduct() + { + if (m_product == null) + m_product = MProduct.get(getCtx(), getM_Product_ID()); + return m_product; + } // getProduct + + /** + * Get Product Standard Precision + * @return standard precision + */ + public int getUOMPrecision() + { + return getProduct().getUOMPrecision(); + } // getUOMPrecision + + + /************************************************************************** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MDistributionRunLine[") + .append(get_ID()).append("-") + .append(getInfo()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Get Info + * @return info + */ + public String getInfo() + { + StringBuffer sb = new StringBuffer (); + sb.append("Line=").append(getLine()) + .append (",TotalQty=").append(getTotalQty()) + .append(",SumMin=").append(getActualMin()) + .append(",SumQty=").append(getActualQty()) + .append(",SumAllocation=").append(getActualAllocation()) + .append(",MaxAllocation=").append(getMaxAllocation()) + .append(",LastDiff=").append(getLastDifference()); + return sb.toString (); + } // getInfo + +} // MDistributionRunLine diff --git a/base/src/org/compiere/model/MDocTypeCounter.java b/base/src/org/compiere/model/MDocTypeCounter.java new file mode 100644 index 0000000000..d20bf93fb7 --- /dev/null +++ b/base/src/org/compiere/model/MDocTypeCounter.java @@ -0,0 +1,377 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Counter Document Type Model + * + * @author Jorg Janke + * @version $Id: MDocTypeCounter.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MDocTypeCounter extends X_C_DocTypeCounter +{ + /** + * Get Counter document for document type + * @param ctx context + * @param C_DocType_ID base document + * @return counter document C_DocType_ID or 0 or -1 if no counter doc + */ + public static int getCounterDocType_ID (Properties ctx, int C_DocType_ID) + { + // Direct Relationship + MDocTypeCounter dtCounter = getCounterDocType (ctx, C_DocType_ID); + if (dtCounter != null) + { + if (!dtCounter.isCreateCounter() || !dtCounter.isValid()) + return -1; + return dtCounter.getCounter_C_DocType_ID(); + } + + // Indirect Relationship + int Counter_C_DocType_ID = 0; + MDocType dt = MDocType.get(ctx, C_DocType_ID); + if (!dt.isCreateCounter()) + return -1; + String cDocBaseType = getCounterDocBaseType(dt.getDocBaseType()); + if (cDocBaseType == null) + return 0; + MDocType[] counters = MDocType.getOfDocBaseType(ctx, cDocBaseType); + for (int i = 0; i < counters.length; i++) + { + MDocType counter = counters[i]; + if (counter.isDefaultCounterDoc()) + { + Counter_C_DocType_ID = counter.getC_DocType_ID(); + break; + } + if (counter.isDefault()) + Counter_C_DocType_ID = counter.getC_DocType_ID(); + else if (i == 0) + Counter_C_DocType_ID = counter.getC_DocType_ID(); + } + return Counter_C_DocType_ID; + } // getCounterDocType_ID + + /** + * Get (first) valid Counter document for document type + * @param ctx context + * @param C_DocType_ID base document + * @return counter document (may be invalid) or null + */ + public static MDocTypeCounter getCounterDocType (Properties ctx, int C_DocType_ID) + { + Integer key = new Integer (C_DocType_ID); + MDocTypeCounter retValue = (MDocTypeCounter)s_counter.get(key); + if (retValue != null) + return retValue; + + // Direct Relationship + MDocTypeCounter temp = null; + String sql = "SELECT * FROM C_DocTypeCounter WHERE C_DocType_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, C_DocType_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next () && retValue == null) + { + retValue = new MDocTypeCounter (ctx, rs, null); + if (!retValue.isCreateCounter() || !retValue.isValid()) + { + temp = retValue; + retValue = null; + } + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "getCounterDocType", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (retValue != null) // valid + return retValue; + if (temp != null) // invalid + return temp; + return null; // nothing found + } // getCounterDocType + + /** + * Get MDocTypeCounter from Cache + * @param ctx context + * @param C_DocTypeCounter_ID id + * @return MDocTypeCounter + * @param trxName transaction + */ + public static MDocTypeCounter get (Properties ctx, int C_DocTypeCounter_ID, String trxName) + { + Integer key = new Integer (C_DocTypeCounter_ID); + MDocTypeCounter retValue = (MDocTypeCounter) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MDocTypeCounter (ctx, C_DocTypeCounter_ID, trxName); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** + * Get Counter Document BaseType + * @param DocBaseType Document Base Type (e.g. SOO) + * @return Counter Document BaseType (e.g. POO) or null if there is none + */ + public static String getCounterDocBaseType (String DocBaseType) + { + if (DocBaseType == null) + return null; + String retValue = null; + // SO/PO + if (MDocType.DOCBASETYPE_SalesOrder.equals(DocBaseType)) + retValue = MDocType.DOCBASETYPE_PurchaseOrder; + else if (MDocType.DOCBASETYPE_PurchaseOrder.equals(DocBaseType)) + retValue = MDocType.DOCBASETYPE_SalesOrder; + // AP/AR Invoice + else if (MDocType.DOCBASETYPE_APInvoice.equals(DocBaseType)) + retValue = MDocType.DOCBASETYPE_ARInvoice; + else if (MDocType.DOCBASETYPE_ARInvoice.equals(DocBaseType)) + retValue = MDocType.DOCBASETYPE_APInvoice; + // Shipment + else if (MDocType.DOCBASETYPE_MaterialDelivery.equals(DocBaseType)) + retValue = MDocType.DOCBASETYPE_MaterialReceipt; + else if (MDocType.DOCBASETYPE_MaterialReceipt.equals(DocBaseType)) + retValue = MDocType.DOCBASETYPE_MaterialDelivery; + // AP/AR CreditMemo + else if (MDocType.DOCBASETYPE_APCreditMemo.equals(DocBaseType)) + retValue = MDocType.DOCBASETYPE_ARCreditMemo; + else if (MDocType.DOCBASETYPE_ARCreditMemo.equals(DocBaseType)) + retValue = MDocType.DOCBASETYPE_APCreditMemo; + // Receipt / Payment + else if (MDocType.DOCBASETYPE_ARReceipt.equals(DocBaseType)) + retValue = MDocType.DOCBASETYPE_APPayment; + else if (MDocType.DOCBASETYPE_APPayment.equals(DocBaseType)) + retValue = MDocType.DOCBASETYPE_ARReceipt; + // + else + s_log.log(Level.SEVERE, "getCounterDocBaseType for " + DocBaseType + ": None found"); + return retValue; + } // getCounterDocBaseType + + + /** Object Cache */ + private static CCache s_cache = new CCache("C_DocTypeCounter", 20); + /** Counter Relationship Cache */ + private static CCache s_counter = new CCache("C_DocTypeCounter", 20); + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MDocTypeCounter.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param C_DocTypeCounter_ID id + * @param trxName transaction + */ + public MDocTypeCounter (Properties ctx, int C_DocTypeCounter_ID, String trxName) + { + super (ctx, C_DocTypeCounter_ID, trxName); + if (C_DocTypeCounter_ID == 0) + { + setIsCreateCounter (true); // Y + setIsValid (false); + } + } // MDocTypeCounter + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MDocTypeCounter (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MDocTypeCounter + + + /** + * Set C_DocType_ID + * @param C_DocType_ID id + */ + public void setC_DocType_ID (int C_DocType_ID) + { + super.setC_DocType_ID (C_DocType_ID); + if (isValid()) + setIsValid(false); + } // setC_DocType_ID + + + /** + * Set Counter C_DocType_ID + * @param Counter_C_DocType_ID id + */ + public void setCounter_C_DocType_ID (int Counter_C_DocType_ID) + { + super.setCounter_C_DocType_ID (Counter_C_DocType_ID); + if (isValid()) + setIsValid(false); + } // setCounter_C_DocType_ID + + /** + * Get Doc Type + * @return doc type or null if not existing + */ + public MDocType getDocType() + { + MDocType dt = null; + if (getC_DocType_ID() > 0) + { + dt = MDocType.get(getCtx(), getC_DocType_ID()); + if (dt.get_ID() == 0) + dt = null; + } + return dt; + } // getDocType + + /** + * Get Counter Doc Type + * @return counter doc type or null if not existing + */ + public MDocType getCounterDocType() + { + MDocType dt = null; + if (getCounter_C_DocType_ID() > 0) + { + dt = MDocType.get(getCtx(), getCounter_C_DocType_ID()); + if (dt.get_ID() == 0) + dt = null; + } + return dt; + } // getCounterDocType + + + /************************************************************************** + * Validate Document Type compatability + * @return Error message or null if valid + */ + public String validate() + { + MDocType dt = getDocType(); + if (dt == null) + { + log.log(Level.SEVERE, "No DocType=" + getC_DocType_ID()); + setIsValid(false); + return "No Document Type"; + } + MDocType c_dt = getCounterDocType(); + if (c_dt == null) + { + log.log(Level.SEVERE, "No Counter DocType=" + getCounter_C_DocType_ID()); + setIsValid(false); + return "No Counter Document Type"; + } + // + String dtBT = dt.getDocBaseType(); + String c_dtBT = c_dt.getDocBaseType(); + log.fine(dtBT + " -> " + c_dtBT); + + // SO / PO + if ((MDocType.DOCBASETYPE_SalesOrder.equals(dtBT) && MDocType.DOCBASETYPE_PurchaseOrder.equals(c_dtBT)) + || (MDocType.DOCBASETYPE_SalesOrder.equals(c_dtBT) && MDocType.DOCBASETYPE_PurchaseOrder.equals(dtBT))) + setIsValid(true); + // AP/AR Invoice + else if ((MDocType.DOCBASETYPE_APInvoice.equals(dtBT) && MDocType.DOCBASETYPE_ARInvoice.equals(c_dtBT)) + || (MDocType.DOCBASETYPE_APInvoice.equals(c_dtBT) && MDocType.DOCBASETYPE_ARInvoice.equals(dtBT))) + setIsValid(true); + // Shipment + else if ((MDocType.DOCBASETYPE_MaterialDelivery.equals(dtBT) && MDocType.DOCBASETYPE_MaterialReceipt.equals(c_dtBT)) + || (MDocType.DOCBASETYPE_MaterialDelivery.equals(c_dtBT) && MDocType.DOCBASETYPE_MaterialReceipt.equals(dtBT))) + setIsValid(true); + // AP/AR CreditMemo + else if ((MDocType.DOCBASETYPE_APCreditMemo.equals(dtBT) && MDocType.DOCBASETYPE_ARCreditMemo.equals(c_dtBT)) + || (MDocType.DOCBASETYPE_APCreditMemo.equals(c_dtBT) && MDocType.DOCBASETYPE_ARCreditMemo.equals(dtBT))) + setIsValid(true); + // Receipt / Payment + else if ((MDocType.DOCBASETYPE_ARReceipt.equals(dtBT) && MDocType.DOCBASETYPE_APPayment.equals(c_dtBT)) + || (MDocType.DOCBASETYPE_ARReceipt.equals(c_dtBT) && MDocType.DOCBASETYPE_APPayment.equals(dtBT))) + setIsValid(true); + else + { + log.warning("NOT - " + dtBT + " -> " + c_dtBT); + setIsValid(false); + return "Not valid"; + } + // Counter should have document numbering + if (!c_dt.isDocNoControlled()) + return "Counter Document Type should be automatically Document Number controlled"; + return null; + } // validate + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MDocTypeCounter["); + sb.append(get_ID()).append(",").append(getName()) + .append(",C_DocType_ID=").append(getC_DocType_ID()) + .append(",Counter=").append(getCounter_C_DocType_ID()) + .append(",DocAction=").append(getDocAction()) + .append ("]"); + return sb.toString (); + } // toString + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getAD_Org_ID() != 0) + setAD_Org_ID(0); + + if (!newRecord + && (is_ValueChanged("C_DocType_ID") || is_ValueChanged("Counter_C_DocType_ID"))) + setIsValid(false); + + // try to validate + if (!isValid()) + validate(); + return true; + } // beforeSave + +} // MDocTypeCounter diff --git a/base/src/org/compiere/model/MDunning.java b/base/src/org/compiere/model/MDunning.java new file mode 100644 index 0000000000..bc115c2b74 --- /dev/null +++ b/base/src/org/compiere/model/MDunning.java @@ -0,0 +1,53 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Dunning Model + * + * @author Jorg Janke + * @version $Id: MDunning.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MDunning extends X_C_Dunning +{ + /** + * Standard Constructor + * @param ctx context + * @param C_Dunning_ID id + * @param trxName transaction + */ + public MDunning (Properties ctx, int C_Dunning_ID, String trxName) + { + super (ctx, C_Dunning_ID, trxName); + } // MDunning + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MDunning (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MDunning + +} // MDunning diff --git a/base/src/org/compiere/model/MDunningLevel.java b/base/src/org/compiere/model/MDunningLevel.java new file mode 100644 index 0000000000..3834b704c2 --- /dev/null +++ b/base/src/org/compiere/model/MDunningLevel.java @@ -0,0 +1,53 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Dunning Level Model + * + * @author Jorg Janke + * @version $Id: MDunningLevel.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MDunningLevel extends X_C_DunningLevel +{ + /** + * Standard Constructor + * @param ctx context + * @param C_DunningLevel_ID id + * @param trxName transaction + */ + public MDunningLevel (Properties ctx, int C_DunningLevel_ID, String trxName) + { + super (ctx, C_DunningLevel_ID, trxName); + } // MDunningLevel + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MDunningLevel (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MDunningLevel + +} // MDunningLevel diff --git a/base/src/org/compiere/model/MDunningRun.java b/base/src/org/compiere/model/MDunningRun.java new file mode 100644 index 0000000000..150c4f1183 --- /dev/null +++ b/base/src/org/compiere/model/MDunningRun.java @@ -0,0 +1,168 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Dunning Run Model + * + * @author Jorg Janke + * @version $Id: MDunningRun.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MDunningRun extends X_C_DunningRun +{ + /** + * Standard Constructor + * @param ctx context + * @param C_DunningRun_ID id + * @param trxName transaction + */ + public MDunningRun (Properties ctx, int C_DunningRun_ID, String trxName) + { + super (ctx, C_DunningRun_ID, trxName); + if (C_DunningRun_ID == 0) + { + // setC_DunningLevel_ID (0); + setDunningDate (new Timestamp(System.currentTimeMillis())); + setProcessed (false); + } + } // MDunningRun + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MDunningRun (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MDunningRun + + private MDunningLevel m_level = null; + private MDunningRunEntry[] m_entries = null; + + /** + * Get Dunning Level + * @return level + */ + public MDunningLevel getLevel() + { + if (m_level == null) + m_level = new MDunningLevel (getCtx(), getC_DunningLevel_ID(), get_TrxName()); + return m_level; + } // getLevel + + /** + * Get Entries + * @param requery requery + * @return entries + */ + public MDunningRunEntry[] getEntries (boolean requery) + { + if (m_entries != null && !requery) + return m_entries; + + String sql = "SELECT * FROM C_DunningRunEntry WHERE C_DunningRun_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_DunningRun_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MDunningRunEntry(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getEntries", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_entries = new MDunningRunEntry[list.size ()]; + list.toArray (m_entries); + return m_entries; + } // getEntries + + /** + * Delete all Entries + * @param force delete also processed records + * @return true if deleted + */ + public boolean deleteEntries(boolean force) + { + getEntries(true); + for (int i = 0; i < m_entries.length; i++) + { + MDunningRunEntry entry = m_entries[i]; + entry.delete(force); + } + boolean ok = getEntries(true).length == 0; + if (ok) + m_entries = null; + return ok; + } // deleteEntries + + /** + * Get/Create Entry for BPartner + * @param C_BPartner_ID business partner + * @param C_Currency_ID currency + * @param SalesRep_ID sales rep + * @return entry + */ + public MDunningRunEntry getEntry (int C_BPartner_ID, int C_Currency_ID, int SalesRep_ID) + { + // TODO: Related BP + int C_BPartnerRelated_ID = C_BPartner_ID; + // + getEntries(false); + for (int i = 0; i < m_entries.length; i++) + { + MDunningRunEntry entry = m_entries[i]; + if (entry.getC_BPartner_ID() == C_BPartnerRelated_ID) + return entry; + } + // New Entry + MDunningRunEntry entry = new MDunningRunEntry (this); + MBPartner bp = new MBPartner (getCtx(), C_BPartnerRelated_ID, get_TrxName()); + entry.setBPartner(bp, true); // AR hardcoded + // + if (entry.getSalesRep_ID() == 0) + entry.setSalesRep_ID (SalesRep_ID); + entry.setC_Currency_ID (C_Currency_ID); + // + m_entries = null; + return entry; + } // getEntry + +} // MDunningRun diff --git a/base/src/org/compiere/model/MDunningRunEntry.java b/base/src/org/compiere/model/MDunningRunEntry.java new file mode 100644 index 0000000000..c0ae5698d5 --- /dev/null +++ b/base/src/org/compiere/model/MDunningRunEntry.java @@ -0,0 +1,136 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Dunning Run Entry Model + * + * @author Jorg Janke + * @version $Id: MDunningRunEntry.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MDunningRunEntry extends X_C_DunningRunEntry +{ + /** + * Standard Constructor + * @param ctx context + * @param C_DunningRunEntry_ID id + * @param trxName transaction + */ + public MDunningRunEntry (Properties ctx, int C_DunningRunEntry_ID, String trxName) + { + super (ctx, C_DunningRunEntry_ID, trxName); + if (C_DunningRunEntry_ID == 0) + { + // setC_BPartner_ID (0); + // setC_BPartner_Location_ID (0); + // setAD_User_ID (0); + + // setSalesRep_ID (0); + // setC_Currency_ID (0); + setAmt (Env.ZERO); + setQty (Env.ZERO); + setProcessed (false); + } + } // MDunningRunEntry + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MDunningRunEntry (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MDunningRunEntry + + /** + * Parent Constructor + * @param parent parent + */ + public MDunningRunEntry (MDunningRun parent) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setC_DunningRun_ID(parent.getC_DunningRun_ID()); + m_parent = parent; + } // MDunningRunEntry + + /** Parent */ + private MDunningRun m_parent = null; + + /** + * Set BPartner + * @param bp partner + * @param isSOTrx SO + */ + public void setBPartner (MBPartner bp, boolean isSOTrx) + { + setC_BPartner_ID(bp.getC_BPartner_ID()); + MBPartnerLocation[] locations = bp.getLocations(false); + // Location + if (locations.length == 1) + setC_BPartner_Location_ID (locations[0].getC_BPartner_Location_ID()); + else + { + for (int i = 0; i < locations.length; i++) + { + MBPartnerLocation location = locations[i]; + if ((location.isPayFrom() && isSOTrx) + || (location.isRemitTo() && !isSOTrx)) + { + setC_BPartner_Location_ID (location.getC_BPartner_Location_ID()); + break; + } + } + } + if (getC_BPartner_Location_ID() == 0) + { + String msg = "@C_BPartner_ID@ " + bp.getName(); + if (isSOTrx) + msg += " @No@ @IsPayFrom@"; + else + msg += " @No@ @IsRemitTo@"; + throw new IllegalArgumentException (msg); + } + // User with location + MUser[] users = MUser.getOfBPartner(getCtx(), bp.getC_BPartner_ID()); + if (users.length == 1) + setAD_User_ID (users[0].getAD_User_ID()); + else + { + for (int i = 0; i < users.length; i++) + { + MUser user = users[i]; + if (user.getC_BPartner_Location_ID() == getC_BPartner_Location_ID()) + { + setAD_User_ID (users[i].getAD_User_ID()); + break; + } + } + } + // + int SalesRep_ID = bp.getSalesRep_ID(); + if (SalesRep_ID != 0) + setSalesRep_ID (SalesRep_ID); + } // setBPartner + +} // MDunningRunEntry diff --git a/base/src/org/compiere/model/MDunningRunLine.java b/base/src/org/compiere/model/MDunningRunLine.java new file mode 100644 index 0000000000..7c2519bf7d --- /dev/null +++ b/base/src/org/compiere/model/MDunningRunLine.java @@ -0,0 +1,306 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Dunning Run Line Model + * + * @author Jorg Janke + * @version $Id: MDunningRunLine.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MDunningRunLine extends X_C_DunningRunLine +{ + /** + * Standarc Constructor + * @param ctx ctx + * @param C_DunningRunLine_ID id + * @param trxName transaction + */ + public MDunningRunLine (Properties ctx, int C_DunningRunLine_ID, String trxName) + { + super (ctx, C_DunningRunLine_ID, trxName); + if (C_DunningRunLine_ID == 0) + { + setAmt (Env.ZERO); + setOpenAmt(Env.ZERO); + setConvertedAmt (Env.ZERO); + setFeeAmt (Env.ZERO); + setInterestAmt (Env.ZERO); + setTotalAmt (Env.ZERO); + setDaysDue (0); + setTimesDunned (0); + setIsInDispute(false); + setProcessed (false); + } + } // MDunningRunLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MDunningRunLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MDunningRunLine + + /** + * Parent Constructor + * @param parent parent + */ + public MDunningRunLine (MDunningRunEntry parent) + { + this(parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setC_DunningRunEntry_ID(parent.getC_DunningRunEntry_ID()); + // + m_parent = parent; + m_C_CurrencyTo_ID = parent.getC_Currency_ID(); + } // MDunningRunLine + + private MDunningRunEntry m_parent = null; + private MInvoice m_invoice = null; + private MPayment m_payment = null; + private int m_C_CurrencyFrom_ID = 0; + private int m_C_CurrencyTo_ID = 0; + + /** + * Get Parent + * @return parent + */ + public MDunningRunEntry getParent() + { + if (m_parent == null) + m_parent = new MDunningRunEntry (getCtx(), getC_DunningRunEntry_ID(), get_TrxName()); + return m_parent; + } // getParent + + /** + * Get Invoice + * @return Returns the invoice. + */ + public MInvoice getInvoice () + { + if (getC_Invoice_ID() == 0) + m_invoice = null; + else if (m_invoice == null) + m_invoice = new MInvoice (getCtx(), getC_Invoice_ID(), get_TrxName()); + return m_invoice; + } // getInvoice + + /** + * Set Invoice + * @param invoice The invoice to set. + */ + public void setInvoice (MInvoice invoice) + { + m_invoice = invoice; + if (invoice != null) + { + m_C_CurrencyFrom_ID = invoice.getC_Currency_ID(); + setAmt(invoice.getGrandTotal()); + setOpenAmt(getAmt()); // not correct + setConvertedAmt (MConversionRate.convert(getCtx(), getOpenAmt(), + getC_CurrencyFrom_ID(), getC_CurrencyTo_ID(), getAD_Client_ID(), getAD_Org_ID())); + } + else + { + m_C_CurrencyFrom_ID = 0; + setAmt(Env.ZERO); + setOpenAmt(Env.ZERO); + setConvertedAmt(Env.ZERO); + } + } // setInvoice + + /** + * Set Invoice + * @param C_Invoice_ID + * @param C_Currency_ID + * @param GrandTotal + * @param Open + * @param DaysDue + * @param IsInDispute + * @param TimesDunned + * @param DaysAfterLast not used + */ + public void setInvoice (int C_Invoice_ID, int C_Currency_ID, + BigDecimal GrandTotal, BigDecimal Open, + int DaysDue, boolean IsInDispute, + int TimesDunned, int DaysAfterLast) + { + setC_Invoice_ID(C_Invoice_ID); + m_C_CurrencyFrom_ID = C_Currency_ID; + setAmt (GrandTotal); + setOpenAmt (Open); + setConvertedAmt (MConversionRate.convert(getCtx(), getOpenAmt(), + C_Currency_ID, getC_CurrencyTo_ID(), getAD_Client_ID(), getAD_Org_ID())); + setIsInDispute(IsInDispute); + setDaysDue(DaysDue); + setTimesDunned(TimesDunned); + } // setInvoice + + + /** + * Get Payment + * @return Returns the payment. + */ + public MPayment getPayment () + { + if (getC_Payment_ID() == 0) + m_payment = null; + else if (m_payment == null) + m_payment = new MPayment (getCtx(), getC_Payment_ID(), get_TrxName()); + return m_payment; + } // getPayment + + /** + * Set Payment + * + public void setPayment (MPayment payment) + { + m_payment = payment; + if (payment != null) + { + m_C_CurrencyFrom_ID = payment.getC_Currency_ID(); + setAmt(payment.getPayAmt()); // need to reverse + setOpenAmt(getAmt()); // not correct + setConvertedAmt (MConversionRate.convert(getCtx(), getOpenAmt(), + getC_CurrencyFrom_ID(), getC_CurrencyTo_ID(), getAD_Client_ID(), getAD_Org_ID())); + } + else + { + m_C_CurrencyFrom_ID = 0; + setAmt(Env.ZERO); + setConvertedAmt(Env.ZERO); + } + } // setPayment + + /** + * Set Payment + * @param C_Payment_ID + * @param C_Currency_ID + * @param PayAmt + * @param OpenAmt + */ + public void setPayment (int C_Payment_ID, int C_Currency_ID, + BigDecimal PayAmt, BigDecimal OpenAmt) + { + setC_Payment_ID(C_Payment_ID); + m_C_CurrencyFrom_ID = C_Currency_ID; + setAmt (PayAmt); + setOpenAmt (OpenAmt); + setConvertedAmt (MConversionRate.convert(getCtx(), getOpenAmt(), + C_Currency_ID, getC_CurrencyTo_ID(), getAD_Client_ID(), getAD_Org_ID())); + } // setPayment + + + /** + * Get Currency From (Invoice/Payment) + * @return Returns the Currency From + */ + public int getC_CurrencyFrom_ID () + { + if (m_C_CurrencyFrom_ID == 0) + { + if (getC_Invoice_ID() != 0) + m_C_CurrencyFrom_ID = getInvoice().getC_Currency_ID(); + else if (getC_Payment_ID() != 0) + m_C_CurrencyFrom_ID = getPayment().getC_Currency_ID(); + } + return m_C_CurrencyFrom_ID; + } // getC_CurrencyFrom_ID + + /** + * Get Currency To from Parent + * @return Returns the Currency To + */ + public int getC_CurrencyTo_ID () + { + if (m_C_CurrencyTo_ID == 0) + m_C_CurrencyTo_ID = getParent().getC_Currency_ID(); + return m_C_CurrencyTo_ID; + } // getC_CurrencyTo_ID + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Set Amt + if (getC_Invoice_ID() == 0 && getC_Payment_ID() == 0) + { + setAmt(Env.ZERO); + setOpenAmt(Env.ZERO); + } + // Converted Amt + if (Env.ZERO.compareTo(getOpenAmt()) == 0) + setConvertedAmt (Env.ZERO); + else if (Env.ZERO.compareTo(getConvertedAmt()) == 0) + setConvertedAmt (MConversionRate.convert(getCtx(), getOpenAmt(), + getC_CurrencyFrom_ID(), getC_CurrencyTo_ID(), getAD_Client_ID(), getAD_Org_ID())); + // Total + setTotalAmt(getConvertedAmt().add(getFeeAmt()).add(getInterestAmt())); + // + return true; + } // beforeSave + + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + updateEntry(); + return success; + } // afterSave + + /** + * After Delete + * @param success success + * @return success + */ + protected boolean afterDelete (boolean success) + { + updateEntry(); + return success; + } // afterDelete + + /** + * Update Entry. + * Calculate/update Amt/Qty + */ + private void updateEntry() + { + String sql = "UPDATE C_DunningRunEntry e " + + "SET (Amt,Qty)=(SELECT SUM(Amt),COUNT(*) FROM C_DunningRunLine l " + + "WHERE e.C_DunningRunEntry_ID=l.C_DunningRunEntry_ID) " + + "WHERE C_DunningRunEntry_ID=" + getC_DunningRunEntry_ID(); + DB.executeUpdate(sql, get_TrxName()); + } // updateEntry + +} // MDunningRunLine diff --git a/base/src/org/compiere/model/MEntityType.java b/base/src/org/compiere/model/MEntityType.java new file mode 100644 index 0000000000..f4f6d27c3d --- /dev/null +++ b/base/src/org/compiere/model/MEntityType.java @@ -0,0 +1,269 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Enitity Type Model + * + * @author Jorg Janke + * @version $Id: MEntityType.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MEntityType extends X_AD_EntityType +{ + /** + * Get Entity Types + * @param ctx context + * @return entity type array + */ + static public MEntityType[] getEntityTypes(Properties ctx) + { + if (s_entityTypes != null) + return s_entityTypes; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM AD_EntityType WHERE IsActive='Y' ORDER BY AD_EntityType_ID"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MEntityType (ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + s_entityTypes = new MEntityType[list.size()]; + list.toArray(s_entityTypes); + s_log.finer("# " + s_entityTypes.length); + return s_entityTypes; + } // getEntityTypes + + /** + * Get Entity Type as String array + * @param ctx context + * @return entity type array + */ + static public String[] getEntityTypeStrings(Properties ctx) + { + MEntityType[] entityTypes = getEntityTypes(ctx); + ArrayList list = new ArrayList(); // list capabilities + String[] retValue = new String[entityTypes.length]; + for (int i = 0; i < entityTypes.length; i++) + { + String s = entityTypes[i].getEntityType().trim(); + list.add(s); + retValue[i] = s; + } + s_log.finer(list.toString()); + return retValue; + } // getEntityTypeStrings + + /** + * Get Entity Type Classpath array + * @param ctx context + * @return classpath array + */ + static public String[] getClasspaths(Properties ctx) + { + MEntityType[] entityTypes = getEntityTypes(ctx); + ArrayList list = new ArrayList(); + for (int i = 0; i < entityTypes.length; i++) + { + String classpath = entityTypes[i].getClasspath(); + if (classpath == null || classpath.length() == 0) + continue; + StringTokenizer st = new StringTokenizer(classpath, ";, \t\n\r\f"); + while (st.hasMoreTokens()) + { + String token = st.nextToken(); + if (token.length() > 0) + { + if (!list.contains(token)) + list.add(token); + } + } + } + String[] retValue = new String[list.size()]; + list.toArray(retValue); + s_log.finer(list.toString()); + return retValue; + } // getClathpaths + + /** + * Get Entity Type Model Package array + * @param ctx context + * @return entity type array + */ + static public String[] getModelPackages(Properties ctx) + { + MEntityType[] entityTypes = getEntityTypes(ctx); + ArrayList list = new ArrayList(); + list.add("adempiere.model"); // default + for (int i = 0; i < entityTypes.length; i++) + { + String modelPackage = entityTypes[i].getModelPackage(); + if (modelPackage == null || modelPackage.length() == 0) + continue; + StringTokenizer st = new StringTokenizer(modelPackage, ";, \t\n\r\f"); + while (st.hasMoreTokens()) + { + String token = st.nextToken(); + if (token.length() > 0) + { + if (!list.contains(token)) + list.add(token); + } + } + } + String[] retValue = new String[list.size()]; + list.toArray(retValue); + s_log.finer(list.toString()); + return retValue; + } // getModelPackages + + /** Cached EntityTypes */ + private static MEntityType[] s_entityTypes = null; + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MEntityType.class); + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param AD_EntityType_ID id + * @param trxName transaction + */ + public MEntityType (Properties ctx, int AD_EntityType_ID, String trxName) + { + super (ctx, AD_EntityType_ID, trxName); + } // MEntityType + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MEntityType (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MEntityType + + /** 10=D, 20=C, 100=U, 110=CUST, 200=A, 210=EXT, 220=XX */ + private static final int s_maxAD_EntityType_ID = 221; + + /** + * Is System Maintained + * @return true if D/C/U/CUST/A/EXT/XX + */ + public boolean isSystemMaintained() + { + int id = getAD_EntityType_ID(); + return id < s_maxAD_EntityType_ID; + } // isSystemMaintained + + /** + * Before Save + * @param newRecord new + * @return true if it can be saved + */ + protected boolean beforeSave (boolean newRecord) + { + if (!newRecord) + { + int id = getAD_EntityType_ID(); + boolean systemMaintained = (id == 10 || id == 20); // C/D + if (systemMaintained) + { + log.saveError("Error", "You cannot modify a System maintained entity"); + return false; + } + systemMaintained = is_ValueChanged("EntityType"); + if (systemMaintained) + { + log.saveError("Error", "You cannot modify EntityType"); + return false; + } + systemMaintained = id < s_maxAD_EntityType_ID + && (is_ValueChanged("Name") || is_ValueChanged("Description") + || is_ValueChanged("Help") || is_ValueChanged("IsActive")); + if (systemMaintained) + { + log.saveError("Error", "You cannot modify Name,Description,Help"); + return false; + } + } + else // new + { + setEntityType(getEntityType().toUpperCase()); // upper case + if (getEntityType().trim().length() < 4) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "EntityType") + + " - 4 Characters"); + return false; + } + boolean ok = true; + char[] cc = getEntityType().toCharArray(); + for (int i = 0; i < cc.length; i++) + { + char c = cc[i]; + if (Character.isDigit(c) || (c >= 'A' && c <= 'Z')) + continue; + // + log.saveError("FillMandatory", Msg.getElement(getCtx(), "EntityType") + + " - Must be ASCII Letter or Digit"); + return false; + } + } // new + s_entityTypes = null; // reset + return true; + } // beforeSave + + /** + * Before Delete + * @return true if it can be deleted + */ + protected boolean beforeDelete () + { + if (isSystemMaintained()) // all pre-defined + { + log.saveError("Error", "You cannot delete a System maintained entity"); + return false; + } + s_entityTypes = null; // reset + return true; + } // beforeDelete + +} // MEntityType diff --git a/base/src/org/compiere/model/MExpenseType.java b/base/src/org/compiere/model/MExpenseType.java new file mode 100644 index 0000000000..9affca48ab --- /dev/null +++ b/base/src/org/compiere/model/MExpenseType.java @@ -0,0 +1,110 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Expense Type Model + * + * @author Jorg Janke + * @version $Id: MExpenseType.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MExpenseType extends X_S_ExpenseType +{ + + /** + * Default Constructor + * @param ctx context + * @param S_ExpenseType_ID id + * @param trxName transaction + */ + public MExpenseType (Properties ctx, int S_ExpenseType_ID, String trxName) + { + super (ctx, S_ExpenseType_ID, trxName); + } // MExpenseType + + /** + * MExpenseType + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MExpenseType (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MExpenseType + + /** Cached Product */ + private MProduct m_product = null; + + /** + * Get Product + * @return product + */ + public MProduct getProduct() + { + if (m_product == null) + { + MProduct[] products = MProduct.get(getCtx(), "S_ExpenseType_ID=" + getS_ExpenseType_ID(), get_TrxName()); + if (products.length > 0) + m_product = products[0]; + } + return m_product; + } // getProduct + + + /** + * beforeSave + * @see org.compiere.model.PO#beforeSave(boolean) + * @param newRecord + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (newRecord) + { + if (getValue() == null || getValue().length() == 0) + setValue(getName()); + m_product = new MProduct(this); + return m_product.save(get_TrxName()); + } + return true; + } // beforeSave + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + + MProduct prod = getProduct(); + if (prod.setExpenseType(this)) + prod.save(get_TrxName()); + + return success; + } // afterSave + + +} // MExpenseType diff --git a/base/src/org/compiere/model/MFactAcct.java b/base/src/org/compiere/model/MFactAcct.java new file mode 100644 index 0000000000..0805224d26 --- /dev/null +++ b/base/src/org/compiere/model/MFactAcct.java @@ -0,0 +1,110 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Accounting Fact Model + * + * @author Jorg Janke + * @version $Id: MFactAcct.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MFactAcct extends X_Fact_Acct +{ + /** + * Delete Accounting + * @param AD_Table_ID table + * @param Record_ID record + * @param trxName transaction + * @return number of rows or -1 for error + */ + public static int delete (int AD_Table_ID, int Record_ID, String trxName) + { + StringBuffer sb = new StringBuffer(); + sb.append("DELETE Fact_Acct WHERE AD_Table_ID=").append(AD_Table_ID) + .append(" AND Record_ID=").append(Record_ID); + int no = DB.executeUpdate(sb.toString(), trxName); + if (no == -1) + s_log.log(Level.SEVERE, "failed: AD_Table_ID=" + AD_Table_ID + ", Record_ID" + Record_ID); + else + s_log.fine("delete - AD_Table_ID=" + AD_Table_ID + + ", Record_ID=" + Record_ID + " - #" + no); + return no; + } // delete + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MFactAcct.class); + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param Fact_Acct_ID id + * @param trxName transaction + */ + public MFactAcct (Properties ctx, int Fact_Acct_ID, String trxName) + { + super (ctx, Fact_Acct_ID, trxName); + } // MFactAcct + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MFactAcct (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MFactAcct + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MFactAcct["); + sb.append(get_ID()).append("-Acct=").append(getAccount_ID()) + .append(",Dr=").append(getAmtSourceDr()).append("|").append(getAmtAcctDr()) + .append(",Cr=").append(getAmtSourceCr()).append("|").append(getAmtAcctCr()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Derive MAccount from record + * @return Valid Account Combination + */ + public MAccount getMAccount() + { + MAccount acct = MAccount.get (getCtx(), getAD_Client_ID(), getAD_Org_ID(), + getC_AcctSchema_ID(), getAccount_ID(), getC_SubAcct_ID(), + getM_Product_ID(), getC_BPartner_ID(), getAD_OrgTrx_ID(), + getC_LocFrom_ID(), getC_LocTo_ID(), getC_SalesRegion_ID(), + getC_Project_ID(), getC_Campaign_ID(), getC_Activity_ID(), + getUser1_ID(), getUser2_ID(), getUserElement1_ID(), getUserElement2_ID()); + if (acct != null && acct.get_ID() == 0) + acct.save(); + return acct; + } // getMAccount + +} // MFactAcct diff --git a/base/src/org/compiere/model/MForm.java b/base/src/org/compiere/model/MForm.java new file mode 100644 index 0000000000..60b67aa5ad --- /dev/null +++ b/base/src/org/compiere/model/MForm.java @@ -0,0 +1,72 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + + +/** + * Form Model + * + * @author Jorg Janke + * @version $Id: MForm.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MForm extends X_AD_Form +{ + + /** + * Default Constructor + * @param ctx context + * @param AD_Form_ID id + * @param trxName transaction + */ + public MForm (Properties ctx, int AD_Form_ID, String trxName) + { + super (ctx, AD_Form_ID, trxName); + } // MForm + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MForm (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MForm + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (newRecord) + { + int AD_Role_ID = Env.getAD_Role_ID(getCtx()); + MFormAccess pa = new MFormAccess(this, AD_Role_ID); + pa.save(); + } + return success; + } // afterSave + +} // MForm diff --git a/base/src/org/compiere/model/MFormAccess.java b/base/src/org/compiere/model/MFormAccess.java new file mode 100644 index 0000000000..8d755d416f --- /dev/null +++ b/base/src/org/compiere/model/MFormAccess.java @@ -0,0 +1,75 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Form Access Model + * + * @author Jorg Janke + * @version $Id: MFormAccess.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MFormAccess extends X_AD_Form_Access +{ + /** + * Standard Constructor + * @param ctx context + * @param ignored id=0 + * @param trxName trx + */ + public MFormAccess (Properties ctx, int ignored, String trxName) + { + super(ctx, 0, trxName); + if (ignored != 0) + throw new IllegalArgumentException("Multi-Key"); + else + { + // setAD_Form_ID (0); + // setAD_Role_ID (0); + setIsReadWrite (true); + } + } // MFormAccess + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MFormAccess (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MFormAccess + + /** + * Parent Constructor + * @param parent parent + * @param AD_Role_ID role id + */ + public MFormAccess (MForm parent, int AD_Role_ID) + { + super (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setAD_Form_ID(parent.getAD_Form_ID()); + setAD_Role_ID (AD_Role_ID); + } // MFormAccess + + +} // MFormAccess diff --git a/base/src/org/compiere/model/MGLCategory.java b/base/src/org/compiere/model/MGLCategory.java new file mode 100644 index 0000000000..52c2e9c3ba --- /dev/null +++ b/base/src/org/compiere/model/MGLCategory.java @@ -0,0 +1,157 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * GL Category + * + * @author Jorg Janke + * @version $Id: MGLCategory.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MGLCategory extends X_GL_Category +{ + /** + * Get MGLCategory from Cache + * @param ctx context + * @param GL_Category_ID id + * @return MGLCategory + */ + public static MGLCategory get (Properties ctx, int GL_Category_ID) + { + Integer key = new Integer (GL_Category_ID); + MGLCategory retValue = (MGLCategory)s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MGLCategory (ctx, GL_Category_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** + * Get Default Category + * @param ctx context + * @param CategoryType optional CategoryType (ignored, if not exists) + * @return GL Category or null + */ + public static MGLCategory getDefault (Properties ctx, String CategoryType) + { + MGLCategory retValue = null; + String sql = "SELECT * FROM GL_Category " + + "WHERE AD_Client_ID=? AND IsDefault='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, Env.getAD_Client_ID(ctx)); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MGLCategory temp = new MGLCategory (ctx, rs, null); + if (CategoryType != null && CategoryType.equals(temp.getCategoryType())) + { + retValue = temp; + break; + } + if (retValue == null) + retValue = temp; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return retValue; + } // getDefault + + /** + * Get Default System Category + * @param ctx context + * @return GL Category + */ + public static MGLCategory getDefaultSystem (Properties ctx) + { + MGLCategory retValue = getDefault(ctx, CATEGORYTYPE_SystemGenerated); + if (retValue == null + || !retValue.getCategoryType().equals(CATEGORYTYPE_SystemGenerated)) + { + retValue = new MGLCategory(ctx, 0, null); + retValue.setName("Default System"); + retValue.setCategoryType(CATEGORYTYPE_SystemGenerated); + retValue.setIsDefault(true); + if (!retValue.save()) + throw new IllegalStateException("Could not save default system GL Category"); + } + return retValue; + } // getDefaultSystem + + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MGLCategory.class); + /** Cache */ + private static CCache s_cache + = new CCache ("GL_Category", 5); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param GL_Category_ID id + * @param trxName transaction + */ + public MGLCategory (Properties ctx, int GL_Category_ID, String trxName) + { + super (ctx, GL_Category_ID, trxName); + if (GL_Category_ID == 0) + { + // setName (null); + setCategoryType (CATEGORYTYPE_Manual); + setIsDefault (false); + } + } // MGLCategory + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MGLCategory (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MGLCategory + +} // MGLCategory diff --git a/base/src/org/compiere/model/MGoal.java b/base/src/org/compiere/model/MGoal.java new file mode 100644 index 0000000000..da401a0dc2 --- /dev/null +++ b/base/src/org/compiere/model/MGoal.java @@ -0,0 +1,615 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.awt.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Performance Goal + * + * @author Jorg Janke + * @version $Id: MGoal.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MGoal extends X_PA_Goal +{ + /** + * Get User Goals + * @param ctx context + * @param AD_User_ID user + * @return array of goals + */ + public static MGoal[] getUserGoals(Properties ctx, int AD_User_ID) + { + if (AD_User_ID < 0) + return getTestGoals(ctx); + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM PA_Goal g " + + "WHERE IsActive='Y'" + + " AND AD_Client_ID=?" // #1 + + " AND ((AD_User_ID IS NULL AND AD_Role_ID IS NULL)" + + " OR AD_User_ID=?" // #2 + + " OR EXISTS (SELECT * FROM AD_User_Roles ur " + + "WHERE g.AD_User_ID=ur.AD_User_ID AND g.AD_Role_ID=ur.AD_Role_ID AND ur.IsActive='Y')) " + + "ORDER BY SeqNo"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, Env.getAD_Client_ID(ctx)); + pstmt.setInt (2, AD_User_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MGoal goal = new MGoal (ctx, rs, null); + goal.updateGoal(false); + list.add (goal); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MGoal[] retValue = new MGoal[list.size ()]; + list.toArray (retValue); + return retValue; + } // getUserGoals + + /** + * Get Accessible Goals + * @param ctx context + * @return array of goals + */ + public static MGoal[] getGoals(Properties ctx) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM PA_Goal WHERE IsActive='Y' " + + "ORDER BY SeqNo"; + sql = MRole.getDefault(ctx, false).addAccessSQL(sql, "PA_Goal", + false, true); // RW to restrict Access + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MGoal goal = new MGoal (ctx, rs, null); + goal.updateGoal(false); + list.add (goal); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MGoal[] retValue = new MGoal[list.size ()]; + list.toArray (retValue); + return retValue; + } // getGoals + + + /** + * Create Test Goals + * @param ctx context + * @return array of goals + */ + public static MGoal[] getTestGoals(Properties ctx) + { + MGoal[] retValue = new MGoal[4]; + retValue[0] = new MGoal (ctx, "Test 1", "Description 1", new BigDecimal (1000), null); + retValue[0].setMeasureActual(new BigDecimal (200)); + retValue[1] = new MGoal (ctx, "Test 2", "Description 2", new BigDecimal (1000), null); + retValue[1].setMeasureActual(new BigDecimal (900)); + retValue[2] = new MGoal (ctx, "Test 3", "Description 3", new BigDecimal (1000), null); + retValue[2].setMeasureActual(new BigDecimal (1200)); + retValue[3] = new MGoal (ctx, "Test 4", "Description 4", new BigDecimal (1000), null); + retValue[3].setMeasureActual(new BigDecimal (3200)); + return retValue; + } // getTestGoals + + /** + * Get Goals with Measure + * @param ctx context + * @param PA_Measure_ID measure + * @return goals + */ + public static MGoal[] getMeasureGoals (Properties ctx, int PA_Measure_ID) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM PA_Goal WHERE IsActive='Y' AND PA_Measure_ID=? " + + "ORDER BY SeqNo"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, PA_Measure_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MGoal (ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MGoal[] retValue = new MGoal[list.size ()]; + list.toArray (retValue); + return retValue; + } // getMeasureGoals + + /** + * Get Multiplier from Scope to Display + * @param goal goal + * @return null if error or multiplier + */ + public static BigDecimal getMultiplier (MGoal goal) + { + String MeasureScope = goal.getMeasureScope(); + String MeasureDisplay = goal.getMeasureDisplay(); + if (MeasureDisplay == null + || MeasureScope.equals(MeasureDisplay)) + return Env.ONE; // 1:1 + + if (MeasureScope.equals(MEASURESCOPE_Total) + || MeasureDisplay.equals(MEASUREDISPLAY_Total)) + return null; // Error + + BigDecimal Multiplier = null; + if (MeasureScope.equals(MEASURESCOPE_Year)) + { + if (MeasureDisplay.equals(MEASUREDISPLAY_Quarter)) + Multiplier = new BigDecimal(1.0/4.0); + else if (MeasureDisplay.equals(MEASUREDISPLAY_Month)) + Multiplier = new BigDecimal(1.0/12.0); + else if (MeasureDisplay.equals(MEASUREDISPLAY_Week)) + Multiplier = new BigDecimal(1.0/52.0); + else if (MeasureDisplay.equals(MEASUREDISPLAY_Day)) + Multiplier = new BigDecimal(1.0/364.0); + } + else if (MeasureScope.equals(MEASURESCOPE_Quarter)) + { + if (MeasureDisplay.equals(MEASUREDISPLAY_Year)) + Multiplier = new BigDecimal(4.0); + else if (MeasureDisplay.equals(MEASUREDISPLAY_Month)) + Multiplier = new BigDecimal(1.0/3.0); + else if (MeasureDisplay.equals(MEASUREDISPLAY_Week)) + Multiplier = new BigDecimal(1.0/13.0); + else if (MeasureDisplay.equals(MEASUREDISPLAY_Day)) + Multiplier = new BigDecimal(1.0/91.0); + } + else if (MeasureScope.equals(MEASURESCOPE_Month)) + { + if (MeasureDisplay.equals(MEASUREDISPLAY_Year)) + Multiplier = new BigDecimal(12.0); + else if (MeasureDisplay.equals(MEASUREDISPLAY_Quarter)) + Multiplier = new BigDecimal(3.0); + else if (MeasureDisplay.equals(MEASUREDISPLAY_Week)) + Multiplier = new BigDecimal(1.0/4.0); + else if (MeasureDisplay.equals(MEASUREDISPLAY_Day)) + Multiplier = new BigDecimal(1.0/30.0); + } + else if (MeasureScope.equals(MEASURESCOPE_Week)) + { + if (MeasureDisplay.equals(MEASUREDISPLAY_Year)) + Multiplier = new BigDecimal(52.0); + else if (MeasureDisplay.equals(MEASUREDISPLAY_Quarter)) + Multiplier = new BigDecimal(13.0); + else if (MeasureDisplay.equals(MEASUREDISPLAY_Month)) + Multiplier = new BigDecimal(4.0); + else if (MeasureDisplay.equals(MEASUREDISPLAY_Day)) + Multiplier = new BigDecimal(1.0/7.0); + } + else if (MeasureScope.equals(MEASURESCOPE_Day)) + { + if (MeasureDisplay.equals(MEASUREDISPLAY_Year)) + Multiplier = new BigDecimal(364.0); + else if (MeasureDisplay.equals(MEASUREDISPLAY_Quarter)) + Multiplier = new BigDecimal(91.0); + else if (MeasureDisplay.equals(MEASUREDISPLAY_Month)) + Multiplier = new BigDecimal(30.0); + else if (MeasureDisplay.equals(MEASUREDISPLAY_Week)) + Multiplier = new BigDecimal(7.0); + } + return Multiplier; + } // getMultiplier + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MGoal.class); + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param PA_Goal_ID id + * @param trxName trx + */ + public MGoal (Properties ctx, int PA_Goal_ID, String trxName) + { + super (ctx, PA_Goal_ID, trxName); + if (PA_Goal_ID == 0) + { + // setName (null); + // setAD_User_ID (0); + // setPA_ColorSchema_ID (0); + setSeqNo (0); + setIsSummary (false); + setMeasureScope (MEASUREDISPLAY_Year); + setGoalPerformance (Env.ZERO); + setRelativeWeight (Env.ONE); + setMeasureTarget (Env.ZERO); + setMeasureActual (Env.ZERO); + } + } // MGoal + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MGoal (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MGoal + + /** + * Base Constructor + * @param ctx context + * @param Name Name + * @param Description Decsription + * @param MeasureTarget target + * @param trxName trx + */ + public MGoal (Properties ctx, String Name, String Description, + BigDecimal MeasureTarget, String trxName) + { + super (ctx, 0, trxName); + setName(Name); + setDescription(Description); + setMeasureTarget(MeasureTarget); + } // MGoal + + + /** Restrictions */ + private MGoalRestriction[] m_restrictions = null; + /** Performance Color */ + private Color m_color = null; + + /** + * Get Restriction Lines + * @param reload reload data + * @return array of lines + */ + public MGoalRestriction[] getRestrictions (boolean reload) + { + if (m_restrictions != null && !reload) + return m_restrictions; + ArrayList list = new ArrayList(); + // + String sql = "SELECT * FROM PA_GoalRestriction " + + "WHERE PA_Goal_ID=? AND IsActive='Y' " + + "ORDER BY Org_ID, C_BPartner_ID, M_Product_ID"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getPA_Goal_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MGoalRestriction (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + m_restrictions = new MGoalRestriction[list.size ()]; + list.toArray (m_restrictions); + return m_restrictions; + } // getRestrictions + + /** + * Get Measure + * @return measure or null + */ + public MMeasure getMeasure() + { + if (getPA_Measure_ID() != 0) + return MMeasure.get(getCtx(), getPA_Measure_ID()); + return null; + } // getMeasure + + + /************************************************************************** + * Update/save Goals for the same measure + * @param force force to update goal (default once per day) + * @return true if updated + */ + public boolean updateGoal(boolean force) + { + log.config("Force=" + force); + MMeasure measure = MMeasure.get(getCtx(), getPA_Measure_ID()); + if (force + || getDateLastRun() == null + || !TimeUtil.isSameHour(getDateLastRun(), null)) + { + if (measure.updateGoals()) // saves + { + load(get_ID(), get_TrxName()); + return true; + } + } + return false; + } // updateGoal + + /** + * Set Measure Actual + * @param MeasureActual actual + */ + public void setMeasureActual (BigDecimal MeasureActual) + { + if (MeasureActual == null) + return; + super.setMeasureActual (MeasureActual); + setDateLastRun(new Timestamp(System.currentTimeMillis())); + setGoalPerformance(); + } // setMeasureActual + + /** + * Calculate Performance Goal as multiplier + */ + public void setGoalPerformance () + { + BigDecimal MeasureTarget = getMeasureTarget(); + BigDecimal MeasureActual = getMeasureActual(); + BigDecimal GoalPerformance = Env.ZERO; + if (MeasureTarget.signum() != 0) + GoalPerformance = MeasureActual.divide(MeasureTarget, 6, BigDecimal.ROUND_HALF_UP); + super.setGoalPerformance (GoalPerformance); + m_color = null; + } // setGoalPerformance + + /** + * Get Goal Performance as Double + * @return performance as multipier + */ + public double getGoalPerformanceDouble() + { + BigDecimal bd = getGoalPerformance(); + return bd.doubleValue(); + } // getGoalPerformanceDouble + + /** + * Get Goal Performance in Percent + * @return performance in percent + */ + public int getPercent() + { + BigDecimal bd = getGoalPerformance().multiply(Env.ONEHUNDRED); + return bd.intValue(); + } // getPercent + + /** + * Get Color + * @return color - white if no target + */ + public Color getColor() + { + if (m_color == null) + { + if (getMeasureTarget().signum() == 0) + m_color = Color.white; + else + m_color = MColorSchema.getColor(getCtx(), getPA_ColorSchema_ID(), getPercent()); + } + return m_color; + } // getColor + + /** + * Get Measure Display + * @return Measure Display + */ + public String getMeasureDisplay () + { + String s = super.getMeasureDisplay (); + if (s == null) + { + if (MEASURESCOPE_Week.equals(getMeasureScope())) + s = MEASUREDISPLAY_Week; + else if (MEASURESCOPE_Day.equals(getMeasureScope())) + s = MEASUREDISPLAY_Day; + else + s = MEASUREDISPLAY_Month; + } + return s; + } // getMeasureDisplay + + /** + * Get Measure Display Text + * @return Measure Display Text + */ + public String getXAxisText () + { + MMeasure measure = getMeasure(); + if (measure != null + && MMeasure.MEASUREDATATYPE_StatusQtyAmount.equals(measure.getMeasureDataType())) + { + if (MMeasure.MEASURETYPE_Request.equals(measure.getMeasureType())) + return Msg.getElement(getCtx(), "R_Status_ID"); + if (MMeasure.MEASURETYPE_Project.equals(measure.getMeasureType())) + return Msg.getElement(getCtx(), "C_Phase_ID"); + } + String value = getMeasureDisplay(); + String display = MRefList.getListName(getCtx(), MEASUREDISPLAY_AD_Reference_ID, value); + return display==null ? value : display; + } // getMeasureDisplayText + + /** + * Goal has Target + * @return true if target + */ + public boolean isTarget() + { + return getMeasureTarget().signum() != 0; + } // isTarget + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MGoal["); + sb.append (get_ID ()) + .append ("-").append (getName()) + .append(",").append(getGoalPerformance()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // if (getMultiplier(this) == null) // error + // setMeasureDisplay(getMeasureScope()); + + // Measure required if nor Summary + if (!isSummary() && getPA_Measure_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "PA_Measure_ID")); + return false; + } + if (isSummary() && getPA_Measure_ID() != 0) + setPA_Measure_ID(0); + + // User/Role Check + if ((newRecord || is_ValueChanged("AD_User_ID") || is_ValueChanged("AD_Role_ID")) + && getAD_User_ID() != 0) + { + MUser user = MUser.get(getCtx(), getAD_User_ID()); + MRole[] roles = user.getRoles(getAD_Org_ID()); + if (roles.length == 0) // No Role + setAD_Role_ID(0); + else if (roles.length == 1) // One + setAD_Role_ID(roles[0].getAD_Role_ID()); + else + { + int AD_Role_ID = getAD_Role_ID(); + if (AD_Role_ID != 0) // validate + { + boolean found = false; + for (int i = 0; i < roles.length; i++) + { + if (AD_Role_ID == roles[i].getAD_Role_ID()) + { + found = true; + break; + } + } + if (!found) + AD_Role_ID = 0; + } + if (AD_Role_ID == 0) // set to first one + setAD_Role_ID(roles[0].getAD_Role_ID()); + } // multiple roles + } // user check + + return true; + } // beforeSave + + /** + * After Save + * @param newRecord new + * @param success success + * @return true + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + + // Update Goal if Target / Scope Changed + if (newRecord + || is_ValueChanged("MeasureTarget") + || is_ValueChanged("MeasureScope")) + updateGoal(true); + + return success; + } + + +} // MGoal diff --git a/base/src/org/compiere/model/MGoalRestriction.java b/base/src/org/compiere/model/MGoalRestriction.java new file mode 100644 index 0000000000..7644e58634 --- /dev/null +++ b/base/src/org/compiere/model/MGoalRestriction.java @@ -0,0 +1,64 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Performance Goal Restriction + * + * @author Jorg Janke + * @version $Id: MGoalRestriction.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MGoalRestriction extends X_PA_GoalRestriction +{ + /** + * Standard Constructor + * @param ctx context + * @param PA_GoalRestriction_ID id + * @param trxName trx + */ + public MGoalRestriction (Properties ctx, int PA_GoalRestriction_ID, + String trxName) + { + super (ctx, PA_GoalRestriction_ID, trxName); + } // MGoalRestriction + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MGoalRestriction (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MGoalRestriction + + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MGoalRestriction["); + sb.append (get_ID()).append ("-").append (getName()).append ("]"); + return sb.toString (); + } // toString +} // MGoalRestriction diff --git a/base/src/org/compiere/model/MGroup.java b/base/src/org/compiere/model/MGroup.java new file mode 100644 index 0000000000..7fe06772a0 --- /dev/null +++ b/base/src/org/compiere/model/MGroup.java @@ -0,0 +1,75 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import org.compiere.util.*; + +/** + * Request Group Model + * @author Jorg Janke + * @version $Id: MGroup.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MGroup extends X_R_Group +{ + /** + * Get MGroup from Cache + * @param ctx context + * @param R_Group_ID id + * @return MGroup + */ + public static MGroup get (Properties ctx, int R_Group_ID) + { + Integer key = new Integer (R_Group_ID); + MGroup retValue = (MGroup) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MGroup (ctx, R_Group_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("R_Group", 20); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param R_Group_ID group + * @param trxName trx + */ + public MGroup (Properties ctx, int R_Group_ID, String trxName) + { + super (ctx, R_Group_ID, trxName); + } // MGroup + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MGroup (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MGroup + +} // MGroup diff --git a/base/src/org/compiere/model/MHierarchy.java b/base/src/org/compiere/model/MHierarchy.java new file mode 100644 index 0000000000..ad2e7960bb --- /dev/null +++ b/base/src/org/compiere/model/MHierarchy.java @@ -0,0 +1,104 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import org.compiere.util.*; + +/** + * Reporting Hierarchy Model + * + * @author Jorg Janke + * @version $Id: MHierarchy.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MHierarchy extends X_PA_Hierarchy +{ + /** + * Get MHierarchy from Cache + * @param ctx context + * @param PA_Hierarchy_ID id + * @return MHierarchy + */ + public static MHierarchy get (Properties ctx, int PA_Hierarchy_ID) + { + Integer key = new Integer (PA_Hierarchy_ID); + MHierarchy retValue = (MHierarchy)s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MHierarchy (ctx, PA_Hierarchy_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache + = new CCache ("PA_Hierarchy_ID", 20); + + /** + * Default Constructor + * @param ctx context + * @param PA_Hierarchy_ID id + * @param trxName trx + */ + public MHierarchy (Properties ctx, int PA_Hierarchy_ID, String trxName) + { + super (ctx, PA_Hierarchy_ID, trxName); + } // MHierarchy + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MHierarchy (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MHierarchy + + /** + * Get AD_Tree_ID based on tree type + * @param TreeType Tree Type + * @return id or 0 + */ + public int getAD_Tree_ID (String TreeType) + { + if (MTree.TREETYPE_Activity.equals(TreeType)) + return getAD_Tree_Activity_ID(); + if (MTree.TREETYPE_BPartner.equals(TreeType)) + return getAD_Tree_BPartner_ID(); + if (MTree.TREETYPE_Campaign.equals(TreeType)) + return getAD_Tree_Campaign_ID(); + if (MTree.TREETYPE_ElementValue.equals(TreeType)) + return getAD_Tree_Account_ID(); + if (MTree.TREETYPE_Organization.equals(TreeType)) + return getAD_Tree_Org_ID(); + if (MTree.TREETYPE_Product.equals(TreeType)) + return getAD_Tree_Product_ID(); + if (MTree.TREETYPE_Project.equals(TreeType)) + return getAD_Tree_Project_ID(); + if (MTree.TREETYPE_SalesRegion.equals(TreeType)) + return getAD_Tree_SalesRegion_ID(); + // + log.warning("Not supported: " + TreeType); + return 0; + } // getAD_Tree_ID + +} // MHierarchy diff --git a/base/src/org/compiere/model/MImage.java b/base/src/org/compiere/model/MImage.java new file mode 100644 index 0000000000..a3507ca4d1 --- /dev/null +++ b/base/src/org/compiere/model/MImage.java @@ -0,0 +1,291 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.awt.*; +import java.io.*; +import java.net.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import javax.swing.*; +import org.compiere.util.*; + +/** + * Image Model + * (DisplayType = 32) + * + * @author Jorg Janke + * @version $Id: MImage.java,v 1.5 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MImage extends X_AD_Image +{ + /** + * Get MImage from Cache + * @param ctx context + * @param AD_Image_ID id + * @return MImage + */ + public static MImage get (Properties ctx, int AD_Image_ID) + { + if (AD_Image_ID == 0) + return new MImage (ctx, AD_Image_ID, null); + // + Integer key = new Integer (AD_Image_ID); + MImage retValue = (MImage) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MImage (ctx, AD_Image_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("AD_Image", 20); + + /** + * Constructor + * @param ctx context + * @param AD_Image_ID image + * @param trxName transaction + */ + public MImage(Properties ctx, int AD_Image_ID, String trxName) + { + super (ctx, AD_Image_ID, trxName); + if (AD_Image_ID < 1) + setName("-"); + } // MImage + + /** + * Load Constructor + * @param ctx + * @param rs + * @param trxName transaction + */ + public MImage (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MImage + + + /** The Image */ + private Image m_image = null; + /** The Icon */ + private Icon m_icon = null; + /** The Image File */ + private File m_file = null; + + /** + * Get Image + * @return image or null + */ + public Image getImage () + { + if (m_image != null) + return m_image; + // Via byte array + byte[] data = getBinaryData(); + if (data != null && data.length > 0) + { + try + { + Toolkit tk = Toolkit.getDefaultToolkit(); + m_image = tk.createImage(data); + return m_image; + } + catch (Exception e) + { + log.log(Level.WARNING, "(byteArray)", e); + return null; + } + } + // Via URL + URL url = getURL(); + if (url == null) + return null; + try + { + Toolkit tk = Toolkit.getDefaultToolkit(); + m_image = tk.getImage(url); + return m_image; + } + catch (Exception e) + { + log.log(Level.WARNING, "(URL)", e); + } + return null; + } // getImage + + /** + * Get Icon + * @return icon or null + */ + public Icon getIcon () + { + if (m_icon != null) + return m_icon; + // Via byte array + byte[] data = getBinaryData(); + if (data != null && data.length > 0) + { + try + { + m_icon = new ImageIcon(data, getName()); + return m_icon; + } + catch (Exception e) + { + log.log(Level.WARNING, "(byteArray)", e); + return null; + } + } + // Via URL + URL url = getURL(); + if (url == null) + return null; + try + { + m_icon = new ImageIcon(url, getName()); + return m_icon; + } + catch (Exception e) + { + log.log(Level.WARNING, "(URL)", e); + } + return null; + } // getIcon + + /** + * Get URL + * @return url or null + */ + private URL getURL() + { + String str = getImageURL(); + if (str == null || str.length() == 0) + return null; + + URL url = null; + try + { + // Try URL directly + if (str.indexOf("://") != -1) + url = new URL(str); + else // Try Resource + url = getClass().getResource(str); + // + if (url == null) + log.warning("Not found: " + str); + } + catch (Exception e) + { + log.warning("Not found: " + str + " - " + e.getMessage()); + } + return url; + } // getURL + + /** + * Set Image URL + * @param ImageURL url + */ + public void setImageURL (String ImageURL) + { + m_image = null; + m_icon = null; + super.setImageURL (ImageURL); + } // setImageURL + + /** + * Set Binary Data + * @param BinaryData data + */ + public void setBinaryData (byte[] BinaryData) + { + m_image = null; + m_icon = null; + super.setBinaryData (BinaryData); + } // setBinaryData + + /** + * Get Data + * @return data + */ + public byte[] getData() + { + byte[] data = super.getBinaryData (); + if (data != null) + return data; + // From URL + String str = getImageURL(); + if (str == null || str.length() == 0) + { + log.config("No Image URL"); + return null; + } + // Get from URL + URL url = getURL(); + if (url == null) + { + log.config("No URL"); + return null; + } + try + { + URLConnection conn = url.openConnection(); + conn.setUseCaches(false); + InputStream is = conn.getInputStream(); + byte[] buffer = new byte[1024*8]; // 8kB + ByteArrayOutputStream os = new ByteArrayOutputStream(); + int length = -1; + while ((length = is.read(buffer)) != -1) + os.write(buffer, 0, length); + is.close(); + data = os.toByteArray(); + os.close(); + + } + catch (Exception e) + { + log.config (e.toString()); + } + return data; + } // getData + + /** + * String Representation + * @return String + */ + public String toString() + { + return "MImage[ID=" + get_ID() + ",Name=" + getName() + "]"; + } // toString + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getAD_Org_ID() != 0) + setAD_Org_ID(0); + return true; + } // beforeSave + +} // MImage diff --git a/base/src/org/compiere/model/MInOut.java b/base/src/org/compiere/model/MInOut.java new file mode 100644 index 0000000000..d094ac0fca --- /dev/null +++ b/base/src/org/compiere/model/MInOut.java @@ -0,0 +1,1871 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.print.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Shipment Model + * + * @author Jorg Janke + * @version $Id: MInOut.java,v 1.4 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MInOut extends X_M_InOut implements DocAction +{ + /** + * Create Shipment From Order + * @param order order + * @param movementDate optional movement date + * @param forceDelivery ignore order delivery rule + * @param allAttributeInstances if true, all attribute set instances + * @param minGuaranteeDate optional minimum guarantee date if all attribute instances + * @param complete complete document (Process if false, Complete if true) + * @param trxName transaction + * @return Shipment or null + */ + public static MInOut createFrom (MOrder order, Timestamp movementDate, + boolean forceDelivery, boolean allAttributeInstances, Timestamp minGuaranteeDate, + boolean complete, String trxName) + { + if (order == null) + throw new IllegalArgumentException("No Order"); + // + if (!forceDelivery && DELIVERYRULE_CompleteLine.equals(order.getDeliveryRule())) + { + return null; + } + + // Create Meader + MInOut retValue = new MInOut (order, 0, movementDate); + retValue.setDocAction(complete ? DOCACTION_Complete : DOCACTION_Prepare); + + // Check if we can create the lines + MOrderLine[] oLines = order.getLines(true, "M_Product_ID"); + for (int i = 0; i < oLines.length; i++) + { + BigDecimal qty = oLines[i].getQtyOrdered().subtract(oLines[i].getQtyDelivered()); + // Nothing to deliver + if (qty.signum() == 0) + continue; + // Stock Info + MStorage[] storages = null; + MProduct product = oLines[i].getProduct(); + if (product != null && product.get_ID() != 0 && product.isStocked()) + { + MProductCategory pc = MProductCategory.get(order.getCtx(), product.getM_Product_Category_ID()); + String MMPolicy = pc.getMMPolicy(); + if (MMPolicy == null || MMPolicy.length() == 0) + { + MClient client = MClient.get(order.getCtx()); + MMPolicy = client.getMMPolicy(); + } + storages = MStorage.getWarehouse (order.getCtx(), order.getM_Warehouse_ID(), + oLines[i].getM_Product_ID(), oLines[i].getM_AttributeSetInstance_ID(), + product.getM_AttributeSet_ID(), + allAttributeInstances, minGuaranteeDate, + MClient.MMPOLICY_FiFo.equals(MMPolicy), trxName); + } + if (!forceDelivery) + { + BigDecimal maxQty = Env.ZERO; + for (int ll = 0; ll < storages.length; ll++) + maxQty = maxQty.add(storages[ll].getQtyOnHand()); + if (DELIVERYRULE_Availability.equals(order.getDeliveryRule())) + { + if (maxQty.compareTo(qty) < 0) + qty = maxQty; + } + else if (DELIVERYRULE_CompleteLine.equals(order.getDeliveryRule())) + { + if (maxQty.compareTo(qty) < 0) + continue; + } + } + // Create Line + if (retValue.get_ID() == 0) // not saved yet + retValue.save(trxName); + // Create a line until qty is reached + for (int ll = 0; ll < storages.length; ll++) + { + BigDecimal lineQty = storages[ll].getQtyOnHand(); + if (lineQty.compareTo(qty) > 0) + lineQty = qty; + MInOutLine line = new MInOutLine (retValue); + line.setOrderLine(oLines[i], storages[ll].getM_Locator_ID(), + order.isSOTrx() ? lineQty : Env.ZERO); + line.setQty(lineQty); // Correct UOM for QtyEntered + if (oLines[i].getQtyEntered().compareTo(oLines[i].getQtyOrdered()) != 0) + line.setQtyEntered(lineQty + .multiply(oLines[i].getQtyEntered()) + .divide(oLines[i].getQtyOrdered(), 12, BigDecimal.ROUND_HALF_UP)); + line.setC_Project_ID(oLines[i].getC_Project_ID()); + line.save(trxName); + // Delivered everything ? + qty = qty.subtract(lineQty); + // storage[ll].changeQtyOnHand(lineQty, !order.isSOTrx()); // Credit Memo not considered + // storage[ll].save(get_TrxName()); + if (qty.signum() == 0) + break; + } + } // for all order lines + + // No Lines saved + if (retValue.get_ID() == 0) + return null; + + return retValue; + } // createFrom + + /** + * Create new Shipment by copying + * @param from shipment + * @param dateDoc date of the document date + * @param C_DocType_ID doc type + * @param isSOTrx sales order + * @param counter create counter links + * @param trxName trx + * @param setOrder set the order link + * @return Shipment + */ + public static MInOut copyFrom (MInOut from, Timestamp dateDoc, + int C_DocType_ID, boolean isSOTrx, boolean counter, String trxName, boolean setOrder) + { + MInOut to = new MInOut (from.getCtx(), 0, null); + to.set_TrxName(trxName); + copyValues(from, to, from.getAD_Client_ID(), from.getAD_Org_ID()); + to.set_ValueNoCheck ("M_InOut_ID", I_ZERO); + to.set_ValueNoCheck ("DocumentNo", null); + // + to.setDocStatus (DOCSTATUS_Drafted); // Draft + to.setDocAction(DOCACTION_Complete); + // + to.setC_DocType_ID (C_DocType_ID); + to.setIsSOTrx(isSOTrx); + if (counter) + to.setMovementType (isSOTrx ? MOVEMENTTYPE_CustomerShipment : MOVEMENTTYPE_VendorReceipts); + // + to.setDateOrdered (dateDoc); + to.setDateAcct (dateDoc); + to.setMovementDate(dateDoc); + to.setDatePrinted(null); + to.setIsPrinted (false); + to.setDateReceived(null); + to.setNoPackages(0); + to.setShipDate(null); + to.setPickDate(null); + to.setIsInTransit(false); + // + to.setIsApproved (false); + to.setC_Invoice_ID(0); + to.setTrackingNo(null); + to.setIsInDispute(false); + // + to.setPosted (false); + to.setProcessed (false); + to.setC_Order_ID(0); // Overwritten by setOrder + if (counter) + { + to.setC_Order_ID(0); + to.setRef_InOut_ID(from.getM_InOut_ID()); + // Try to find Order/Invoice link + if (from.getC_Order_ID() != 0) + { + MOrder peer = new MOrder (from.getCtx(), from.getC_Order_ID(), from.get_TrxName()); + if (peer.getRef_Order_ID() != 0) + to.setC_Order_ID(peer.getRef_Order_ID()); + } + if (from.getC_Invoice_ID() != 0) + { + MInvoice peer = new MInvoice (from.getCtx(), from.getC_Invoice_ID(), from.get_TrxName()); + if (peer.getRef_Invoice_ID() != 0) + to.setC_Invoice_ID(peer.getRef_Invoice_ID()); + } + } + else + { + to.setRef_InOut_ID(0); + if (setOrder) + to.setC_Order_ID(from.getC_Order_ID()); + } + // + if (!to.save(trxName)) + throw new IllegalStateException("Could not create Shipment"); + if (counter) + from.setRef_InOut_ID(to.getM_InOut_ID()); + + if (to.copyLinesFrom(from, counter, setOrder) == 0) + throw new IllegalStateException("Could not create Shipment Lines"); + + return to; + } // copyFrom + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_InOut_ID + * @param trxName rx name + */ + public MInOut (Properties ctx, int M_InOut_ID, String trxName) + { + super (ctx, M_InOut_ID, trxName); + if (M_InOut_ID == 0) + { + // setDocumentNo (null); + // setC_BPartner_ID (0); + // setC_BPartner_Location_ID (0); + // setM_Warehouse_ID (0); + // setC_DocType_ID (0); + setIsSOTrx (false); + setMovementDate (new Timestamp (System.currentTimeMillis ())); + setDateAcct (getMovementDate()); + // setMovementType (MOVEMENTTYPE_CustomerShipment); + setDeliveryRule (DELIVERYRULE_Availability); + setDeliveryViaRule (DELIVERYVIARULE_Pickup); + setFreightCostRule (FREIGHTCOSTRULE_FreightIncluded); + setDocStatus (DOCSTATUS_Drafted); + setDocAction (DOCACTION_Complete); + setPriorityRule (PRIORITYRULE_Medium); + setNoPackages(0); + setIsInTransit(false); + setIsPrinted (false); + setSendEMail (false); + setIsInDispute(false); + // + setIsApproved(false); + super.setProcessed (false); + setProcessing(false); + setPosted(false); + } + } // MInOut + + /** + * Load Constructor + * @param ctx context + * @param rs result set record + * @param trxName transaction + */ + public MInOut (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MInOut + + /** + * Order Constructor - create header only + * @param order order + * @param movementDate optional movement date (default today) + * @param C_DocTypeShipment_ID document type or 0 + */ + public MInOut (MOrder order, int C_DocTypeShipment_ID, Timestamp movementDate) + { + this (order.getCtx(), 0, order.get_TrxName()); + setClientOrg(order); + setC_BPartner_ID (order.getC_BPartner_ID()); + setC_BPartner_Location_ID (order.getC_BPartner_Location_ID()); // shipment address + setAD_User_ID(order.getAD_User_ID()); + // + setM_Warehouse_ID (order.getM_Warehouse_ID()); + setIsSOTrx (order.isSOTrx()); + setMovementType (order.isSOTrx() ? MOVEMENTTYPE_CustomerShipment : MOVEMENTTYPE_VendorReceipts); + if (C_DocTypeShipment_ID == 0) + C_DocTypeShipment_ID = DB.getSQLValue(null, + "SELECT C_DocTypeShipment_ID FROM C_DocType WHERE C_DocType_ID=?", + order.getC_DocType_ID()); + setC_DocType_ID (C_DocTypeShipment_ID); + + // Default - Today + if (movementDate != null) + setMovementDate (movementDate); + setDateAcct (getMovementDate()); + + // Copy from Order + setC_Order_ID(order.getC_Order_ID()); + setDeliveryRule (order.getDeliveryRule()); + setDeliveryViaRule (order.getDeliveryViaRule()); + setM_Shipper_ID(order.getM_Shipper_ID()); + setFreightCostRule (order.getFreightCostRule()); + setFreightAmt(order.getFreightAmt()); + setSalesRep_ID(order.getSalesRep_ID()); + // + setC_Activity_ID(order.getC_Activity_ID()); + setC_Campaign_ID(order.getC_Campaign_ID()); + setC_Charge_ID(order.getC_Charge_ID()); + setChargeAmt(order.getChargeAmt()); + // + setC_Project_ID(order.getC_Project_ID()); + setDateOrdered(order.getDateOrdered()); + setDescription(order.getDescription()); + setPOReference(order.getPOReference()); + setSalesRep_ID(order.getSalesRep_ID()); + setAD_OrgTrx_ID(order.getAD_OrgTrx_ID()); + setUser1_ID(order.getUser1_ID()); + setUser2_ID(order.getUser2_ID()); + } // MInOut + + /** + * Invoice Constructor - create header only + * @param invoice invoice + * @param C_DocTypeShipment_ID document type or 0 + * @param movementDate optional movement date (default today) + * @param M_Warehouse_ID warehouse + */ + public MInOut (MInvoice invoice, int C_DocTypeShipment_ID, Timestamp movementDate, int M_Warehouse_ID) + { + this (invoice.getCtx(), 0, invoice.get_TrxName()); + setClientOrg(invoice); + setC_BPartner_ID (invoice.getC_BPartner_ID()); + setC_BPartner_Location_ID (invoice.getC_BPartner_Location_ID()); // shipment address + setAD_User_ID(invoice.getAD_User_ID()); + // + setM_Warehouse_ID (M_Warehouse_ID); + setIsSOTrx (invoice.isSOTrx()); + setMovementType (invoice.isSOTrx() ? MOVEMENTTYPE_CustomerShipment : MOVEMENTTYPE_VendorReceipts); + MOrder order = null; + if (invoice.getC_Order_ID() != 0) + order = new MOrder (invoice.getCtx(), invoice.getC_Order_ID(), invoice.get_TrxName()); + if (C_DocTypeShipment_ID == 0 && order != null) + C_DocTypeShipment_ID = DB.getSQLValue(null, + "SELECT C_DocTypeShipment_ID FROM C_DocType WHERE C_DocType_ID=?", + order.getC_DocType_ID()); + if (C_DocTypeShipment_ID != 0) + setC_DocType_ID (C_DocTypeShipment_ID); + else + setC_DocType_ID(); + + // Default - Today + if (movementDate != null) + setMovementDate (movementDate); + setDateAcct (getMovementDate()); + + // Copy from Invoice + setC_Order_ID(invoice.getC_Order_ID()); + setSalesRep_ID(invoice.getSalesRep_ID()); + // + setC_Activity_ID(invoice.getC_Activity_ID()); + setC_Campaign_ID(invoice.getC_Campaign_ID()); + setC_Charge_ID(invoice.getC_Charge_ID()); + setChargeAmt(invoice.getChargeAmt()); + // + setC_Project_ID(invoice.getC_Project_ID()); + setDateOrdered(invoice.getDateOrdered()); + setDescription(invoice.getDescription()); + setPOReference(invoice.getPOReference()); + setAD_OrgTrx_ID(invoice.getAD_OrgTrx_ID()); + setUser1_ID(invoice.getUser1_ID()); + setUser2_ID(invoice.getUser2_ID()); + + if (order != null) + { + setDeliveryRule (order.getDeliveryRule()); + setDeliveryViaRule (order.getDeliveryViaRule()); + setM_Shipper_ID(order.getM_Shipper_ID()); + setFreightCostRule (order.getFreightCostRule()); + setFreightAmt(order.getFreightAmt()); + } + } // MInOut + + /** + * Copy Constructor - create header only + * @param original original + * @param movementDate optional movement date (default today) + * @param C_DocTypeShipment_ID document type or 0 + */ + public MInOut (MInOut original, int C_DocTypeShipment_ID, Timestamp movementDate) + { + this (original.getCtx(), 0, original.get_TrxName()); + setClientOrg(original); + setC_BPartner_ID (original.getC_BPartner_ID()); + setC_BPartner_Location_ID (original.getC_BPartner_Location_ID()); // shipment address + setAD_User_ID(original.getAD_User_ID()); + // + setM_Warehouse_ID (original.getM_Warehouse_ID()); + setIsSOTrx (original.isSOTrx()); + setMovementType (original.getMovementType()); + if (C_DocTypeShipment_ID == 0) + setC_DocType_ID(original.getC_DocType_ID()); + else + setC_DocType_ID (C_DocTypeShipment_ID); + + // Default - Today + if (movementDate != null) + setMovementDate (movementDate); + setDateAcct (getMovementDate()); + + // Copy from Order + setC_Order_ID(original.getC_Order_ID()); + setDeliveryRule (original.getDeliveryRule()); + setDeliveryViaRule (original.getDeliveryViaRule()); + setM_Shipper_ID(original.getM_Shipper_ID()); + setFreightCostRule (original.getFreightCostRule()); + setFreightAmt(original.getFreightAmt()); + setSalesRep_ID(original.getSalesRep_ID()); + // + setC_Activity_ID(original.getC_Activity_ID()); + setC_Campaign_ID(original.getC_Campaign_ID()); + setC_Charge_ID(original.getC_Charge_ID()); + setChargeAmt(original.getChargeAmt()); + // + setC_Project_ID(original.getC_Project_ID()); + setDateOrdered(original.getDateOrdered()); + setDescription(original.getDescription()); + setPOReference(original.getPOReference()); + setSalesRep_ID(original.getSalesRep_ID()); + setAD_OrgTrx_ID(original.getAD_OrgTrx_ID()); + setUser1_ID(original.getUser1_ID()); + setUser2_ID(original.getUser2_ID()); + } // MInOut + + + /** Lines */ + private MInOutLine[] m_lines = null; + /** Confirmations */ + private MInOutConfirm[] m_confirms = null; + /** BPartner */ + private MBPartner m_partner = null; + + + /** + * Get Document Status + * @return Document Status Clear Text + */ + public String getDocStatusName() + { + return MRefList.getListName(getCtx(), 131, getDocStatus()); + } // getDocStatusName + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * String representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MInOut[") + .append (get_ID()).append("-").append(getDocumentNo()) + .append(",DocStatus=").append(getDocStatus()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Get Document Info + * @return document info (untranslated) + */ + public String getDocumentInfo() + { + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + return dt.getName() + " " + getDocumentNo(); + } // getDocumentInfo + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.SHIPMENT, getC_Invoice_ID()); + if (re == null) + return null; + return re.getPDF(file); + } // createPDF + + /** + * Get Lines of Shipment + * @param requery refresh from db + * @return lines + */ + public MInOutLine[] getLines (boolean requery) + { + if (m_lines != null && !requery) + return m_lines; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_InOutLine WHERE M_InOut_ID=? ORDER BY Line"; + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getM_InOut_ID()); + rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MInOutLine(getCtx(), rs, get_TrxName())); + rs.close(); + rs = null; + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + list = null; + // throw new DBException(ex); + } + finally + { + try + { + if (rs != null) + rs.close(); + if (pstmt != null) + pstmt.close(); + } + catch (SQLException e) + { + } + } + pstmt = null; + rs = null; + // + if (list == null) + return null; + // + m_lines = new MInOutLine[list.size()]; + list.toArray(m_lines); + return m_lines; + } // getMInOutLines + + /** + * Get Lines of Shipment + * @return lines + */ + public MInOutLine[] getLines() + { + return getLines(false); + } // getLines + + + /** + * Get Confirmations + * @param requery requery + * @return array of Confirmations + */ + public MInOutConfirm[] getConfirmations(boolean requery) + { + if (m_confirms != null && !requery) + return m_confirms; + + ArrayList list = new ArrayList (); + String sql = "SELECT * FROM M_InOutConfirm WHERE M_InOut_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getM_InOut_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MInOutConfirm(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + m_confirms = new MInOutConfirm[list.size ()]; + list.toArray (m_confirms); + return m_confirms; + } // getConfirmations + + + /** + * Copy Lines From other Shipment + * @param otherShipment shipment + * @param counter set counter info + * @param setOrder set order link + * @return number of lines copied + */ + public int copyLinesFrom (MInOut otherShipment, boolean counter, boolean setOrder) + { + if (isProcessed() || isPosted() || otherShipment == null) + return 0; + MInOutLine[] fromLines = otherShipment.getLines(false); + int count = 0; + for (int i = 0; i < fromLines.length; i++) + { + MInOutLine line = new MInOutLine (this); + MInOutLine fromLine = fromLines[i]; + line.set_TrxName(get_TrxName()); + if (counter) // header + PO.copyValues(fromLine, line, getAD_Client_ID(), getAD_Org_ID()); + else + PO.copyValues(fromLine, line, fromLine.getAD_Client_ID(), fromLine.getAD_Org_ID()); + line.setM_InOut_ID(getM_InOut_ID()); + line.set_ValueNoCheck ("M_InOutLine_ID", I_ZERO); // new + // Reset + if (!setOrder) + line.setC_OrderLine_ID(0); + if (!counter) + line.setM_AttributeSetInstance_ID(0); + // line.setS_ResourceAssignment_ID(0); + line.setRef_InOutLine_ID(0); + line.setIsInvoiced(false); + // + line.setConfirmedQty(Env.ZERO); + line.setPickedQty(Env.ZERO); + line.setScrappedQty(Env.ZERO); + line.setTargetQty(Env.ZERO); + // Set Locator based on header Warehouse + if (getM_Warehouse_ID() != otherShipment.getM_Warehouse_ID()) + { + line.setM_Locator_ID(0); + line.setM_Locator_ID(Env.ZERO); + } + // + if (counter) + { + line.setRef_InOutLine_ID(fromLine.getM_InOutLine_ID()); + if (fromLine.getC_OrderLine_ID() != 0) + { + MOrderLine peer = new MOrderLine (getCtx(), fromLine.getC_OrderLine_ID(), get_TrxName()); + if (peer.getRef_OrderLine_ID() != 0) + line.setC_OrderLine_ID(peer.getRef_OrderLine_ID()); + } + } + // + line.setProcessed(false); + if (line.save(get_TrxName())) + count++; + // Cross Link + if (counter) + { + fromLine.setRef_InOutLine_ID(line.getM_InOutLine_ID()); + fromLine.save(get_TrxName()); + } + } + if (fromLines.length != count) + log.log(Level.SEVERE, "Line difference - From=" + fromLines.length + " <> Saved=" + count); + return count; + } // copyLinesFrom + + /** Reversal Flag */ + private boolean m_reversal = false; + + /** + * Set Reversal + * @param reversal reversal + */ + private void setReversal(boolean reversal) + { + m_reversal = reversal; + } // setReversal + /** + * Is Reversal + * @return reversal + */ + private boolean isReversal() + { + return m_reversal; + } // isReversal + + /** + * Set Processed. + * Propergate to Lines/Taxes + * @param processed processed + */ + public void setProcessed (boolean processed) + { + super.setProcessed (processed); + if (get_ID() == 0) + return; + String sql = "UPDATE M_InOutLine SET Processed='" + + (processed ? "Y" : "N") + + "' WHERE M_InOut_ID=" + getM_InOut_ID(); + int noLine = DB.executeUpdate(sql, get_TrxName()); + m_lines = null; + log.fine(processed + " - Lines=" + noLine); + } // setProcessed + + /** + * Get BPartner + * @return partner + */ + public MBPartner getBPartner() + { + if (m_partner == null) + m_partner = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName()); + return m_partner; + } // getPartner + + /** + * Set Document Type + * @param DocBaseType doc type MDocType.DOCBASETYPE_ + */ + public void setC_DocType_ID (String DocBaseType) + { + String sql = "SELECT C_DocType_ID FROM C_DocType " + + "WHERE AD_Client_ID=? AND DocBaseType=?" + + " AND IsActive='Y'" + + " AND IsSOTrx='" + (isSOTrx() ? "Y" : "N") + "' " + + "ORDER BY IsDefault DESC"; + int C_DocType_ID = DB.getSQLValue(null, sql, getAD_Client_ID(), DocBaseType); + if (C_DocType_ID <= 0) + log.log(Level.SEVERE, "Not found for AC_Client_ID=" + + getAD_Client_ID() + " - " + DocBaseType); + else + { + log.fine("DocBaseType=" + DocBaseType + " - C_DocType_ID=" + C_DocType_ID); + setC_DocType_ID (C_DocType_ID); + boolean isSOTrx = MDocType.DOCBASETYPE_MaterialDelivery.equals(DocBaseType); + setIsSOTrx (isSOTrx); + } + } // setC_DocType_ID + + /** + * Set Default C_DocType_ID. + * Based on SO flag + */ + public void setC_DocType_ID() + { + if (isSOTrx()) + setC_DocType_ID(MDocType.DOCBASETYPE_MaterialDelivery); + else + setC_DocType_ID(MDocType.DOCBASETYPE_MaterialReceipt); + } // setC_DocType_ID + + /** + * Set Business Partner Defaults & Details + * @param bp business partner + */ + public void setBPartner (MBPartner bp) + { + if (bp == null) + return; + + setC_BPartner_ID(bp.getC_BPartner_ID()); + + // Set Locations + MBPartnerLocation[] locs = bp.getLocations(false); + if (locs != null) + { + for (int i = 0; i < locs.length; i++) + { + if (locs[i].isShipTo()) + setC_BPartner_Location_ID(locs[i].getC_BPartner_Location_ID()); + } + // set to first if not set + if (getC_BPartner_Location_ID() == 0 && locs.length > 0) + setC_BPartner_Location_ID(locs[0].getC_BPartner_Location_ID()); + } + if (getC_BPartner_Location_ID() == 0) + log.log(Level.SEVERE, "Has no To Address: " + bp); + + // Set Contact + MUser[] contacts = bp.getContacts(false); + if (contacts != null && contacts.length > 0) // get first User + setAD_User_ID(contacts[0].getAD_User_ID()); + } // setBPartner + + /** + * Create the missing next Confirmation + */ + public void createConfirmation() + { + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + boolean pick = dt.isPickQAConfirm(); + boolean ship = dt.isShipConfirm(); + // Nothing to do + if (!pick && !ship) + { + log.fine("No need"); + return; + } + + // Create Both .. after each other + if (pick && ship) + { + boolean havePick = false; + boolean haveShip = false; + MInOutConfirm[] confirmations = getConfirmations(false); + for (int i = 0; i < confirmations.length; i++) + { + MInOutConfirm confirm = confirmations[i]; + if (MInOutConfirm.CONFIRMTYPE_PickQAConfirm.equals(confirm.getConfirmType())) + { + if (!confirm.isProcessed()) // wait intil done + { + log.fine("Unprocessed: " + confirm); + return; + } + havePick = true; + } + else if (MInOutConfirm.CONFIRMTYPE_ShipReceiptConfirm.equals(confirm.getConfirmType())) + haveShip = true; + } + // Create Pick + if (!havePick) + { + MInOutConfirm.create (this, MInOutConfirm.CONFIRMTYPE_PickQAConfirm, false); + return; + } + // Create Ship + if (!haveShip) + { + MInOutConfirm.create (this, MInOutConfirm.CONFIRMTYPE_ShipReceiptConfirm, false); + return; + } + return; + } + // Create just one + if (pick) + MInOutConfirm.create (this, MInOutConfirm.CONFIRMTYPE_PickQAConfirm, true); + else if (ship) + MInOutConfirm.create (this, MInOutConfirm.CONFIRMTYPE_ShipReceiptConfirm, true); + } // createConfirmation + + + /** + * Set Warehouse and check/set Organization + * @param M_Warehouse_ID id + */ + public void setM_Warehouse_ID (int M_Warehouse_ID) + { + if (M_Warehouse_ID == 0) + { + log.severe("Ignored - Cannot set AD_Warehouse_ID to 0"); + return; + } + super.setM_Warehouse_ID (M_Warehouse_ID); + // + MWarehouse wh = MWarehouse.get(getCtx(), getM_Warehouse_ID()); + if (wh.getAD_Org_ID() != getAD_Org_ID()) + { + log.warning("M_Warehouse_ID=" + M_Warehouse_ID + + ", Overwritten AD_Org_ID=" + getAD_Org_ID() + "->" + wh.getAD_Org_ID()); + setAD_Org_ID(wh.getAD_Org_ID()); + } + } // setM_Warehouse_ID + + + /** + * Before Save + * @param newRecord new + * @return true or false + */ + protected boolean beforeSave (boolean newRecord) + { + // Warehouse Org + if (newRecord) + { + MWarehouse wh = MWarehouse.get(getCtx(), getM_Warehouse_ID()); + if (wh.getAD_Org_ID() != getAD_Org_ID()) + { + log.saveError("WarehouseOrgConflict", ""); + return false; + } + } + // Shipment - Needs Order + if (isSOTrx() && getC_Order_ID() == 0) + { + log.saveError("FillMandatory", Msg.translate(getCtx(), "C_Order_ID")); + return false; + } + return true; + } // beforeSave + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success || newRecord) + return success; + + if (is_ValueChanged("AD_Org_ID")) + { + String sql = "UPDATE M_InOutLine ol" + + " SET AD_Org_ID =" + + "(SELECT AD_Org_ID" + + " FROM M_InOut o WHERE ol.M_InOut_ID=o.M_InOut_ID) " + + "WHERE M_InOut_ID=" + getC_Order_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + log.fine("Lines -> #" + no); + } + return true; + } // afterSave + + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // process + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info(toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info(toString()); + setDocAction(DOCACTION_Prepare); + return true; + } // invalidateIt + + /** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + + // Std Period open? + if (!MPeriod.isOpen(getCtx(), getDateAcct(), dt.getDocBaseType())) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + + // Credit Check + if (isSOTrx() && !isReversal()) + { + MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), null); + if (MBPartner.SOCREDITSTATUS_CreditStop.equals(bp.getSOCreditStatus())) + { + m_processMsg = "@BPartnerCreditStop@ - @TotalOpenBalance@=" + + bp.getTotalOpenBalance() + + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); + return DocAction.STATUS_Invalid; + } + if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus())) + { + m_processMsg = "@BPartnerCreditHold@ - @TotalOpenBalance@=" + + bp.getTotalOpenBalance() + + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); + return DocAction.STATUS_Invalid; + } + BigDecimal notInvoicedAmt = MBPartner.getNotInvoicedAmt(getC_BPartner_ID()); + if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus(notInvoicedAmt))) + { + m_processMsg = "@BPartnerOverSCreditHold@ - @TotalOpenBalance@=" + + bp.getTotalOpenBalance() + ", @NotInvoicedAmt@=" + notInvoicedAmt + + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); + return DocAction.STATUS_Invalid; + } + } + + // Lines + MInOutLine[] lines = getLines(true); + if (lines == null || lines.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + BigDecimal Volume = Env.ZERO; + BigDecimal Weight = Env.ZERO; + + // Mandatory Attributes + for (int i = 0; i < lines.length; i++) + { + MInOutLine line = lines[i]; + MProduct product = line.getProduct(); + if (product != null) + { + Volume = Volume.add(product.getVolume().multiply(line.getMovementQty())); + Weight = Weight.add(product.getWeight().multiply(line.getMovementQty())); + } + // + if (line.getM_AttributeSetInstance_ID() != 0) + continue; + if (product != null) + { + int M_AttributeSet_ID = product.getM_AttributeSet_ID(); + if (M_AttributeSet_ID != 0) + { + MAttributeSet mas = MAttributeSet.get(getCtx(), M_AttributeSet_ID); + if (mas != null + && ((isSOTrx() && mas.isMandatory()) + || (!isSOTrx() && mas.isMandatoryAlways())) ) + { + m_processMsg = "@M_AttributeSet_ID@ @IsMandatory@"; + return DocAction.STATUS_Invalid; + } + } + } + } + setVolume(Volume); + setWeight(Weight); + + if (!isReversal()) // don't change reversal + { + checkMaterialPolicy(); // set MASI + createConfirmation(); + } + + m_justPrepared = true; + if (!DOCACTION_Complete.equals(getDocAction())) + setDocAction(DOCACTION_Complete); + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info(toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info(toString()); + setIsApproved(false); + return true; + } // rejectIt + + /** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + // Outstanding (not processed) Incoming Confirmations ? + MInOutConfirm[] confirmations = getConfirmations(true); + for (int i = 0; i < confirmations.length; i++) + { + MInOutConfirm confirm = confirmations[i]; + if (!confirm.isProcessed()) + { + if (MInOutConfirm.CONFIRMTYPE_CustomerConfirmation.equals(confirm.getConfirmType())) + continue; + // + m_processMsg = "Open @M_InOutConfirm_ID@: " + + confirm.getConfirmTypeName() + " - " + confirm.getDocumentNo(); + return DocAction.STATUS_InProgress; + } + } + + + // Implicit Approval + if (!isApproved()) + approveIt(); + log.info(toString()); + StringBuffer info = new StringBuffer(); + + // For all lines + MInOutLine[] lines = getLines(false); + for (int lineIndex = 0; lineIndex < lines.length; lineIndex++) + { + MInOutLine sLine = lines[lineIndex]; + MProduct product = sLine.getProduct(); + + // Qty & Type + String MovementType = getMovementType(); + BigDecimal Qty = sLine.getMovementQty(); + if (MovementType.charAt(1) == '-') // C- Customer Shipment - V- Vendor Return + Qty = Qty.negate(); + BigDecimal QtySO = Env.ZERO; + BigDecimal QtyPO = Env.ZERO; + + // Update Order Line + MOrderLine oLine = null; + if (sLine.getC_OrderLine_ID() != 0) + { + oLine = new MOrderLine (getCtx(), sLine.getC_OrderLine_ID(), get_TrxName()); + log.fine("OrderLine - Reserved=" + oLine.getQtyReserved() + + ", Delivered=" + oLine.getQtyDelivered()); + if (isSOTrx()) + QtySO = sLine.getMovementQty(); + else + QtyPO = sLine.getMovementQty(); + } + + log.info("Line=" + sLine.getLine() + " - Qty=" + sLine.getMovementQty()); + + // Stock Movement - Counterpart MOrder.reserveStock + if (product != null + && product.isStocked() ) + { + log.fine("Material Transaction"); + MTransaction mtrx = null; + // Reservation ASI - assume none + int reservationAttributeSetInstance_ID = 0; // sLine.getM_AttributeSetInstance_ID(); + if (oLine != null) + reservationAttributeSetInstance_ID = oLine.getM_AttributeSetInstance_ID(); + // + if (sLine.getM_AttributeSetInstance_ID() == 0) + { + MInOutLineMA mas[] = MInOutLineMA.get(getCtx(), + sLine.getM_InOutLine_ID(), get_TrxName()); + for (int j = 0; j < mas.length; j++) + { + MInOutLineMA ma = mas[j]; + BigDecimal QtyMA = ma.getMovementQty(); + if (MovementType.charAt(1) == '-') // C- Customer Shipment - V- Vendor Return + QtyMA = QtyMA.negate(); + BigDecimal QtySOMA = Env.ZERO; + BigDecimal QtyPOMA = Env.ZERO; + if (sLine.getC_OrderLine_ID() != 0) + { + if (isSOTrx()) + QtySOMA = ma.getMovementQty(); + else + QtyPOMA = ma.getMovementQty(); + } + // Update Storage - see also VMatch.createMatchRecord + if (!MStorage.add(getCtx(), getM_Warehouse_ID(), + sLine.getM_Locator_ID(), + sLine.getM_Product_ID(), + ma.getM_AttributeSetInstance_ID(), reservationAttributeSetInstance_ID, + QtyMA, QtySOMA.negate(), QtyPOMA.negate(), get_TrxName())) + { + m_processMsg = "Cannot correct Inventory (MA)"; + return DocAction.STATUS_Invalid; + } + // Create Transaction + mtrx = new MTransaction (getCtx(), sLine.getAD_Org_ID(), + MovementType, sLine.getM_Locator_ID(), + sLine.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), + QtyMA, getMovementDate(), get_TrxName()); + mtrx.setM_InOutLine_ID(sLine.getM_InOutLine_ID()); + if (!mtrx.save()) + { + m_processMsg = "Could not create Material Transaction (MA)"; + return DocAction.STATUS_Invalid; + } + } + } + // sLine.getM_AttributeSetInstance_ID() != 0 + if (mtrx == null) + { + // Fallback: Update Storage - see also VMatch.createMatchRecord + if (!MStorage.add(getCtx(), getM_Warehouse_ID(), + sLine.getM_Locator_ID(), + sLine.getM_Product_ID(), + sLine.getM_AttributeSetInstance_ID(), reservationAttributeSetInstance_ID, + Qty, QtySO.negate(), QtyPO.negate(), get_TrxName())) + { + m_processMsg = "Cannot correct Inventory"; + return DocAction.STATUS_Invalid; + } + // FallBack: Create Transaction + mtrx = new MTransaction (getCtx(), sLine.getAD_Org_ID(), + MovementType, sLine.getM_Locator_ID(), + sLine.getM_Product_ID(), sLine.getM_AttributeSetInstance_ID(), + Qty, getMovementDate(), get_TrxName()); + mtrx.setM_InOutLine_ID(sLine.getM_InOutLine_ID()); + if (!mtrx.save()) + { + m_processMsg = "Could not create Material Transaction"; + return DocAction.STATUS_Invalid; + } + } + } // stock movement + + // Correct Order Line + if (product != null && oLine != null) // other in VMatch.createMatchRecord + oLine.setQtyReserved(oLine.getQtyReserved().subtract(sLine.getMovementQty())); + + // Update Sales Order Line + if (oLine != null) + { + if (isSOTrx() // PO is done by Matching + || sLine.getM_Product_ID() == 0) // PO Charges, empty lines + { + if (isSOTrx()) + oLine.setQtyDelivered(oLine.getQtyDelivered().subtract(Qty)); + else + oLine.setQtyDelivered(oLine.getQtyDelivered().add(Qty)); + oLine.setDateDelivered(getMovementDate()); // overwrite=last + } + if (!oLine.save()) + { + m_processMsg = "Could not update Order Line"; + return DocAction.STATUS_Invalid; + } + else + log.fine("OrderLine -> Reserved=" + oLine.getQtyReserved() + + ", Delivered=" + oLine.getQtyReserved()); + } + + // Create Asset for SO + if (product != null + && isSOTrx() + && product.isCreateAsset() + && sLine.getMovementQty().signum() > 0 + && !isReversal()) + { + log.fine("Asset"); + info.append("@A_Asset_ID@: "); + int noAssets = sLine.getMovementQty().intValue(); + if (!product.isOneAssetPerUOM()) + noAssets = 1; + for (int i = 0; i < noAssets; i++) + { + if (i > 0) + info.append(" - "); + int deliveryCount = i+1; + if (!product.isOneAssetPerUOM()) + deliveryCount = 0; + MAsset asset = new MAsset (this, sLine, deliveryCount); + if (!asset.save(get_TrxName())) + { + m_processMsg = "Could not create Asset"; + return DocAction.STATUS_Invalid; + } + info.append(asset.getValue()); + } + } // Asset + + + // Matching + if (!isSOTrx() + && sLine.getM_Product_ID() != 0 + && !isReversal()) + { + BigDecimal matchQty = sLine.getMovementQty(); + // Invoice - Receipt Match (requires Product) + MInvoiceLine iLine = MInvoiceLine.getOfInOutLine (sLine); + if (iLine != null && iLine.getM_Product_ID() != 0) + { + MMatchInv[] matches = MMatchInv.get(getCtx(), + sLine.getM_InOutLine_ID(), iLine.getC_InvoiceLine_ID(), get_TrxName()); + if (matches == null || matches.length == 0) + { + MMatchInv inv = new MMatchInv (iLine, getMovementDate(), matchQty); + if (sLine.getM_AttributeSetInstance_ID() != iLine.getM_AttributeSetInstance_ID()) + { + iLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); + iLine.save(); // update matched invoice with ASI + inv.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); + } + if (!inv.save(get_TrxName())) + { + m_processMsg = "Could not create Inv Matching"; + return DocAction.STATUS_Invalid; + } + } + } + + // Link to Order + if (sLine.getC_OrderLine_ID() != 0) + { + log.fine("PO Matching"); + // Ship - PO + MMatchPO po = MMatchPO.create (null, sLine, getMovementDate(), matchQty); + if (!po.save(get_TrxName())) + { + m_processMsg = "Could not create PO Matching"; + return DocAction.STATUS_Invalid; + } + // Update PO with ASI + if (oLine != null && oLine.getM_AttributeSetInstance_ID() == 0) + { + oLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); + oLine.save(get_TrxName()); + } + } + else // No Order - Try finding links via Invoice + { + // Invoice has an Order Link + if (iLine != null && iLine.getC_OrderLine_ID() != 0) + { + // Invoice is created before Shipment + log.fine("PO(Inv) Matching"); + // Ship - Invoice + MMatchPO po = MMatchPO.create (iLine, sLine, + getMovementDate(), matchQty); + if (!po.save(get_TrxName())) + { + m_processMsg = "Could not create PO(Inv) Matching"; + return DocAction.STATUS_Invalid; + } + // Update PO with ASI + oLine = new MOrderLine (getCtx(), po.getC_OrderLine_ID(), get_TrxName()); + if (oLine != null && oLine.getM_AttributeSetInstance_ID() == 0) + { + oLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); + oLine.save(get_TrxName()); + } + } + } // No Order + } // PO Matching + + } // for all lines + + // Counter Documents + MInOut counter = createCounterDoc(); + if (counter != null) + info.append(" - @CounterDoc@: @M_InOut_ID@=").append(counter.getDocumentNo()); + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + m_processMsg = valid; + return DocAction.STATUS_Invalid; + } + + m_processMsg = info.toString(); + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + + /** + * Check Material Policy + * Sets line ASI + */ + private void checkMaterialPolicy() + { + int no = MInOutLineMA.deleteInOutMA(getM_InOut_ID(), get_TrxName()); + if (no > 0) + log.config("Delete old #" + no); + MInOutLine[] lines = getLines(false); + + // Incoming Trx + String MovementType = getMovementType(); + boolean inTrx = MovementType.charAt(1) == '+'; // V+ Vendor Receipt + MClient client = MClient.get(getCtx()); + + // Check Lines + for (int i = 0; i < lines.length; i++) + { + MInOutLine line = lines[i]; + boolean needSave = false; + MProduct product = line.getProduct(); + + // Need to have Location + if (product != null + && line.getM_Locator_ID() == 0) + { + line.setM_Warehouse_ID(getM_Warehouse_ID()); + line.setM_Locator_ID(inTrx ? Env.ZERO : line.getMovementQty()); // default Locator + needSave = true; + } + + // Attribute Set Instance + if (product != null + && line.getM_AttributeSetInstance_ID() == 0) + { + if (inTrx) + { + MAttributeSetInstance asi = new MAttributeSetInstance(getCtx(), 0, get_TrxName()); + asi.setClientOrg(getAD_Client_ID(), 0); + asi.setM_AttributeSet_ID(product.getM_AttributeSet_ID()); + if (asi.save()) + { + line.setM_AttributeSetInstance_ID(asi.getM_AttributeSetInstance_ID()); + log.config("New ASI=" + line); + needSave = true; + } + } + else // Outgoing Trx + { + MProductCategory pc = MProductCategory.get(getCtx(), product.getM_Product_Category_ID()); + String MMPolicy = pc.getMMPolicy(); + if (MMPolicy == null || MMPolicy.length() == 0) + MMPolicy = client.getMMPolicy(); + // + MStorage[] storages = MStorage.getAllWithASI(getCtx(), + line.getM_Product_ID(), line.getM_Locator_ID(), + MClient.MMPOLICY_FiFo.equals(MMPolicy), get_TrxName()); + BigDecimal qtyToDeliver = line.getMovementQty(); + for (int ii = 0; ii < storages.length; ii++) + { + MStorage storage = storages[ii]; + if (ii == 0) + { + if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) + { + line.setM_AttributeSetInstance_ID(storage.getM_AttributeSetInstance_ID()); + needSave = true; + log.config("Direct - " + line); + qtyToDeliver = Env.ZERO; + } + else + { + log.config("Split - " + line); + MInOutLineMA ma = new MInOutLineMA (line, + storage.getM_AttributeSetInstance_ID(), + storage.getQtyOnHand()); + if (!ma.save()) + ; + qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); + log.fine("#" + ii + ": " + ma + ", QtyToDeliver=" + qtyToDeliver); + } + } + else // create addl material allocation + { + MInOutLineMA ma = new MInOutLineMA (line, + storage.getM_AttributeSetInstance_ID(), + qtyToDeliver); + if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) + qtyToDeliver = Env.ZERO; + else + { + ma.setMovementQty(storage.getQtyOnHand()); + qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); + } + if (!ma.save()) + ; + log.fine("#" + ii + ": " + ma + ", QtyToDeliver=" + qtyToDeliver); + } + if (qtyToDeliver.signum() == 0) + break; + } // for all storages + + // No AttributeSetInstance found for remainder + if (qtyToDeliver.signum() != 0) + { + MInOutLineMA ma = new MInOutLineMA (line, + 0, qtyToDeliver); + if (!ma.save()) + ; + log.fine("##: " + ma); + } + } // outgoing Trx + } // attributeSetInstance + + if (needSave && !line.save()) + log.severe("NOT saved " + line); + } // for all lines + } // checkMaterialPolicy + + + /************************************************************************** + * Create Counter Document + * @return InOut + */ + private MInOut createCounterDoc() + { + // Is this a counter doc ? + if (getRef_InOut_ID() != 0) + return null; + + // Org Must be linked to BPartner + MOrg org = MOrg.get(getCtx(), getAD_Org_ID()); + int counterC_BPartner_ID = org.getLinkedC_BPartner_ID(); + if (counterC_BPartner_ID == 0) + return null; + // Business Partner needs to be linked to Org + MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), null); + int counterAD_Org_ID = bp.getAD_OrgBP_ID_Int(); + if (counterAD_Org_ID == 0) + return null; + + MBPartner counterBP = new MBPartner (getCtx(), counterC_BPartner_ID, null); + MOrgInfo counterOrgInfo = MOrgInfo.get(getCtx(), counterAD_Org_ID); + log.info("Counter BP=" + counterBP.getName()); + + // Document Type + int C_DocTypeTarget_ID = 0; + MDocTypeCounter counterDT = MDocTypeCounter.getCounterDocType(getCtx(), getC_DocType_ID()); + if (counterDT != null) + { + log.fine(counterDT.toString()); + if (!counterDT.isCreateCounter() || !counterDT.isValid()) + return null; + C_DocTypeTarget_ID = counterDT.getCounter_C_DocType_ID(); + } + else // indirect + { + C_DocTypeTarget_ID = MDocTypeCounter.getCounterDocType_ID(getCtx(), getC_DocType_ID()); + log.fine("Indirect C_DocTypeTarget_ID=" + C_DocTypeTarget_ID); + if (C_DocTypeTarget_ID <= 0) + return null; + } + + // Deep Copy + MInOut counter = copyFrom(this, getMovementDate(), + C_DocTypeTarget_ID, !isSOTrx(), true, get_TrxName(), true); + + // + counter.setAD_Org_ID(counterAD_Org_ID); + counter.setM_Warehouse_ID(counterOrgInfo.getM_Warehouse_ID()); + // + counter.setBPartner(counterBP); + // Refernces (Should not be required + counter.setSalesRep_ID(getSalesRep_ID()); + counter.save(get_TrxName()); + + String MovementType = counter.getMovementType(); + boolean inTrx = MovementType.charAt(1) == '+'; // V+ Vendor Receipt + + // Update copied lines + MInOutLine[] counterLines = counter.getLines(true); + for (int i = 0; i < counterLines.length; i++) + { + MInOutLine counterLine = counterLines[i]; + counterLine.setClientOrg(counter); + counterLine.setM_Warehouse_ID(counter.getM_Warehouse_ID()); + counterLine.setM_Locator_ID(0); + counterLine.setM_Locator_ID(inTrx ? Env.ZERO : counterLine.getMovementQty()); + // + counterLine.save(get_TrxName()); + } + + log.fine(counter.toString()); + + // Document Action + if (counterDT != null) + { + if (counterDT.getDocAction() != null) + { + counter.setDocAction(counterDT.getDocAction()); + counter.processIt(counterDT.getDocAction()); + counter.save(get_TrxName()); + } + } + return counter; + } // createCounterDoc + + /** + * Void Document. + * @return true if success + */ + public boolean voidIt() + { + log.info(toString()); + + if (DOCSTATUS_Closed.equals(getDocStatus()) + || DOCSTATUS_Reversed.equals(getDocStatus()) + || DOCSTATUS_Voided.equals(getDocStatus())) + { + m_processMsg = "Document Closed: " + getDocStatus(); + return false; + } + + // Not Processed + if (DOCSTATUS_Drafted.equals(getDocStatus()) + || DOCSTATUS_Invalid.equals(getDocStatus()) + || DOCSTATUS_InProgress.equals(getDocStatus()) + || DOCSTATUS_Approved.equals(getDocStatus()) + || DOCSTATUS_NotApproved.equals(getDocStatus()) ) + { + // Set lines to 0 + MInOutLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MInOutLine line = lines[i]; + BigDecimal old = line.getMovementQty(); + if (old.signum() != 0) + { + line.setQty(Env.ZERO); + line.addDescription("Void (" + old + ")"); + line.save(get_TrxName()); + } + } + } + else + { + return reverseCorrectIt(); + } + + setProcessed(true); + setDocAction(DOCACTION_None); + return true; + } // voidIt + + /** + * Close Document. + * @return true if success + */ + public boolean closeIt() + { + log.info(toString()); + setProcessed(true); + setDocAction(DOCACTION_None); + return true; + } // closeIt + + /** + * Reverse Correction - same date + * @return true if success + */ + public boolean reverseCorrectIt() + { + log.info(toString()); + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + if (!MPeriod.isOpen(getCtx(), getDateAcct(), dt.getDocBaseType())) + { + m_processMsg = "@PeriodClosed@"; + return false; + } + + // Reverse/Delete Matching + if (!isSOTrx()) + { + MMatchInv[] mInv = MMatchInv.getInOut(getCtx(), getM_InOut_ID(), get_TrxName()); + for (int i = 0; i < mInv.length; i++) + mInv[i].delete(true); + MMatchPO[] mPO = MMatchPO.getInOut(getCtx(), getM_InOut_ID(), get_TrxName()); + for (int i = 0; i < mPO.length; i++) + { + if (mPO[i].getC_InvoiceLine_ID() == 0) + mPO[i].delete(true); + else + { + mPO[i].setM_InOutLine_ID(0); + mPO[i].save(); + + } + } + } + + // Deep Copy + MInOut reversal = copyFrom (this, getMovementDate(), + getC_DocType_ID(), isSOTrx(), false, get_TrxName(), true); + if (reversal == null) + { + m_processMsg = "Could not create Ship Reversal"; + return false; + } + reversal.setReversal(true); + + // Reverse Line Qty + MInOutLine[] sLines = getLines(false); + MInOutLine[] rLines = reversal.getLines(false); + for (int i = 0; i < rLines.length; i++) + { + MInOutLine rLine = rLines[i]; + rLine.setQtyEntered(rLine.getQtyEntered().negate()); + rLine.setMovementQty(rLine.getMovementQty().negate()); + rLine.setM_AttributeSetInstance_ID(sLines[i].getM_AttributeSetInstance_ID()); + if (!rLine.save(get_TrxName())) + { + m_processMsg = "Could not correct Ship Reversal Line"; + return false; + } + // We need to copy MA + if (rLine.getM_AttributeSetInstance_ID() == 0) + { + MInOutLineMA mas[] = MInOutLineMA.get(getCtx(), + sLines[i].getM_InOutLine_ID(), get_TrxName()); + for (int j = 0; j < mas.length; j++) + { + MInOutLineMA ma = new MInOutLineMA (rLine, + mas[j].getM_AttributeSetInstance_ID(), + mas[j].getMovementQty().negate()); + if (!ma.save()) + ; + } + } + // De-Activate Asset + MAsset asset = MAsset.getFromShipment(getCtx(), sLines[i].getM_InOutLine_ID(), get_TrxName()); + if (asset != null) + { + asset.setIsActive(false); + asset.addDescription("(" + reversal.getDocumentNo() + " #" + rLine.getLine() + "<-)"); + asset.save(); + } + } + reversal.setC_Order_ID(getC_Order_ID()); + reversal.addDescription("{->" + getDocumentNo() + ")"); + // + if (!reversal.processIt(DocAction.ACTION_Complete) + || !reversal.getDocStatus().equals(DocAction.STATUS_Completed)) + { + m_processMsg = "Reversal ERROR: " + reversal.getProcessMsg(); + return false; + } + reversal.closeIt(); + reversal.setDocStatus(DOCSTATUS_Reversed); + reversal.setDocAction(DOCACTION_None); + reversal.save(get_TrxName()); + // + addDescription("(" + reversal.getDocumentNo() + "<-)"); + + m_processMsg = reversal.getDocumentNo(); + setProcessed(true); + setDocStatus(DOCSTATUS_Reversed); // may come from void + setDocAction(DOCACTION_None); + return true; + } // reverseCorrectionIt + + /** + * Reverse Accrual - none + * @return false + */ + public boolean reverseAccrualIt() + { + log.info(toString()); + return false; + } // reverseAccrualIt + + /** + * Re-activate + * @return false + */ + public boolean reActivateIt() + { + log.info(toString()); + return false; + } // reActivateIt + + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getDocumentNo()); + // : Total Lines = 123.00 (#1) + sb.append(":") + // .append(Msg.translate(getCtx(),"TotalLines")).append("=").append(getTotalLines()) + .append(" (#").append(getLines(false).length).append(")"); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner (Responsible) + * @return AD_User_ID + */ + public int getDoc_User_ID() + { + return getSalesRep_ID(); + } // getDoc_User_ID + + /** + * Get Document Approval Amount + * @return amount + */ + public BigDecimal getApprovalAmt() + { + return Env.ZERO; + } // getApprovalAmt + + /** + * Get C_Currency_ID + * @return Accounting Currency + */ + public int getC_Currency_ID () + { + return Env.getContextAsInt(getCtx(),"$C_Currency_ID "); + } // getC_Currency_ID + + /** + * Document Status is Complete or Closed + * @return true if CO, CL or RE + */ + public boolean isComplete() + { + String ds = getDocStatus(); + return DOCSTATUS_Completed.equals(ds) + || DOCSTATUS_Closed.equals(ds) + || DOCSTATUS_Reversed.equals(ds); + } // isComplete + +} // MInOut diff --git a/base/src/org/compiere/model/MInOutConfirm.java b/base/src/org/compiere/model/MInOutConfirm.java new file mode 100644 index 0000000000..38ab893b15 --- /dev/null +++ b/base/src/org/compiere/model/MInOutConfirm.java @@ -0,0 +1,736 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Shipment Confirmation Model + * + * @author Jorg Janke + * @version $Id: MInOutConfirm.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MInOutConfirm extends X_M_InOutConfirm implements DocAction +{ + /** + * Create Confirmation or return existing one + * @param ship shipment + * @param confirmType confirmation type + * @param checkExisting if false, new confirmation is created + * @return Confirmation + */ + public static MInOutConfirm create (MInOut ship, String confirmType, boolean checkExisting) + { + if (checkExisting) + { + MInOutConfirm[] confirmations = ship.getConfirmations(false); + for (int i = 0; i < confirmations.length; i++) + { + MInOutConfirm confirm = confirmations[i]; + if (confirm.getConfirmType().equals(confirmType)) + { + s_log.info("create - existing: " + confirm); + return confirm; + } + } + } + + MInOutConfirm confirm = new MInOutConfirm (ship, confirmType); + confirm.save(ship.get_TrxName()); + MInOutLine[] shipLines = ship.getLines(false); + for (int i = 0; i < shipLines.length; i++) + { + MInOutLine sLine = shipLines[i]; + MInOutLineConfirm cLine = new MInOutLineConfirm (confirm); + cLine.setInOutLine(sLine); + cLine.save(ship.get_TrxName()); + } + s_log.info("New: " + confirm); + return confirm; + } // MInOutConfirm + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MInOutConfirm.class); + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_InOutConfirm_ID id + * @param trxName transaction + */ + public MInOutConfirm (Properties ctx, int M_InOutConfirm_ID, String trxName) + { + super (ctx, M_InOutConfirm_ID, trxName); + if (M_InOutConfirm_ID == 0) + { + // setConfirmType (null); + setDocAction (DOCACTION_Complete); // CO + setDocStatus (DOCSTATUS_Drafted); // DR + setIsApproved (false); + setIsCancelled (false); + setIsInDispute(false); + super.setProcessed (false); + } + } // MInOutConfirm + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MInOutConfirm (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MInOutConfirm + + /** + * Parent Constructor + * @param ship shipment + * @param confirmType confirmation type + */ + public MInOutConfirm (MInOut ship, String confirmType) + { + this (ship.getCtx(), 0, ship.get_TrxName()); + setClientOrg(ship); + setM_InOut_ID (ship.getM_InOut_ID()); + setConfirmType (confirmType); + } // MInOutConfirm + + /** Confirm Lines */ + private MInOutLineConfirm[] m_lines = null; + /** Credit Memo to create */ + private MInvoice m_creditMemo = null; + /** Physical Inventory to create */ + private MInventory m_inventory = null; + + /** + * Get Lines + * @param requery requery + * @return array of lines + */ + public MInOutLineConfirm[] getLines (boolean requery) + { + if (m_lines != null && !requery) + return m_lines; + String sql = "SELECT * FROM M_InOutLineConfirm " + + "WHERE M_InOutConfirm_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getM_InOutConfirm_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MInOutLineConfirm(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_lines = new MInOutLineConfirm[list.size ()]; + list.toArray (m_lines); + return m_lines; + } // getLines + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * Get Name of ConfirmType + * @return confirm type + */ + public String getConfirmTypeName () + { + return MRefList.getListName (getCtx(), CONFIRMTYPE_AD_Reference_ID, getConfirmType()); + } // getConfirmTypeName + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MInOutConfirm["); + sb.append(get_ID()).append("-").append(getSummary()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Get Document Info + * @return document info (untranslated) + */ + public String getDocumentInfo() + { + return Msg.getElement(getCtx(), "M_InOutConfirm_ID") + " " + getDocumentNo(); + } // getDocumentInfo + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + // ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.INVOICE, getC_Invoice_ID()); + // if (re == null) + return null; + // return re.getPDF(file); + } // createPDF + + /** + * Set Approved + * @param IsApproved approval + */ + public void setIsApproved (boolean IsApproved) + { + if (IsApproved && !isApproved()) + { + int AD_User_ID = Env.getAD_User_ID(getCtx()); + MUser user = MUser.get(getCtx(), AD_User_ID); + String info = user.getName() + + ": " + + Msg.translate(getCtx(), "IsApproved") + + " - " + new Timestamp(System.currentTimeMillis()); + addDescription(info); + } + super.setIsApproved (IsApproved); + } // setIsApproved + + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // processIt + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info(toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info(toString()); + setDocAction(DOCACTION_Prepare); + return true; + } // invalidateIt + + /** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + + /** + MDocType dt = MDocType.get(getCtx(), getC_DocTypeTarget_ID()); + + // Std Period open? + if (!MPeriod.isOpen(getCtx(), getDateAcct(), dt.getDocBaseType())) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + **/ + + MInOutLineConfirm[] lines = getLines(true); + if (lines.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + // Set dispute if not fully confirmed + boolean difference = false; + for (int i = 0; i < lines.length; i++) + { + if (!lines[i].isFullyConfirmed()) + { + difference = true; + break; + } + } + setIsInDispute(difference); + + // + m_justPrepared = true; + if (!DOCACTION_Complete.equals(getDocAction())) + setDocAction(DOCACTION_Complete); + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info(toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info(toString()); + setIsApproved(false); + return true; + } // rejectIt + + /** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + // Implicit Approval + if (!isApproved()) + approveIt(); + log.info(toString()); + // + MInOut inout = new MInOut (getCtx(), getM_InOut_ID(), get_TrxName()); + MInOutLineConfirm[] lines = getLines(false); + + // Check if we need to split Shipment + if (isInDispute()) + { + MDocType dt = MDocType.get(getCtx(), inout.getC_DocType_ID()); + if (dt.isSplitWhenDifference()) + { + if (dt.getC_DocTypeDifference_ID() == 0) + { + m_processMsg = "No Split Document Type defined for: " + dt.getName(); + return DocAction.STATUS_Invalid; + } + splitInOut (inout, dt.getC_DocTypeDifference_ID(), lines); + m_lines = null; + } + } + + // All lines + for (int i = 0; i < lines.length; i++) + { + MInOutLineConfirm confirmLine = lines[i]; + confirmLine.set_TrxName(get_TrxName()); + if (!confirmLine.processLine (inout.isSOTrx(), getConfirmType())) + { + m_processMsg = "ShipLine not saved - " + confirmLine; + return DocAction.STATUS_Invalid; + } + if (confirmLine.isFullyConfirmed()) + { + confirmLine.setProcessed(true); + confirmLine.save(get_TrxName()); + } + else + { + if (createDifferenceDoc (inout, confirmLine)) + { + confirmLine.setProcessed(true); + confirmLine.save(get_TrxName()); + } + else + { + log.log(Level.SEVERE, "Scrapped=" + confirmLine.getScrappedQty() + + " - Difference=" + confirmLine.getDifferenceQty()); + return DocAction.STATUS_Invalid; + } + } + } // for all lines + + if (m_creditMemo != null) + m_processMsg += " @C_Invoice_ID@=" + m_creditMemo.getDocumentNo(); + if (m_inventory != null) + m_processMsg += " @M_Inventory_ID@=" + m_inventory.getDocumentNo(); + + + // Try to complete Shipment + // if (inout.processIt(DocAction.ACTION_Complete)) + // m_processMsg = "@M_InOut_ID@ " + inout.getDocumentNo() + ": @Completed@"; + + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + m_processMsg = valid; + return DocAction.STATUS_Invalid; + } + + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + /** + * Split Shipment into confirmed and dispute + * @param original original shipment + * @param C_DocType_ID target DocType + * @param confirmLines confirm lines + */ + private void splitInOut (MInOut original, int C_DocType_ID, MInOutLineConfirm[] confirmLines) + { + MInOut split = new MInOut (original, C_DocType_ID, original.getMovementDate()); + split.addDescription("Splitted from " + original.getDocumentNo()); + split.setIsInDispute(true); + if (!split.save(get_TrxName())) + throw new IllegalStateException("Cannot save Split"); + original.addDescription("Split: " + split.getDocumentNo()); + if (!original.save(get_TrxName())) + throw new IllegalStateException("Cannot update original Shipment"); + + // Go through confirmations + for (int i = 0; i < confirmLines.length; i++) + { + MInOutLineConfirm confirmLine = confirmLines[i]; + BigDecimal differenceQty = confirmLine.getDifferenceQty(); + if (differenceQty.compareTo(Env.ZERO) == 0) + continue; + // + MInOutLine oldLine = confirmLine.getLine(); + log.fine("Qty=" + differenceQty + ", Old=" + oldLine); + // + MInOutLine splitLine = new MInOutLine (split); + splitLine.setC_OrderLine_ID(oldLine.getC_OrderLine_ID()); + splitLine.setC_UOM_ID(oldLine.getC_UOM_ID()); + splitLine.setDescription(oldLine.getDescription()); + splitLine.setIsDescription(oldLine.isDescription()); + splitLine.setLine(oldLine.getLine()); + splitLine.setM_AttributeSetInstance_ID(oldLine.getM_AttributeSetInstance_ID()); + splitLine.setM_Locator_ID(oldLine.getM_Locator_ID()); + splitLine.setM_Product_ID(oldLine.getM_Product_ID()); + splitLine.setM_Warehouse_ID(oldLine.getM_Warehouse_ID()); + splitLine.setRef_InOutLine_ID(oldLine.getRef_InOutLine_ID()); + splitLine.addDescription("Split: from " + oldLine.getMovementQty()); + // Qtys + splitLine.setQty(differenceQty); // Entered/Movement + if (!splitLine.save(get_TrxName())) + throw new IllegalStateException("Cannot save Split Line"); + // Old + oldLine.addDescription("Splitted: from " + oldLine.getMovementQty()); + oldLine.setQty(oldLine.getMovementQty().subtract(differenceQty)); + if (!oldLine.save(get_TrxName())) + throw new IllegalStateException("Cannot save Splited Line"); + // Update Confirmation Line + confirmLine.setTargetQty(confirmLine.getTargetQty().subtract(differenceQty)); + confirmLine.setDifferenceQty(Env.ZERO); + if (!confirmLine.save(get_TrxName())) + throw new IllegalStateException("Cannot save Split Confirmation"); + } // for all confirmations + + m_processMsg = "Split @M_InOut_ID@=" + split.getDocumentNo() + + " - @M_InOutConfirm_ID@="; + + // Create Dispute Confirmation + split.processIt(DocAction.ACTION_Prepare); + // split.createConfirmation(); + split.save(get_TrxName()); + MInOutConfirm[] splitConfirms = split.getConfirmations(true); + if (splitConfirms.length > 0) + { + int index = 0; + if (splitConfirms[index].isProcessed()) + { + if (splitConfirms.length > 1) + index++; // try just next + if (splitConfirms[index].isProcessed()) + { + m_processMsg += splitConfirms[index].getDocumentNo() + " processed??"; + return; + } + } + splitConfirms[index].setIsInDispute(true); + splitConfirms[index].save(get_TrxName()); + m_processMsg += splitConfirms[index].getDocumentNo(); + // Set Lines to unconfirmed + MInOutLineConfirm[] splitConfirmLines = splitConfirms[index].getLines(false); + for (int i = 0; i < splitConfirmLines.length; i++) + { + MInOutLineConfirm splitConfirmLine = splitConfirmLines[i]; + splitConfirmLine.setScrappedQty(Env.ZERO); + splitConfirmLine.setConfirmedQty(Env.ZERO); + splitConfirmLine.save(get_TrxName()); + } + } + else + m_processMsg += "??"; + + } // splitInOut + + + /** + * Create Difference Document + * @param inout shipment/receipt + * @param confirm confirm line + * @return true if created + */ + private boolean createDifferenceDoc (MInOut inout, MInOutLineConfirm confirm) + { + if (m_processMsg == null) + m_processMsg = ""; + else if (m_processMsg.length() > 0) + m_processMsg += "; "; + // Credit Memo if linked Document + if (confirm.getDifferenceQty().signum() != 0 + && !inout.isSOTrx() && inout.getRef_InOut_ID() != 0) + { + log.info("Difference=" + confirm.getDifferenceQty()); + if (m_creditMemo == null) + { + m_creditMemo = new MInvoice (inout, null); + m_creditMemo.setDescription(Msg.translate(getCtx(), "M_InOutConfirm_ID") + " " + getDocumentNo()); + m_creditMemo.setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_APCreditMemo); + if (!m_creditMemo.save(get_TrxName())) + { + m_processMsg += "Credit Memo not created"; + return false; + } + setC_Invoice_ID(m_creditMemo.getC_Invoice_ID()); + } + MInvoiceLine line = new MInvoiceLine (m_creditMemo); + line.setShipLine(confirm.getLine()); + line.setQty(confirm.getDifferenceQty()); // Entered/Invoiced + if (!line.save(get_TrxName())) + { + m_processMsg += "Credit Memo Line not created"; + return false; + } + confirm.setC_InvoiceLine_ID(line.getC_InvoiceLine_ID()); + } + + // Create Inventory Difference + if (confirm.getScrappedQty().signum() != 0) + { + log.info("Scrapped=" + confirm.getScrappedQty()); + if (m_inventory == null) + { + MWarehouse wh = MWarehouse.get(getCtx(), inout.getM_Warehouse_ID()); + m_inventory = new MInventory (wh); + m_inventory.setDescription(Msg.translate(getCtx(), "M_InOutConfirm_ID") + " " + getDocumentNo()); + if (!m_inventory.save(get_TrxName())) + { + m_processMsg += "Inventory not created"; + return false; + } + setM_Inventory_ID(m_inventory.getM_Inventory_ID()); + } + MInOutLine ioLine = confirm.getLine(); + MInventoryLine line = new MInventoryLine (m_inventory, + ioLine.getM_Locator_ID(), ioLine.getM_Product_ID(), ioLine.getM_AttributeSetInstance_ID(), + confirm.getScrappedQty(), Env.ZERO); + if (!line.save(get_TrxName())) + { + m_processMsg += "Inventory Line not created"; + return false; + } + confirm.setM_InventoryLine_ID(line.getM_InventoryLine_ID()); + } + + // + if (!confirm.save(get_TrxName())) + { + m_processMsg += "Confirmation Line not saved"; + return false; + } + return true; + } // createDifferenceDoc + + /** + * Void Document. + * @return false + */ + public boolean voidIt() + { + log.info(toString()); + return false; + } // voidIt + + /** + * Close Document. + * @return true if success + */ + public boolean closeIt() + { + log.info(toString()); + + setDocAction(DOCACTION_None); + return true; + } // closeIt + + /** + * Reverse Correction + * @return false + */ + public boolean reverseCorrectIt() + { + log.info(toString()); + return false; + } // reverseCorrectionIt + + /** + * Reverse Accrual - none + * @return false + */ + public boolean reverseAccrualIt() + { + log.info(toString()); + return false; + } // reverseAccrualIt + + /** + * Re-activate + * @return false + */ + public boolean reActivateIt() + { + log.info(toString()); + return false; + } // reActivateIt + + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getDocumentNo()); + // : Total Lines = 123.00 (#1) + sb.append(": ") + .append(Msg.translate(getCtx(),"ApprovalAmt")).append("=").append(getApprovalAmt()) + .append(" (#").append(getLines(false).length).append(")"); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner (Responsible) + * @return AD_User_ID + */ + public int getDoc_User_ID() + { + return getUpdatedBy(); + } // getDoc_User_ID + + /** + * Get Document Currency + * @return C_Currency_ID + */ + public int getC_Currency_ID() + { + // MPriceList pl = MPriceList.get(getCtx(), getM_PriceList_ID()); + // return pl.getC_Currency_ID(); + return 0; + } // getC_Currency_ID + +} // MInOutConfirm diff --git a/base/src/org/compiere/model/MInOutLine.java b/base/src/org/compiere/model/MInOutLine.java new file mode 100644 index 0000000000..ccb2a06441 --- /dev/null +++ b/base/src/org/compiere/model/MInOutLine.java @@ -0,0 +1,673 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * InOut Line + * + * @author Jorg Janke + * @version $Id: MInOutLine.java,v 1.5 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MInOutLine extends X_M_InOutLine +{ + /** + * Get Ship lines Of Order Line + * @param ctx context + * @param C_OrderLine_ID line + * @param where optional addition where clause + * @param trxName transaction + * @return array of receipt lines + */ + public static MInOutLine[] getOfOrderLine (Properties ctx, + int C_OrderLine_ID, String where, String trxName) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_InOutLine WHERE C_OrderLine_ID=?"; + if (where != null && where.length() > 0) + sql += " AND " + where; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, C_OrderLine_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MInOutLine(ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MInOutLine[] retValue = new MInOutLine[list.size ()]; + list.toArray (retValue); + return retValue; + } // getOfOrderLine + + /** + * Get Ship lines Of Order Line + * @param ctx context + * @param C_OrderLine_ID line + * @param trxName transaction + * @return array of receipt lines2 + */ + public static MInOutLine[] get (Properties ctx, int C_OrderLine_ID, String trxName) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_InOutLine WHERE C_OrderLine_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, C_OrderLine_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MInOutLine(ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MInOutLine[] retValue = new MInOutLine[list.size ()]; + list.toArray (retValue); + return retValue; + } // getOfOrderLine + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MInOutLine.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_InOutLine_ID id + * @param trxName trx name + */ + public MInOutLine (Properties ctx, int M_InOutLine_ID, String trxName) + { + super (ctx, M_InOutLine_ID, trxName); + if (M_InOutLine_ID == 0) + { + // setLine (0); + // setM_Locator_ID (0); + // setC_UOM_ID (0); + // setM_Product_ID (0); + setM_AttributeSetInstance_ID(0); + // setMovementQty (Env.ZERO); + setConfirmedQty(Env.ZERO); + setPickedQty(Env.ZERO); + setScrappedQty(Env.ZERO); + setTargetQty(Env.ZERO); + setIsInvoiced (false); + setIsDescription (false); + } + } // MInOutLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set record + * @param trxName transaction + */ + public MInOutLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MInOutLine + + /** + * Parent Constructor + * @param inout parent + */ + public MInOutLine (MInOut inout) + { + this (inout.getCtx(), 0, inout.get_TrxName()); + setClientOrg (inout); + setM_InOut_ID (inout.getM_InOut_ID()); + setM_Warehouse_ID (inout.getM_Warehouse_ID()); + setC_Project_ID(inout.getC_Project_ID()); + m_parent = inout; + } // MInOutLine + + /** Product */ + private MProduct m_product = null; + /** Warehouse */ + private int m_M_Warehouse_ID = 0; + /** Parent */ + private MInOut m_parent = null; + + /** + * Get Parent + * @return parent + */ + public MInOut getParent() + { + if (m_parent == null) + m_parent = new MInOut (getCtx(), getM_InOut_ID(), get_TrxName()); + return m_parent; + } // getParent + + /** + * Set Order Line. + * Does not set Quantity! + * @param oLine order line + * @param M_Locator_ID locator + * @param Qty used only to find suitable locator + */ + public void setOrderLine (MOrderLine oLine, int M_Locator_ID, BigDecimal Qty) + { + setC_OrderLine_ID(oLine.getC_OrderLine_ID()); + setLine(oLine.getLine()); + setC_UOM_ID(oLine.getC_UOM_ID()); + MProduct product = oLine.getProduct(); + if (product == null) + { + set_ValueNoCheck("M_Product_ID", null); + set_ValueNoCheck("M_AttributeSetInstance_ID", null); + set_ValueNoCheck("M_Locator_ID", null); + } + else + { + setM_Product_ID(oLine.getM_Product_ID()); + setM_AttributeSetInstance_ID(oLine.getM_AttributeSetInstance_ID()); + // + if (product.isItem()) + { + if (M_Locator_ID == 0) + setM_Locator_ID(Qty); // requires warehouse, product, asi + else + setM_Locator_ID(M_Locator_ID); + } + else + set_ValueNoCheck("M_Locator_ID", null); + } + setC_Charge_ID(oLine.getC_Charge_ID()); + setDescription(oLine.getDescription()); + setIsDescription(oLine.isDescription()); + // + setC_Project_ID(oLine.getC_Project_ID()); + setC_ProjectPhase_ID(oLine.getC_ProjectPhase_ID()); + setC_ProjectTask_ID(oLine.getC_ProjectTask_ID()); + setC_Activity_ID(oLine.getC_Activity_ID()); + setC_Campaign_ID(oLine.getC_Campaign_ID()); + setAD_OrgTrx_ID(oLine.getAD_OrgTrx_ID()); + setUser1_ID(oLine.getUser1_ID()); + setUser2_ID(oLine.getUser2_ID()); + } // setOrderLine + + /** + * Set Invoice Line. + * Does not set Quantity! + * @param iLine invoice line + * @param M_Locator_ID locator + * @param Qty qty only fo find suitable locator + */ + public void setInvoiceLine (MInvoiceLine iLine, int M_Locator_ID, BigDecimal Qty) + { + setC_OrderLine_ID(iLine.getC_OrderLine_ID()); + setLine(iLine.getLine()); + setC_UOM_ID(iLine.getC_UOM_ID()); + int M_Product_ID = iLine.getM_Product_ID(); + if (M_Product_ID == 0) + { + set_ValueNoCheck("M_Product_ID", null); + set_ValueNoCheck("M_Locator_ID", null); + set_ValueNoCheck("M_AttributeSetInstance_ID", null); + } + else + { + setM_Product_ID(M_Product_ID); + setM_AttributeSetInstance_ID(iLine.getM_AttributeSetInstance_ID()); + if (M_Locator_ID == 0) + setM_Locator_ID(Qty); // requires warehouse, product, asi + else + setM_Locator_ID(M_Locator_ID); + } + setC_Charge_ID(iLine.getC_Charge_ID()); + setDescription(iLine.getDescription()); + setIsDescription(iLine.isDescription()); + // + setC_Project_ID(iLine.getC_Project_ID()); + setC_ProjectPhase_ID(iLine.getC_ProjectPhase_ID()); + setC_ProjectTask_ID(iLine.getC_ProjectTask_ID()); + setC_Activity_ID(iLine.getC_Activity_ID()); + setC_Campaign_ID(iLine.getC_Campaign_ID()); + setAD_OrgTrx_ID(iLine.getAD_OrgTrx_ID()); + setUser1_ID(iLine.getUser1_ID()); + setUser2_ID(iLine.getUser2_ID()); + } // setInvoiceLine + + /** + * Get Warehouse + * @return Returns the m_Warehouse_ID. + */ + public int getM_Warehouse_ID() + { + if (m_M_Warehouse_ID == 0) + m_M_Warehouse_ID = getParent().getM_Warehouse_ID(); + return m_M_Warehouse_ID; + } // getM_Warehouse_ID + + /** + * Set Warehouse + * @param warehouse_ID The m_Warehouse_ID to set. + */ + public void setM_Warehouse_ID (int warehouse_ID) + { + m_M_Warehouse_ID = warehouse_ID; + } // setM_Warehouse_ID + + /** + * Set M_Locator_ID + * @param M_Locator_ID id + */ + public void setM_Locator_ID (int M_Locator_ID) + { + if (M_Locator_ID < 0) + throw new IllegalArgumentException ("M_Locator_ID is mandatory."); + // set to 0 explicitly to reset + set_Value ("M_Locator_ID", new Integer(M_Locator_ID)); + } // setM_Locator_ID + + /** + * Set (default) Locator based on qty. + * @param Qty quantity + * Assumes Warehouse is set + */ + public void setM_Locator_ID(BigDecimal Qty) + { + // Locator esatblished + if (getM_Locator_ID() != 0) + return; + // No Product + if (getM_Product_ID() == 0) + { + set_ValueNoCheck("M_Locator_ID", null); + return; + } + + // Get existing Location + int M_Locator_ID = MStorage.getM_Locator_ID (getM_Warehouse_ID(), + getM_Product_ID(), getM_AttributeSetInstance_ID(), + Qty, get_TrxName()); + // Get default Location + if (M_Locator_ID == 0) + { + MWarehouse wh = MWarehouse.get(getCtx(), getM_Warehouse_ID()); + M_Locator_ID = wh.getDefaultLocator().getM_Locator_ID(); + } + setM_Locator_ID(M_Locator_ID); + } // setM_Locator_ID + + /** + * Set Movement/Movement Qty + * @param Qty Entered/Movement Qty + */ + public void setQty (BigDecimal Qty) + { + setQtyEntered(Qty); + setMovementQty(getQtyEntered()); + } // setQtyInvoiced + + /** + * Set Qty Entered - enforce entered UOM + * @param QtyEntered + */ + public void setQtyEntered (BigDecimal QtyEntered) + { + if (QtyEntered != null && getC_UOM_ID() != 0) + { + int precision = MUOM.getPrecision(getCtx(), getC_UOM_ID()); + QtyEntered = QtyEntered.setScale(precision, BigDecimal.ROUND_HALF_UP); + } + super.setQtyEntered (QtyEntered); + } // setQtyEntered + + /** + * Set Movement Qty - enforce Product UOM + * @param MovementQty + */ + public void setMovementQty (BigDecimal MovementQty) + { + MProduct product = getProduct(); + if (MovementQty != null && product != null) + { + int precision = product.getUOMPrecision(); + MovementQty = MovementQty.setScale(precision, BigDecimal.ROUND_HALF_UP); + } + super.setMovementQty(MovementQty); + } // setMovementQty + + /** + * Get Product + * @return product or null + */ + public MProduct getProduct() + { + if (m_product == null && getM_Product_ID() != 0) + m_product = MProduct.get (getCtx(), getM_Product_ID()); + return m_product; + } // getProduct + + /** + * Set Product + * @param product product + */ + public void setProduct (MProduct product) + { + m_product = product; + if (m_product != null) + { + setM_Product_ID(m_product.getM_Product_ID()); + setC_UOM_ID (m_product.getC_UOM_ID()); + } + else + { + setM_Product_ID(0); + setC_UOM_ID (0); + } + setM_AttributeSetInstance_ID(0); + } // setProduct + + /** + * Set M_Product_ID + * @param M_Product_ID product + * @param setUOM also set UOM from product + */ + public void setM_Product_ID (int M_Product_ID, boolean setUOM) + { + if (setUOM) + setProduct(MProduct.get(getCtx(), M_Product_ID)); + else + super.setM_Product_ID (M_Product_ID); + setM_AttributeSetInstance_ID(0); + } // setM_Product_ID + + /** + * Set Product and UOM + * @param M_Product_ID product + * @param C_UOM_ID uom + */ + public void setM_Product_ID (int M_Product_ID, int C_UOM_ID) + { + if (M_Product_ID != 0) + super.setM_Product_ID (M_Product_ID); + super.setC_UOM_ID(C_UOM_ID); + setM_AttributeSetInstance_ID(0); + m_product = null; + } // setM_Product_ID + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * Get C_Project_ID + * @return project + */ + public int getC_Project_ID() + { + int ii = super.getC_Project_ID (); + if (ii == 0) + ii = getParent().getC_Project_ID(); + return ii; + } // getC_Project_ID + + /** + * Get C_Activity_ID + * @return Activity + */ + public int getC_Activity_ID() + { + int ii = super.getC_Activity_ID (); + if (ii == 0) + ii = getParent().getC_Activity_ID(); + return ii; + } // getC_Activity_ID + + /** + * Get C_Campaign_ID + * @return Campaign + */ + public int getC_Campaign_ID() + { + int ii = super.getC_Campaign_ID (); + if (ii == 0) + ii = getParent().getC_Campaign_ID(); + return ii; + } // getC_Campaign_ID + + /** + * Get User2_ID + * @return User2 + */ + public int getUser1_ID () + { + int ii = super.getUser1_ID (); + if (ii == 0) + ii = getParent().getUser1_ID(); + return ii; + } // getUser1_ID + + /** + * Get User2_ID + * @return User2 + */ + public int getUser2_ID () + { + int ii = super.getUser2_ID (); + if (ii == 0) + ii = getParent().getUser2_ID(); + return ii; + } // getUser2_ID + + /** + * Get AD_OrgTrx_ID + * @return trx org + */ + public int getAD_OrgTrx_ID() + { + int ii = super.getAD_OrgTrx_ID(); + if (ii == 0) + ii = getParent().getAD_OrgTrx_ID(); + return ii; + } // getAD_OrgTrx_ID + + /************************************************************************** + * Before Save + * @param newRecord new + * @return save + */ + protected boolean beforeSave (boolean newRecord) + { + log.fine(""); + // Get Line No + if (getLine() == 0) + { + String sql = "SELECT COALESCE(MAX(Line),0)+10 FROM M_InOutLine WHERE M_InOut_ID=?"; + int ii = DB.getSQLValue (get_TrxName(), sql, getM_InOut_ID()); + setLine (ii); + } + // UOM + if (getC_UOM_ID() == 0) + setC_UOM_ID (Env.getContextAsInt(getCtx(), "#C_UOM_ID")); + if (getC_UOM_ID() == 0) + { + int C_UOM_ID = MUOM.getDefault_UOM_ID(getCtx()); + if (C_UOM_ID > 0) + setC_UOM_ID (C_UOM_ID); + } + // Qty Precision + if (newRecord || is_ValueChanged("QtyEntered")) + setQtyEntered(getQtyEntered()); + if (newRecord || is_ValueChanged("MovementQty")) + setMovementQty(getMovementQty()); + + // Order Line + if (getC_OrderLine_ID() == 0) + { + if (getParent().isSOTrx()) + { + log.saveError("FillMandatory", Msg.translate(getCtx(), "C_Order_ID")); + return false; + } + } + + // if (getC_Charge_ID() == 0 && getM_Product_ID() == 0) + // ; + + /** Qty on instance ASI + if (getM_AttributeSetInstance_ID() != 0) + { + MProduct product = getProduct(); + int M_AttributeSet_ID = product.getM_AttributeSet_ID(); + boolean isInstance = M_AttributeSet_ID != 0; + if (isInstance) + { + MAttributeSet mas = MAttributeSet.get(getCtx(), M_AttributeSet_ID); + isInstance = mas.isInstanceAttribute(); + } + // Max + if (isInstance) + { + MStorage storage = MStorage.get(getCtx(), getM_Locator_ID(), + getM_Product_ID(), getM_AttributeSetInstance_ID(), get_TrxName()); + if (storage != null) + { + BigDecimal qty = storage.getQtyOnHand(); + if (getMovementQty().compareTo(qty) > 0) + { + log.warning("Qty - Stock=" + qty + ", Movement=" + getMovementQty()); + log.saveError("QtyInsufficient", "=" + qty); + return false; + } + } + } + } /**/ + + return true; + } // beforeSave + + /** + * Before Delete + * @return true if drafted + */ + protected boolean beforeDelete () + { + if (getParent().getDocStatus().equals(MInOut.DOCSTATUS_Drafted)) + return true; + log.saveError("Error", Msg.getMsg(getCtx(), "CannotDelete")); + return false; + } // beforeDelete + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MInOutLine[").append (get_ID()) + .append(",M_Product_ID=").append(getM_Product_ID()) + .append(",QtyEntered=").append(getQtyEntered()) + .append(",MovementQty=").append(getMovementQty()) + .append(",M_AttributeSetInstance_ID=").append(getM_AttributeSetInstance_ID()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Get Base value for Cost Distribution + * @param CostDistribution cost Distribution + * @return base number + */ + public BigDecimal getBase (String CostDistribution) + { + if (MLandedCost.LANDEDCOSTDISTRIBUTION_Costs.equals(CostDistribution)) + { + // TODO Costs! + log.severe("Not Implemented yet - Cost"); + return Env.ZERO; + } + else if (MLandedCost.LANDEDCOSTDISTRIBUTION_Line.equals(CostDistribution)) + return Env.ONE; + else if (MLandedCost.LANDEDCOSTDISTRIBUTION_Quantity.equals(CostDistribution)) + return getMovementQty(); + else if (MLandedCost.LANDEDCOSTDISTRIBUTION_Volume.equals(CostDistribution)) + { + MProduct product = getProduct(); + if (product == null) + { + log.severe("No Product"); + return Env.ZERO; + } + return getMovementQty().multiply(product.getVolume()); + } + else if (MLandedCost.LANDEDCOSTDISTRIBUTION_Weight.equals(CostDistribution)) + { + MProduct product = getProduct(); + if (product == null) + { + log.severe("No Product"); + return Env.ZERO; + } + return getMovementQty().multiply(product.getWeight()); + } + // + log.severe("Invalid Criteria: " + CostDistribution); + return Env.ZERO; + } // getBase + +} // MInOutLine diff --git a/base/src/org/compiere/model/MInOutLineConfirm.java b/base/src/org/compiere/model/MInOutLineConfirm.java new file mode 100644 index 0000000000..c996216dd8 --- /dev/null +++ b/base/src/org/compiere/model/MInOutLineConfirm.java @@ -0,0 +1,191 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Ship Confirmation Line Model + * + * @author Jorg Janke + * @version $Id: MInOutLineConfirm.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MInOutLineConfirm extends X_M_InOutLineConfirm +{ + /** + * Standard Constructor + * @param ctx context + * @param M_InOutLineConfirm_ID id + * @param trxName transaction + */ + public MInOutLineConfirm (Properties ctx, int M_InOutLineConfirm_ID, String trxName) + { + super (ctx, M_InOutLineConfirm_ID, trxName); + if (M_InOutLineConfirm_ID == 0) + { + // setM_InOutConfirm_ID (0); + // setM_InOutLine_ID (0); + // setTargetQty (Env.ZERO); + // setConfirmedQty (Env.ZERO); + setDifferenceQty(Env.ZERO); + setScrappedQty(Env.ZERO); + setProcessed (false); + } + } // MInOutLineConfirm + + /** + * Load Construvtor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MInOutLineConfirm (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MInOutLineConfirm + + /** + * Parent Construvtor + * @param header parent + */ + public MInOutLineConfirm (MInOutConfirm header) + { + this (header.getCtx(), 0, header.get_TrxName()); + setClientOrg(header); + setM_InOutConfirm_ID(header.getM_InOutConfirm_ID()); + } // MInOutLineConfirm + + /** Ship Line */ + private MInOutLine m_line = null; + + /** + * Set Shipment Line + * @param line shipment line + */ + public void setInOutLine (MInOutLine line) + { + setM_InOutLine_ID(line.getM_InOutLine_ID()); + setTargetQty(line.getMovementQty()); // Confirmations in Storage UOM + setConfirmedQty (getTargetQty()); // suggestion + m_line = line; + } // setInOutLine + + /** + * Get Shipment Line + * @return line + */ + public MInOutLine getLine() + { + if (m_line == null) + m_line = new MInOutLine (getCtx(), getM_InOutLine_ID(), get_TrxName()); + return m_line; + } // getLine + + + /** + * Process Confirmation Line. + * - Update InOut Line + * @param isSOTrx sales order + * @param confirmType type + * @return success + */ + public boolean processLine (boolean isSOTrx, String confirmType) + { + MInOutLine line = getLine(); + + // Customer + if (MInOutConfirm.CONFIRMTYPE_CustomerConfirmation.equals(confirmType)) + { + line.setConfirmedQty(getConfirmedQty()); + } + + // Drop Ship + else if (MInOutConfirm.CONFIRMTYPE_DropShipConfirm.equals(confirmType)) + { + + } + + // Pick or QA + else if (MInOutConfirm.CONFIRMTYPE_PickQAConfirm.equals(confirmType)) + { + line.setTargetQty(getTargetQty()); + line.setMovementQty(getConfirmedQty()); // Entered NOT changed + line.setPickedQty(getConfirmedQty()); + // + line.setScrappedQty(getScrappedQty()); + } + + // Ship or Receipt + else if (MInOutConfirm.CONFIRMTYPE_ShipReceiptConfirm.equals(confirmType)) + { + line.setTargetQty(getTargetQty()); + BigDecimal qty = getConfirmedQty(); + if (!isSOTrx) // In PO, we have the responsibility for scapped + qty = qty.add(getScrappedQty()); + line.setMovementQty(qty); // Entered NOT changed + // + line.setScrappedQty(getScrappedQty()); + } + // Vendor + else if (MInOutConfirm.CONFIRMTYPE_VendorConfirmation.equals(confirmType)) + { + line.setConfirmedQty(getConfirmedQty()); + } + + return line.save(get_TrxName()); + } // processConfirmation + + /** + * Is Fully Confirmed + * @return true if Target = Confirmed qty + */ + public boolean isFullyConfirmed() + { + return getTargetQty().compareTo(getConfirmedQty()) == 0; + } // isFullyConfirmed + + + /** + * Before Delete - do not delete + * @return false + */ + protected boolean beforeDelete () + { + log.saveError("Error", Msg.getMsg(getCtx(), "CannotDelete")); + return false; + } // beforeDelete + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Calculate Difference = Target - Confirmed - Scrapped + BigDecimal difference = getTargetQty(); + difference = difference.subtract(getConfirmedQty()); + difference = difference.subtract(getScrappedQty()); + setDifferenceQty(difference); + // + return true; + } // beforeSave + +} // MInOutLineConfirm diff --git a/base/src/org/compiere/model/MInOutLineMA.java b/base/src/org/compiere/model/MInOutLineMA.java new file mode 100644 index 0000000000..ec69a27761 --- /dev/null +++ b/base/src/org/compiere/model/MInOutLineMA.java @@ -0,0 +1,149 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Shipment Material Allocation + * + * @author Jorg Janke + * @version $Id: MInOutLineMA.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MInOutLineMA extends X_M_InOutLineMA +{ + /** + * Get Material Allocations for Line + * @param ctx context + * @param M_InOutLine_ID line + * @param trxName trx + * @return allocations + */ + public static MInOutLineMA[] get (Properties ctx, int M_InOutLine_ID, String trxName) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_InOutLineMA WHERE M_InOutLine_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_InOutLine_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + list.add (new MInOutLineMA (ctx, rs, trxName)); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + MInOutLineMA[] retValue = new MInOutLineMA[list.size ()]; + list.toArray (retValue); + return retValue; + } // get + + /** + * Delete all Material Allocation for InOut + * @param M_InOut_ID shipment + * @param trxName transaction + * @return number of rows deleted or -1 for error + */ + public static int deleteInOutMA (int M_InOut_ID, String trxName) + { + String sql = "DELETE FROM M_InOutLineMA ma WHERE EXISTS " + + "(SELECT * FROM M_InOutLine l WHERE l.M_InOutLine_ID=ma.M_InOutLine_ID" + + " AND M_InOut_ID=" + M_InOut_ID + ")"; + return DB.executeUpdate(sql, trxName); + } // deleteInOutMA + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MInOutLineMA.class); + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_InOutLineMA_ID ignored + * @param trxName trx + */ + public MInOutLineMA (Properties ctx, int M_InOutLineMA_ID, String trxName) + { + super (ctx, M_InOutLineMA_ID, trxName); + if (M_InOutLineMA_ID != 0) + throw new IllegalArgumentException("Multi-Key"); + } // MInOutLineMA + + /** + * Load Cosntructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MInOutLineMA (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MInOutLineMA + + /** + * Parent Constructor + * @param parent parent + * @param M_AttributeSetInstance_ID asi + * @param MovementQty qty + */ + public MInOutLineMA (MInOutLine parent, int M_AttributeSetInstance_ID, BigDecimal MovementQty) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setM_InOutLine_ID(parent.getM_InOutLine_ID()); + // + setM_AttributeSetInstance_ID(M_AttributeSetInstance_ID); + setMovementQty(MovementQty); + } // MInOutLineMA + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MInOutLineMA["); + sb.append("M_InOutLine_ID=").append(getM_InOutLine_ID()) + .append(",M_AttributeSetInstance_ID=").append(getM_AttributeSetInstance_ID()) + .append(", Qty=").append(getMovementQty()) + .append ("]"); + return sb.toString (); + } // toString + +} // MInOutLineMA diff --git a/base/src/org/compiere/model/MIndex.java b/base/src/org/compiere/model/MIndex.java new file mode 100644 index 0000000000..aae1c0376f --- /dev/null +++ b/base/src/org/compiere/model/MIndex.java @@ -0,0 +1,296 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Text Index Model + * + * @author Yves Sandfort + * @version $Id: MIndex.java,v 1.6 2006/08/09 16:38:25 jjanke Exp $ + */ +public class MIndex extends X_K_Index +{ + /** + * Standard Constructor + * @param ctx context + * @param K_Index_ID index + * @param trxName transaction + */ + public MIndex (Properties ctx, int K_Index_ID, String trxName) + { + super (ctx, K_Index_ID, trxName); + } // MIndex + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MIndex (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MIndex + + /** + * cleanUp + * @param trxName + * @param AD_Client_ID + * @param AD_Table_ID + * @param Record_ID + * @return Number of records cleaned + */ + public static int cleanUp (String trxName, int AD_Client_ID, int AD_Table_ID, int Record_ID) + { + StringBuffer sb = new StringBuffer ("DELETE FROM K_Index " + + "WHERE AD_Client_ID=" + AD_Client_ID + " AND " + + "AD_Table_ID=" + AD_Table_ID + " AND " + + "Record_ID=" + Record_ID); + int no = DB.executeUpdate(sb.toString(), trxName); + return no; + } + + /** + * Set Keyword & standardize + * @param Keyword + */ + public void setKeyword (String Keyword) + { + String kw = standardizeKeyword(Keyword); + if (kw == null) + kw = "?"; + super.setKeyword (kw); + } // setKeyword + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (newRecord || is_ValueChanged("Keyword")) + setKeyword(getKeyword()); + if (getKeyword().equals("?")) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "Keyword")); + return false; + } + return true; + } // beforeSave + + /** + * Index/Keyword a StringBuffer + * @param thisText The String to convert into Hash + * @return Hashtable with String + * + */ + public static Hashtable indexStringBuffer(StringBuffer thisText) + { + return indexString(thisText.toString()); + } + + /** + * Index/Keyword a String + * @param thisText The String to convert into Hash + * @return Hashtable with String + * + */ + public static Hashtable indexString(String thisText) + { + thisText = removeHTML(thisText); + if (thisText!=null) { + String [] keywords = thisText.toUpperCase().split("\\t|\\p{Punct}|\\p{Space}"); + Hashtable keyhash = new Hashtable(keywords.length); + int currentPos = 0; + for (int i=0;i=2) + { + if (!keyhash.contains(keywords[i])) + { + int startExcerpt = thisText.toUpperCase().indexOf(keywords[i],currentPos); + if (startExcerpt>50) + startExcerpt = startExcerpt - 50; + if (startExcerpt>thisText.length () && startExcerpt>50 && thisText.length()>50) + startExcerpt = thisText.length()-50; + int endExcerpt = thisText.toUpperCase().indexOf(keywords[i],currentPos) + keywords[i].length(); + if (endExcerpt>currentPos) + currentPos = endExcerpt; + if (endExcerptthisText.length()) + endExcerpt = thisText.length (); + thisExcerpt = thisText.substring(startExcerpt,endExcerpt); + keyhash.put(keywords[i],thisExcerpt); + } + } + } + return keyhash; + } else { + return null; + } + + } + + /** + * runIndex + * @param thisText The text to be indexed + * @param ctx context + * @param trxName Transaction if needed + * @param tableID Table ID + * @param recordID Record ID + * @param CMWebProjectID Web Project ID + * @param sourceUpdated Update Date of Source + * @return true if successfully indexed + */ + public static boolean runIndex(String thisText, Properties ctx, String trxName, + int tableID, int recordID, int CMWebProjectID, Timestamp sourceUpdated) + { + if (thisText!=null) { + Hashtable keyHash = indexString(thisText); + for (Enumeration e=keyHash.keys(); e.hasMoreElements();) { + String name = (String)e.nextElement(); + String value = (String)keyHash.get(name); + MIndex thisIndex = new MIndex(ctx, 0, trxName); + thisIndex.setAD_Table_ID(tableID); + if (CMWebProjectID>0) + thisIndex.setCM_WebProject_ID(CMWebProjectID); + thisIndex.setExcerpt(value); + thisIndex.setKeyword(name); + thisIndex.setRecord_ID(recordID); + thisIndex.setSourceUpdated(sourceUpdated); + thisIndex.save(); + } + return true; + } else { + return false; + } + } + + + /** + * reIndex Document + * @param runCleanUp clean old records + * @param toBeIndexed Array of Strings to be indexed + * @param ctx Context + * @param AD_Client_ID Client + * @param AD_Table_ID Table + * @param Record_ID Record + * @param CM_WebProject_ID Web Project + * @param lastUpdated Date of last update + */ + public static void reIndex(boolean runCleanUp, String[] toBeIndexed, Properties ctx, + int AD_Client_ID, int AD_Table_ID, int Record_ID, int CM_WebProject_ID, Timestamp lastUpdated) + { + String trxName = "ReIndex_" + AD_Table_ID + "_" + Record_ID; + try { + if (!runCleanUp) + { + MIndex.cleanUp(trxName, AD_Client_ID, AD_Table_ID, Record_ID); + } + for (int i=0;i\\s]+))?)+\\s*|\\s*)/?>", " "); + retValue = retValue.replaceAll ("= '!' && c <= 'Z') // includes Digits + return String.valueOf(c); + // + int index = Arrays.binarySearch(s_char, c); + if (index < 0) + return String.valueOf(c); + return s_string[index]; + } // standardizeKeyword + + /** + * Foreign upper case characters ascending for binary search. + * Make sure that you use native2ascii to convert + * (note Eclipse, etc. actually save the content as utf-8 - so the command is + * native2ascii -encoding utf-8 filename) + */ + private static final char[] s_char + = new char[] { + '\u00c4', '\u00d6', '\u00dc', '\u00df' // ÄÖÜß - German stuff + }; + + /** + * Foreign character string linked to s_char position + */ + private static final String[] s_string + = new String[] { + "AE", "OE", "UE", "SS" + }; + +} // MIndex diff --git a/base/src/org/compiere/model/MIndexStop.java b/base/src/org/compiere/model/MIndexStop.java new file mode 100644 index 0000000000..23ea2169b2 --- /dev/null +++ b/base/src/org/compiere/model/MIndexStop.java @@ -0,0 +1,82 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Text Search Stop Keyword Model + * + * @author Jorg Janke + * @version $Id: MIndexStop.java,v 1.3 2006/08/09 16:38:25 jjanke Exp $ + */ +public class MIndexStop extends X_K_IndexStop +{ + /** + * Standard Constructor + * @param ctx context + * @param K_IndexStop_ID id + * @param trxName transaction + */ + public MIndexStop (Properties ctx, int K_IndexStop_ID, String trxName) + { + super (ctx, K_IndexStop_ID, trxName); + } // MIndexStop + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MIndexStop (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MIndexStop + + /** + * Set Keyword & standardize + * @param Keyword + */ + public void setKeyword (String Keyword) + { + String kw = MIndex.standardizeKeyword(Keyword); + if (kw == null) + kw = "?"; + super.setKeyword (kw); + } // setKeyword + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (newRecord || is_ValueChanged("Keyword")) + setKeyword(getKeyword()); + if (getKeyword().equals("?")) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "Keyword")); + return false; + } + return true; + } // beforeSave + +} // MIndexStop diff --git a/base/src/org/compiere/model/MInfoColumn.java b/base/src/org/compiere/model/MInfoColumn.java new file mode 100644 index 0000000000..bd825d1616 --- /dev/null +++ b/base/src/org/compiere/model/MInfoColumn.java @@ -0,0 +1,52 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Info Window Column Model + * + * @author Jorg Janke + * @version $Id: MInfoColumn.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MInfoColumn extends X_AD_InfoColumn +{ + /** + * Stanfard Constructor + * @param ctx context + * @param AD_InfoColumn_ID id + * @param trxName transaction + */ + public MInfoColumn (Properties ctx, int AD_InfoColumn_ID, String trxName) + { + super (ctx, AD_InfoColumn_ID, trxName); + } // MInfoColumn + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MInfoColumn (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MInfoColumn + +} // MInfoColumn diff --git a/base/src/org/compiere/model/MInfoWindow.java b/base/src/org/compiere/model/MInfoWindow.java new file mode 100644 index 0000000000..532fb34cf6 --- /dev/null +++ b/base/src/org/compiere/model/MInfoWindow.java @@ -0,0 +1,52 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Info Window Model + * + * @author Jorg Janke + * @version $Id: MInfoWindow.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MInfoWindow extends X_AD_InfoWindow +{ + /** + * Standard Constructor + * @param ctx context + * @param AD_InfoWindow_ID id + * @param trxName transaction + */ + public MInfoWindow (Properties ctx, int AD_InfoWindow_ID, String trxName) + { + super (ctx, AD_InfoWindow_ID, trxName); + } // MInfoWindow + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MInfoWindow (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MInfoWindow + +} // MInfoWindow diff --git a/base/src/org/compiere/model/MInterestArea.java b/base/src/org/compiere/model/MInterestArea.java new file mode 100644 index 0000000000..f43e2a47f5 --- /dev/null +++ b/base/src/org/compiere/model/MInterestArea.java @@ -0,0 +1,166 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import org.compiere.util.*; + +/** + * Interest Area. + * Note: if model is changed, update + * org.compiere.wstore.Info.getInterests() + * manually + * + * @author Jorg Janke + * @version $Id: MInterestArea.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MInterestArea extends X_R_InterestArea +{ + /** + * Get MInterestArea from Cache + * @param ctx context + * @param R_InterestArea_ID id + * @return MInterestArea + */ + public static MInterestArea get (Properties ctx, int R_InterestArea_ID) + { + Integer key = new Integer (R_InterestArea_ID); + MInterestArea retValue = (MInterestArea) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MInterestArea (ctx, R_InterestArea_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("R_InterestArea", 5); + + + /** + * Constructor + * @param ctx context + * @param R_InterestArea_ID interest area + * @param trxName transaction + */ + public MInterestArea (Properties ctx, int R_InterestArea_ID, String trxName) + { + super (ctx, R_InterestArea_ID, trxName); + if (R_InterestArea_ID == 0) + { + // setName (null); + // setR_InterestArea_ID (0); + } + } // MInterestArea + + /** + * Loader Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MInterestArea (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MInterestArea + + + /** + * String representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MInterestArea[") + .append (get_ID()).append(" - ").append(getName()) + .append ("]"); + return sb.toString (); + } + + /*************************************************************************/ + + private int m_AD_User_ID = -1; + private MContactInterest m_ci = null; + + /** + * Set Subscription info "constructor". + * Create inactive Subscription + * @param AD_User_ID contact + */ + public void setSubscriptionInfo (int AD_User_ID) + { + m_AD_User_ID = AD_User_ID; + m_ci = MContactInterest.get(getCtx(), getR_InterestArea_ID(), AD_User_ID, + false, get_TrxName()); + } // setSubscription + + /** + * Set AD_User_ID + * @param AD_User_ID user + */ + public void setAD_User_ID (int AD_User_ID) + { + m_AD_User_ID = AD_User_ID; + } + + /** + * Get AD_User_ID + * @return user + */ + public int getAD_User_ID () + { + return m_AD_User_ID; + } + + /** + * Get Subscribe Date + * @return subscribe date + */ + public Timestamp getSubscribeDate () + { + if (m_ci != null) + return m_ci.getSubscribeDate(); + return null; + } + + /** + * Get Opt Out Date + * @return opt-out date + */ + public Timestamp getOptOutDate () + { + if (m_ci != null) + return m_ci.getOptOutDate(); + return null; + } + + /** + * Is Subscribed + * @return true if sunscribed + */ + public boolean isSubscribed() + { + if (m_AD_User_ID <= 0 || m_ci == null) + return false; + // We have a BPartner Contact + return m_ci.isSubscribed(); + } // isSubscribed + +} // MInterestArea diff --git a/base/src/org/compiere/model/MInventory.java b/base/src/org/compiere/model/MInventory.java new file mode 100644 index 0000000000..6f700f7ec9 --- /dev/null +++ b/base/src/org/compiere/model/MInventory.java @@ -0,0 +1,846 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Physical Inventory Model + * + * @author Jorg Janke + * @version $Id: MInventory.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MInventory extends X_M_Inventory implements DocAction +{ + /** + * Get Inventory from Cache + * @param ctx context + * @param M_Inventory_ID id + * @return MInventory + */ + public static MInventory get (Properties ctx, int M_Inventory_ID) + { + Integer key = new Integer (M_Inventory_ID); + MInventory retValue = (MInventory) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MInventory (ctx, M_Inventory_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("M_Inventory", 5, 5); + + + /** + * Standard Constructor + * @param ctx context + * @param M_Inventory_ID id + * @param trxName transaction + */ + public MInventory (Properties ctx, int M_Inventory_ID, String trxName) + { + super (ctx, M_Inventory_ID, trxName); + if (M_Inventory_ID == 0) + { + // setName (null); + // setM_Warehouse_ID (0); // FK + setMovementDate (new Timestamp(System.currentTimeMillis())); + setDocAction (DOCACTION_Complete); // CO + setDocStatus (DOCSTATUS_Drafted); // DR + setIsApproved (false); + setMovementDate (new Timestamp(System.currentTimeMillis())); // @#Date@ + setPosted (false); + setProcessed (false); + } + } // MInventory + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MInventory (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MInventory + + /** + * Warehouse Constructor + * @param wh warehouse + */ + public MInventory (MWarehouse wh) + { + this (wh.getCtx(), 0, wh.get_TrxName()); + setClientOrg(wh); + setM_Warehouse_ID(wh.getM_Warehouse_ID()); + } // MInventory + + + /** Lines */ + private MInventoryLine[] m_lines = null; + + /** + * Get Lines + * @param requery requery + * @return array of lines + */ + public MInventoryLine[] getLines (boolean requery) + { + if (m_lines != null && !requery) + return m_lines; + // + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_InventoryLine WHERE M_Inventory_ID=? ORDER BY Line"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getM_Inventory_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MInventoryLine (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } catch (Exception e) + { + pstmt = null; + } + + m_lines = new MInventoryLine[list.size ()]; + list.toArray (m_lines); + return m_lines; + } // getLines + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * Overwrite Client/Org - from Import. + * @param AD_Client_ID client + * @param AD_Org_ID org + */ + public void setClientOrg (int AD_Client_ID, int AD_Org_ID) + { + super.setClientOrg(AD_Client_ID, AD_Org_ID); + } // setClientOrg + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MInventory["); + sb.append (get_ID()) + .append ("-").append (getDocumentNo()) + .append (",M_Warehouse_ID=").append(getM_Warehouse_ID()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Get Document Info + * @return document info (untranslated) + */ + public String getDocumentInfo() + { + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + return dt.getName() + " " + getDocumentNo(); + } // getDocumentInfo + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + // ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.INVOICE, getC_Invoice_ID()); + // if (re == null) + return null; + // return re.getPDF(file); + } // createPDF + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getC_DocType_ID() == 0) + { + MDocType types[] = MDocType.getOfDocBaseType(getCtx(), MDocType.DOCBASETYPE_MaterialPhysicalInventory); + if (types.length > 0) // get first + setC_DocType_ID(types[0].getC_DocType_ID()); + else + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@NotFound@ @C_DocType_ID@")); + return false; + } + } + return true; + } // beforeSave + + + /** + * Set Processed. + * Propergate to Lines/Taxes + * @param processed processed + */ + public void setProcessed (boolean processed) + { + super.setProcessed (processed); + if (get_ID() == 0) + return; + String sql = "UPDATE M_InventoryLine SET Processed='" + + (processed ? "Y" : "N") + + "' WHERE M_Inventory_ID=" + getM_Inventory_ID(); + int noLine = DB.executeUpdate(sql, get_TrxName()); + m_lines = null; + log.fine("Processed=" + processed + " - Lines=" + noLine); + } // setProcessed + + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // processIt + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info(toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info(toString()); + setDocAction(DOCACTION_Prepare); + return true; + } // invalidateIt + + /** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + + // Std Period open? + if (!MPeriod.isOpen(getCtx(), getMovementDate(), MDocType.DOCBASETYPE_MaterialPhysicalInventory)) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + MInventoryLine[] lines = getLines(false); + if (lines.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + + // TODO: Add up Amounts + // setApprovalAmt(); + + + m_justPrepared = true; + if (!DOCACTION_Complete.equals(getDocAction())) + setDocAction(DOCACTION_Complete); + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info(toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info(toString()); + setIsApproved(false); + return true; + } // rejectIt + + /** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + // Implicit Approval + if (!isApproved()) + approveIt(); + log.info(toString()); + // + MInventoryLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MInventoryLine line = lines[i]; + if (!line.isActive()) + continue; + + MTransaction trx = null; + if (line.getM_AttributeSetInstance_ID() == 0) + { + BigDecimal qtyDiff = line.getQtyInternalUse().negate(); + if (qtyDiff.signum() == 0) + qtyDiff = line.getQtyCount().subtract(line.getQtyBook()); + // + if (qtyDiff.signum() > 0) + { + // Storage + MStorage storage = MStorage.get(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), 0, get_TrxName()); + if (storage == null) + storage = MStorage.getCreate(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), 0, get_TrxName()); + BigDecimal qtyNew = storage.getQtyOnHand().add(qtyDiff); + log.fine("Diff=" + qtyDiff + + " - OnHand=" + storage.getQtyOnHand() + "->" + qtyNew); + storage.setQtyOnHand(qtyNew); + storage.setDateLastInventory(getMovementDate()); + if (!storage.save(get_TrxName())) + { + m_processMsg = "Storage not updated(1)"; + return DocAction.STATUS_Invalid; + } + log.fine(storage.toString()); + // Transaction + trx = new MTransaction (getCtx(), line.getAD_Org_ID(), + MTransaction.MOVEMENTTYPE_InventoryIn, + line.getM_Locator_ID(), line.getM_Product_ID(), 0, + qtyDiff, getMovementDate(), get_TrxName()); + trx.setM_InventoryLine_ID(line.getM_InventoryLine_ID()); + if (!trx.save()) + { + m_processMsg = "Transaction not inserted(1)"; + return DocAction.STATUS_Invalid; + } + } + else // negative qty + { + MInventoryLineMA mas[] = MInventoryLineMA.get(getCtx(), + line.getM_InventoryLine_ID(), get_TrxName()); + for (int j = 0; j < mas.length; j++) + { + MInventoryLineMA ma = mas[j]; + // Storage + MStorage storage = MStorage.get(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); + if (storage == null) + storage = MStorage.getCreate(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); + // + BigDecimal maxDiff = qtyDiff; + if (maxDiff.signum() < 0 + && ma.getMovementQty().compareTo(maxDiff.negate()) < 0) + maxDiff = ma.getMovementQty().negate(); + BigDecimal qtyNew = ma.getMovementQty().add(maxDiff); // Storage+Diff + log.fine("MA Qty=" + ma.getMovementQty() + + ",Diff=" + qtyDiff + "|" + maxDiff + + " - OnHand=" + storage.getQtyOnHand() + "->" + qtyNew + + " {" + ma.getM_AttributeSetInstance_ID() + "}"); + // + storage.setQtyOnHand(qtyNew); + storage.setDateLastInventory(getMovementDate()); + if (!storage.save(get_TrxName())) + { + m_processMsg = "Storage not updated (MA)"; + return DocAction.STATUS_Invalid; + } + log.fine(storage.toString()); + + // Transaction + trx = new MTransaction (getCtx(), line.getAD_Org_ID(), + MTransaction.MOVEMENTTYPE_InventoryIn, + line.getM_Locator_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), + maxDiff, getMovementDate(), get_TrxName()); + trx.setM_InventoryLine_ID(line.getM_InventoryLine_ID()); + if (!trx.save()) + { + m_processMsg = "Transaction not inserted (MA)"; + return DocAction.STATUS_Invalid; + } + // + qtyDiff = qtyDiff.subtract(maxDiff); + if (qtyDiff.signum() == 0) + break; + } + } // negative qty + } + + // Fallback + if (trx == null) + { + // Storage + MStorage storage = MStorage.get(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), get_TrxName()); + if (storage == null) + storage = MStorage.getCreate(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), get_TrxName()); + // + BigDecimal qtyDiff = line.getQtyInternalUse().negate(); + if (Env.ZERO.compareTo(qtyDiff) == 0) + qtyDiff = line.getQtyCount().subtract(line.getQtyBook()); + BigDecimal qtyNew = storage.getQtyOnHand().add(qtyDiff); + log.fine("Count=" + line.getQtyCount() + + ",Book=" + line.getQtyBook() + ", Difference=" + qtyDiff + + " - OnHand=" + storage.getQtyOnHand() + "->" + qtyNew); + // + storage.setQtyOnHand(qtyNew); + storage.setDateLastInventory(getMovementDate()); + if (!storage.save(get_TrxName())) + { + m_processMsg = "Storage not updated(2)"; + return DocAction.STATUS_Invalid; + } + log.fine(storage.toString()); + + // Transaction + trx = new MTransaction (getCtx(), line.getAD_Org_ID(), + MTransaction.MOVEMENTTYPE_InventoryIn, + line.getM_Locator_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), + qtyDiff, getMovementDate(), get_TrxName()); + trx.setM_InventoryLine_ID(line.getM_InventoryLine_ID()); + if (!trx.save()) + { + m_processMsg = "Transaction not inserted(2)"; + return DocAction.STATUS_Invalid; + } + } // Fallback + + } // for all lines + + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + m_processMsg = valid; + return DocAction.STATUS_Invalid; + } + // + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + + /** + * Check Material Policy. + * (NOT USED) + * Sets line ASI + */ + private void checkMaterialPolicy() + { + int no = MInventoryLineMA.deleteInventoryMA(getM_Inventory_ID(), get_TrxName()); + if (no > 0) + log.config("Delete old #" + no); + MInventoryLine[] lines = getLines(false); + + // Incoming Trx + MClient client = MClient.get(getCtx()); + + // Check Lines + for (int i = 0; i < lines.length; i++) + { + MInventoryLine line = lines[i]; + boolean needSave = false; + + // Attribute Set Instance + if (line.getM_AttributeSetInstance_ID() == 0) + { + MProduct product = MProduct.get(getCtx(), line.getM_Product_ID()); + BigDecimal qtyDiff = line.getQtyInternalUse().negate(); + if (Env.ZERO.compareTo(qtyDiff) == 0) + qtyDiff = line.getQtyCount().subtract(line.getQtyBook()); + log.fine("Count=" + line.getQtyCount() + + ",Book=" + line.getQtyBook() + ", Difference=" + qtyDiff); + if (qtyDiff.signum() > 0) // In + { + MAttributeSetInstance asi = new MAttributeSetInstance(getCtx(), 0, get_TrxName()); + asi.setClientOrg(getAD_Client_ID(), 0); + asi.setM_AttributeSet_ID(product.getM_AttributeSet_ID()); + if (asi.save()) + { + line.setM_AttributeSetInstance_ID(asi.getM_AttributeSetInstance_ID()); + needSave = true; + } + } + else // Outgoing Trx + { + MProductCategory pc = MProductCategory.get(getCtx(), product.getM_Product_Category_ID()); + String MMPolicy = pc.getMMPolicy(); + if (MMPolicy == null || MMPolicy.length() == 0) + MMPolicy = client.getMMPolicy(); + // + MStorage[] storages = MStorage.getAllWithASI(getCtx(), + line.getM_Product_ID(), line.getM_Locator_ID(), + MClient.MMPOLICY_FiFo.equals(MMPolicy), get_TrxName()); + BigDecimal qtyToDeliver = qtyDiff.negate(); + for (int ii = 0; ii < storages.length; ii++) + { + MStorage storage = storages[ii]; + if (ii == 0) + { + if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) + { + line.setM_AttributeSetInstance_ID(storage.getM_AttributeSetInstance_ID()); + needSave = true; + log.config("Direct - " + line); + qtyToDeliver = Env.ZERO; + } + else + { + log.config("Split - " + line); + MInventoryLineMA ma = new MInventoryLineMA (line, + storage.getM_AttributeSetInstance_ID(), + storage.getQtyOnHand().negate()); + if (!ma.save()) + ; + qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); + log.fine("#" + ii + ": " + ma + ", QtyToDeliver=" + qtyToDeliver); + } + } + else // create addl material allocation + { + MInventoryLineMA ma = new MInventoryLineMA (line, + storage.getM_AttributeSetInstance_ID(), + qtyToDeliver.negate()); + if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) + qtyToDeliver = Env.ZERO; + else + { + ma.setMovementQty(storage.getQtyOnHand().negate()); + qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); + } + if (!ma.save()) + ; + log.fine("#" + ii + ": " + ma + ", QtyToDeliver=" + qtyToDeliver); + } + if (qtyToDeliver.signum() == 0) + break; + } // for all storages + + // No AttributeSetInstance found for remainder + if (qtyToDeliver.signum() != 0) + { + MInventoryLineMA ma = new MInventoryLineMA (line, + 0, qtyToDeliver.negate()); + if (!ma.save()) + ; + log.fine("##: " + ma); + } + } // outgoing Trx + } // attributeSetInstance + + if (needSave && !line.save()) + log.severe("NOT saved " + line); + } // for all lines + + } // checkMaterialPolicy + + /** + * Void Document. + * @return false + */ + public boolean voidIt() + { + log.info(toString()); + if (DOCSTATUS_Closed.equals(getDocStatus()) + || DOCSTATUS_Reversed.equals(getDocStatus()) + || DOCSTATUS_Voided.equals(getDocStatus())) + { + m_processMsg = "Document Closed: " + getDocStatus(); + return false; + } + + // Not Processed + if (DOCSTATUS_Drafted.equals(getDocStatus()) + || DOCSTATUS_Invalid.equals(getDocStatus()) + || DOCSTATUS_InProgress.equals(getDocStatus()) + || DOCSTATUS_Approved.equals(getDocStatus()) + || DOCSTATUS_NotApproved.equals(getDocStatus()) ) + { + // Set lines to 0 + MInventoryLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MInventoryLine line = lines[i]; + BigDecimal oldCount = line.getQtyCount(); + BigDecimal oldInternal = line.getQtyInternalUse(); + if (oldCount.compareTo(line.getQtyBook()) != 0 + || oldInternal.signum() != 0) + { + line.setQtyInternalUse(Env.ZERO); + line.setQtyCount(line.getQtyBook()); + line.addDescription("Void (" + oldCount + "/" + oldInternal + ")"); + line.save(get_TrxName()); + } + } + } + else + { + return reverseCorrectIt(); + } + + setProcessed(true); + setDocAction(DOCACTION_None); + return true; + } // voidIt + + /** + * Close Document. + * @return true if success + */ + public boolean closeIt() + { + log.info(toString()); + + setDocAction(DOCACTION_None); + return true; + } // closeIt + + /** + * Reverse Correction + * @return false + */ + public boolean reverseCorrectIt() + { + log.info(toString()); + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + if (!MPeriod.isOpen(getCtx(), getMovementDate(), dt.getDocBaseType())) + { + m_processMsg = "@PeriodClosed@"; + return false; + } + + // Deep Copy + MInventory reversal = new MInventory(getCtx(), 0, get_TrxName()); + copyValues(this, reversal, getAD_Client_ID(), getAD_Org_ID()); + reversal.setDocStatus(DOCSTATUS_Drafted); + reversal.setDocAction(DOCACTION_Complete); + reversal.setIsApproved (false); + reversal.setPosted(false); + reversal.setProcessed(false); + reversal.addDescription("{->" + getDocumentNo() + ")"); + if (!reversal.save()) + { + m_processMsg = "Could not create Inventory Reversal"; + return false; + } + + // Reverse Line Qty + MInventoryLine[] oLines = getLines(true); + for (int i = 0; i < oLines.length; i++) + { + MInventoryLine oLine = oLines[i]; + MInventoryLine rLine = new MInventoryLine(getCtx(), 0, get_TrxName()); + copyValues(oLine, rLine, oLine.getAD_Client_ID(), oLine.getAD_Org_ID()); + rLine.setM_Inventory_ID(reversal.getM_Inventory_ID()); + rLine.setParent(reversal); + // + rLine.setQtyBook (oLine.getQtyCount()); // switch + rLine.setQtyCount (oLine.getQtyBook()); + rLine.setQtyInternalUse (oLine.getQtyInternalUse().negate()); + if (!rLine.save()) + { + m_processMsg = "Could not create Inventory Reversal Line"; + return false; + } + } + // + if (!reversal.processIt(DocAction.ACTION_Complete)) + { + m_processMsg = "Reversal ERROR: " + reversal.getProcessMsg(); + return false; + } + reversal.closeIt(); + reversal.setDocStatus(DOCSTATUS_Reversed); + reversal.setDocAction(DOCACTION_None); + reversal.save(); + m_processMsg = reversal.getDocumentNo(); + + // Update Reversed (this) + addDescription("(" + reversal.getDocumentNo() + "<-)"); + setProcessed(true); + setDocStatus(DOCSTATUS_Reversed); // may come from void + setDocAction(DOCACTION_None); + + return true; + } // reverseCorrectionIt + + /** + * Reverse Accrual + * @return false + */ + public boolean reverseAccrualIt() + { + log.info(toString()); + return false; + } // reverseAccrualIt + + /** + * Re-activate + * @return false + */ + public boolean reActivateIt() + { + log.info(toString()); + return false; + } // reActivateIt + + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getDocumentNo()); + // : Total Lines = 123.00 (#1) + sb.append(": ") + .append(Msg.translate(getCtx(),"ApprovalAmt")).append("=").append(getApprovalAmt()) + .append(" (#").append(getLines(false).length).append(")"); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner (Responsible) + * @return AD_User_ID + */ + public int getDoc_User_ID() + { + return getUpdatedBy(); + } // getDoc_User_ID + + /** + * Get Document Currency + * @return C_Currency_ID + */ + public int getC_Currency_ID() + { + // MPriceList pl = MPriceList.get(getCtx(), getM_PriceList_ID()); + // return pl.getC_Currency_ID(); + return 0; + } // getC_Currency_ID + +} // MInventory diff --git a/base/src/org/compiere/model/MInventoryLine.java b/base/src/org/compiere/model/MInventoryLine.java new file mode 100644 index 0000000000..fdaea9019a --- /dev/null +++ b/base/src/org/compiere/model/MInventoryLine.java @@ -0,0 +1,415 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Physical Inventory Line Model + * + * @author Jorg Janke + * @version $Id: MInventoryLine.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MInventoryLine extends X_M_InventoryLine +{ + /** + * Get Inventory Line with parameters + * @param inventory inventory + * @param M_Locator_ID locator + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID asi + * @return line or null + */ + public static MInventoryLine get (MInventory inventory, + int M_Locator_ID, int M_Product_ID, int M_AttributeSetInstance_ID) + { + MInventoryLine retValue = null; + String sql = "SELECT * FROM M_InventoryLine " + + "WHERE M_Inventory_ID=? AND M_Locator_ID=?" + + " AND M_Product_ID=? AND M_AttributeSetInstance_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, inventory.get_TrxName()); + pstmt.setInt (1, inventory.getM_Inventory_ID()); + pstmt.setInt(2, M_Locator_ID); + pstmt.setInt(3, M_Product_ID); + pstmt.setInt(4, M_AttributeSetInstance_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = new MInventoryLine (inventory.getCtx(), rs, inventory.get_TrxName()); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + return retValue; + } // get + + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MInventoryLine.class); + + + /************************************************************************** + * Default Constructor + * @param ctx context + * @param M_InventoryLine_ID line + * @param trxName transaction + */ + public MInventoryLine (Properties ctx, int M_InventoryLine_ID, String trxName) + { + super (ctx, M_InventoryLine_ID, trxName); + if (M_InventoryLine_ID == 0) + { + // setM_Inventory_ID (0); // Parent + // setM_InventoryLine_ID (0); // PK + // setM_Locator_ID (0); // FK + setLine(0); + // setM_Product_ID (0); // FK + setM_AttributeSetInstance_ID(0); // FK + setInventoryType (INVENTORYTYPE_InventoryDifference); + setQtyBook (Env.ZERO); + setQtyCount (Env.ZERO); + setProcessed(false); + } + } // MInventoryLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MInventoryLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MInventoryLine + + /** + * Detail Constructor. + * Locator/Product/AttributeSetInstance must be unique + * @param inventory parent + * @param M_Locator_ID locator + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID instance + * @param QtyBook book value + * @param QtyCount count value + */ + public MInventoryLine (MInventory inventory, + int M_Locator_ID, int M_Product_ID, int M_AttributeSetInstance_ID, + BigDecimal QtyBook, BigDecimal QtyCount) + { + this (inventory.getCtx(), 0, inventory.get_TrxName()); + if (inventory.get_ID() == 0) + throw new IllegalArgumentException("Header not saved"); + m_parent = inventory; + setM_Inventory_ID (inventory.getM_Inventory_ID()); // Parent + setClientOrg (inventory.getAD_Client_ID(), inventory.getAD_Org_ID()); + setM_Locator_ID (M_Locator_ID); // FK + setM_Product_ID (M_Product_ID); // FK + setM_AttributeSetInstance_ID (M_AttributeSetInstance_ID); + // + if (QtyBook != null) + setQtyBook (QtyBook); + if (QtyCount != null && QtyCount.signum() != 0) + setQtyCount (QtyCount); + m_isManualEntry = false; + } // MInventoryLine + + /** Manually created */ + private boolean m_isManualEntry = true; + /** Parent */ + private MInventory m_parent = null; + /** Product */ + private MProduct m_product = null; + + /** + * Get Qty Book + * @return Qty Book + */ + public BigDecimal getQtyBook () + { + BigDecimal bd = super.getQtyBook (); + if (bd == null) + bd = Env.ZERO; + return bd; + } // getQtyBook + + /** + * Get Qty Count + * @return Qty Count + */ + public BigDecimal getQtyCount () + { + BigDecimal bd = super.getQtyCount(); + if (bd == null) + bd = Env.ZERO; + return bd; + } // getQtyBook + + /** + * Get Product + * @return product or null if not defined + */ + public MProduct getProduct() + { + int M_Product_ID = getM_Product_ID(); + if (M_Product_ID == 0) + return null; + if (m_product != null && m_product.getM_Product_ID() != M_Product_ID) + m_product = null; // reset + if (m_product == null) + m_product = MProduct.get(getCtx(), M_Product_ID); + return m_product; + } // getProduct + + /** + * Set Count Qty - enforce UOM + * @param QtyCount qty + */ + public void setQtyCount (BigDecimal QtyCount) + { + if (QtyCount != null) + { + MProduct product = getProduct(); + if (product != null) + { + int precision = product.getUOMPrecision(); + QtyCount = QtyCount.setScale(precision, BigDecimal.ROUND_HALF_UP); + } + } + super.setQtyCount(QtyCount); + } // setQtyCount + + /** + * Set Internal Use Qty - enforce UOM + * @param QtyInternalUse qty + */ + public void setQtyInternalUse (BigDecimal QtyInternalUse) + { + if (QtyInternalUse != null) + { + MProduct product = getProduct(); + if (product != null) + { + int precision = product.getUOMPrecision(); + QtyInternalUse = QtyInternalUse.setScale(precision, BigDecimal.ROUND_HALF_UP); + } + } + super.setQtyInternalUse(QtyInternalUse); + } // setQtyInternalUse + + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * Get Parent + * @param parent parent + */ + protected void setParent(MInventory parent) + { + m_parent = parent; + } // setParent + + /** + * Get Parent + * @return parent + */ + private MInventory getParent() + { + if (m_parent == null) + m_parent = new MInventory (getCtx(), getM_Inventory_ID(), get_TrxName()); + return m_parent; + } // getParent + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MInventoryLine["); + sb.append (get_ID()) + .append("-M_Product_ID=").append (getM_Product_ID()) + .append(",QtyCount=").append(getQtyCount()) + .append(",QtyInternalUse=").append(getQtyInternalUse()) + .append(",QtyBook=").append(getQtyBook()) + .append(",M_AttributeSetInstance_ID=").append(getM_AttributeSetInstance_ID()) + .append("]"); + return sb.toString (); + } // toString + + /** + * Before Save + * @param newRecord new + * @return true if can be saved + */ + protected boolean beforeSave (boolean newRecord) + { + if (newRecord && m_isManualEntry) + { + // Product requires ASI + if (getM_AttributeSetInstance_ID() == 0) + { + MProduct product = MProduct.get(getCtx(), getM_Product_ID()); + if (product.getM_AttributeSet_ID() != 0) + { + MAttributeSet mas = MAttributeSet.get(getCtx(), product.getM_AttributeSet_ID()); + if (mas.isInstanceAttribute() + && (mas.isMandatory() || mas.isMandatoryAlways())) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "M_AttributeSetInstance_ID")); + return false; + } + } + } // No ASI + } // new or manual + + // Set Line No + if (getLine() == 0) + { + String sql = "SELECT COALESCE(MAX(Line),0)+10 AS DefaultValue FROM M_InventoryLine WHERE M_Inventory_ID=?"; + int ii = DB.getSQLValue (get_TrxName(), sql, getM_Inventory_ID()); + setLine (ii); + } + + // Enforce Qty UOM + if (newRecord || is_ValueChanged("QtyCount")) + setQtyCount(getQtyCount()); + if (newRecord || is_ValueChanged("QtyInternalUse")) + setQtyInternalUse(getQtyInternalUse()); + + // InternalUse Inventory + if (getQtyInternalUse().signum() != 0) + { + if (!INVENTORYTYPE_ChargeAccount.equals(getInventoryType())) + setInventoryType(INVENTORYTYPE_ChargeAccount); + // + if (getC_Charge_ID() == 0) + { + log.saveError("InternalUseNeedsCharge", ""); + return false; + } + } + else if (INVENTORYTYPE_ChargeAccount.equals(getInventoryType())) + { + if (getC_Charge_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "C_Charge_ID")); + return false; + } + } + else if (getC_Charge_ID() != 0) + setC_Charge_ID(0); + + // Set AD_Org to parent if not charge + if (getC_Charge_ID() == 0) + setAD_Org_ID(getParent().getAD_Org_ID()); + + return true; + } // beforeSave + + /** + * After Save + * @param newRecord new + * @param success success + * @return true + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + // Create MA + if (newRecord && success + && m_isManualEntry && getM_AttributeSetInstance_ID() == 0) + createMA(); + return true; + } // afterSave + + /** + * Create Material Allocations for new Instances + */ + private void createMA() + { + MStorage[] storages = MStorage.getAll(getCtx(), getM_Product_ID(), + getM_Locator_ID(), get_TrxName()); + boolean allZeroASI = true; + for (int i = 0; i < storages.length; i++) + { + if (storages[i].getM_AttributeSetInstance_ID() != 0) + { + allZeroASI = false; + break; + } + } + if (allZeroASI) + return; + + MInventoryLineMA ma = null; + BigDecimal sum = Env.ZERO; + for (int i = 0; i < storages.length; i++) + { + MStorage storage = storages[i]; + if (storage.getQtyOnHand().signum() == 0) + continue; + if (ma != null + && ma.getM_AttributeSetInstance_ID() == storage.getM_AttributeSetInstance_ID()) + ma.setMovementQty(ma.getMovementQty().add(storage.getQtyOnHand())); + else + ma = new MInventoryLineMA (this, + storage.getM_AttributeSetInstance_ID(), storage.getQtyOnHand()); + if (!ma.save()) + ; + sum = sum.add(storage.getQtyOnHand()); + } + if (sum.compareTo(getQtyBook()) != 0) + { + log.warning("QtyBook=" + getQtyBook() + " corrected to Sum of MA=" + sum); + setQtyBook(sum); + } + } // createMA + +} // MInventoryLine diff --git a/base/src/org/compiere/model/MInventoryLineMA.java b/base/src/org/compiere/model/MInventoryLineMA.java new file mode 100644 index 0000000000..7b29af56f3 --- /dev/null +++ b/base/src/org/compiere/model/MInventoryLineMA.java @@ -0,0 +1,149 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Inventory Material Allocation + * + * @author Jorg Janke + * @version $Id: MInventoryLineMA.java,v 1.3 2006/07/30 00:51:04 jjanke Exp $ + */ +public class MInventoryLineMA extends X_M_InventoryLineMA +{ + /** + * Get Material Allocations for Line + * @param ctx context + * @param M_InventoryLine_ID line + * @param trxName trx + * @return allocations + */ + public static MInventoryLineMA[] get (Properties ctx, int M_InventoryLine_ID, String trxName) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_InventoryLineMA WHERE M_InventoryLine_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_InventoryLine_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MInventoryLineMA (ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + MInventoryLineMA[] retValue = new MInventoryLineMA[list.size ()]; + list.toArray (retValue); + return retValue; + } // get + + /** + * Delete all Material Allocation for Inventory + * @param M_Inventory_ID inventory + * @param trxName transaction + * @return number of rows deleted or -1 for error + */ + public static int deleteInventoryMA (int M_Inventory_ID, String trxName) + { + String sql = "DELETE FROM M_InventoryLineMA ma WHERE EXISTS " + + "(SELECT * FROM M_InventoryLine l WHERE l.M_InventoryLine_ID=ma.M_InventoryLine_ID" + + " AND M_Inventory_ID=" + M_Inventory_ID + ")"; + return DB.executeUpdate(sql, trxName); + } // deleteInventoryMA + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MInventoryLineMA.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_InventoryLineMA_ID ignored + * @param trxName trx + */ + public MInventoryLineMA (Properties ctx, int M_InventoryLineMA_ID, String trxName) + { + super (ctx, M_InventoryLineMA_ID, trxName); + if (M_InventoryLineMA_ID != 0) + throw new IllegalArgumentException("Multi-Key"); + } // MInventoryLineMA + + /** + * Load Cosntructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MInventoryLineMA (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MInventoryLineMA + + /** + * Parent Constructor + * @param parent parent + * @param M_AttributeSetInstance_ID asi + * @param MovementQty qty + */ + public MInventoryLineMA (MInventoryLine parent, int M_AttributeSetInstance_ID, BigDecimal MovementQty) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setM_InventoryLine_ID(parent.getM_InventoryLine_ID()); + // + setM_AttributeSetInstance_ID(M_AttributeSetInstance_ID); + setMovementQty(MovementQty); + } // MInventoryLineMA + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MInventoryLineMA["); + sb.append("M_InventoryLine_ID=").append(getM_InventoryLine_ID()) + .append(",M_AttributeSetInstance_ID=").append(getM_AttributeSetInstance_ID()) + .append(", Qty=").append(getMovementQty()) + .append ("]"); + return sb.toString (); + } // toString + +} // MInventoryLineMA diff --git a/base/src/org/compiere/model/MInvoice.java b/base/src/org/compiere/model/MInvoice.java new file mode 100644 index 0000000000..a6c6fdf7a6 --- /dev/null +++ b/base/src/org/compiere/model/MInvoice.java @@ -0,0 +1,2172 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.print.*; +import org.compiere.process.*; +import org.compiere.util.*; + + +/** + * Invoice Model. + * Please do not set DocStatus and C_DocType_ID directly. + * They are set in the process() method. + * Use DocAction and C_DocTypeTarget_ID instead. + * + * @author Jorg Janke + * @version $Id: MInvoice.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MInvoice extends X_C_Invoice implements DocAction +{ + /** + * Get Payments Of BPartner + * @param ctx context + * @param C_BPartner_ID id + * @param trxName transaction + * @return array + */ + public static MInvoice[] getOfBPartner (Properties ctx, int C_BPartner_ID, String trxName) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_Invoice WHERE C_BPartner_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, C_BPartner_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MInvoice(ctx,rs, trxName)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + // + MInvoice[] retValue = new MInvoice[list.size()]; + list.toArray(retValue); + return retValue; + } // getOfBPartner + + /** + * Create new Invoice by copying + * @param from invoice + * @param dateDoc date of the document date + * @param C_DocTypeTarget_ID target doc type + * @param isSOTrx sales order + * @param counter create counter links + * @param trxName trx + * @param setOrder set Order links + * @return Invoice + */ + public static MInvoice copyFrom (MInvoice from, Timestamp dateDoc, + int C_DocTypeTarget_ID, boolean isSOTrx, boolean counter, + String trxName, boolean setOrder) + { + MInvoice to = new MInvoice (from.getCtx(), 0, null); + to.set_TrxName(trxName); + PO.copyValues (from, to, from.getAD_Client_ID(), from.getAD_Org_ID()); + to.set_ValueNoCheck ("C_Invoice_ID", I_ZERO); + to.set_ValueNoCheck ("DocumentNo", null); + // + to.setDocStatus (DOCSTATUS_Drafted); // Draft + to.setDocAction(DOCACTION_Complete); + // + to.setC_DocType_ID(0); + to.setC_DocTypeTarget_ID (C_DocTypeTarget_ID); + to.setIsSOTrx(isSOTrx); + // + to.setDateInvoiced (dateDoc); + to.setDateAcct (dateDoc); + to.setDatePrinted(null); + to.setIsPrinted (false); + // + to.setIsApproved (false); + to.setC_Payment_ID(0); + to.setC_CashLine_ID(0); + to.setIsPaid (false); + to.setIsInDispute(false); + // + // Amounts are updated by trigger when adding lines + to.setGrandTotal(Env.ZERO); + to.setTotalLines(Env.ZERO); + // + to.setIsTransferred (false); + to.setPosted (false); + to.setProcessed (false); + // delete references + to.setIsSelfService(false); + if (!setOrder) + to.setC_Order_ID(0); + if (counter) + { + to.setRef_Invoice_ID(from.getC_Invoice_ID()); + // Try to find Order link + if (from.getC_Order_ID() != 0) + { + MOrder peer = new MOrder (from.getCtx(), from.getC_Order_ID(), from.get_TrxName()); + if (peer.getRef_Order_ID() != 0) + to.setC_Order_ID(peer.getRef_Order_ID()); + } + } + else + to.setRef_Invoice_ID(0); + + if (!to.save(trxName)) + throw new IllegalStateException("Could not create Invoice"); + if (counter) + from.setRef_Invoice_ID(to.getC_Invoice_ID()); + + // Lines + if (to.copyLinesFrom(from, counter, setOrder) == 0) + throw new IllegalStateException("Could not create Invoice Lines"); + + return to; + } // copyFrom + + /** + * Get PDF File Name + * @param documentDir directory + * @param C_Invoice_ID invoice + * @return file name + */ + public static String getPDFFileName (String documentDir, int C_Invoice_ID) + { + StringBuffer sb = new StringBuffer (documentDir); + if (sb.length() == 0) + sb.append("."); + if (!sb.toString().endsWith(File.separator)) + sb.append(File.separator); + sb.append("C_Invoice_ID_") + .append(C_Invoice_ID) + .append(".pdf"); + return sb.toString(); + } // getPDFFileName + + + /** + * Get MInvoice from Cache + * @param ctx context + * @param C_Invoice_ID id + * @return MInvoice + */ + public static MInvoice get (Properties ctx, int C_Invoice_ID) + { + Integer key = new Integer (C_Invoice_ID); + MInvoice retValue = (MInvoice) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MInvoice (ctx, C_Invoice_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("C_Invoice", 20, 2); // 2 minutes + + + /************************************************************************** + * Invoice Constructor + * @param ctx context + * @param C_Invoice_ID invoice or 0 for new + * @param trxName trx name + */ + public MInvoice (Properties ctx, int C_Invoice_ID, String trxName) + { + super (ctx, C_Invoice_ID, trxName); + if (C_Invoice_ID == 0) + { + setDocStatus (DOCSTATUS_Drafted); // Draft + setDocAction (DOCACTION_Complete); + // + setPaymentRule(PAYMENTRULE_OnCredit); // Payment Terms + + setDateInvoiced (new Timestamp (System.currentTimeMillis ())); + setDateAcct (new Timestamp (System.currentTimeMillis ())); + // + setChargeAmt (Env.ZERO); + setTotalLines (Env.ZERO); + setGrandTotal (Env.ZERO); + // + setIsSOTrx (true); + setIsTaxIncluded (false); + setIsApproved (false); + setIsDiscountPrinted (false); + setIsPaid (false); + setSendEMail (false); + setIsPrinted (false); + setIsTransferred (false); + setIsSelfService(false); + setIsPayScheduleValid(false); + setIsInDispute(false); + setPosted(false); + super.setProcessed (false); + setProcessing(false); + } + } // MInvoice + + /** + * Load Constructor + * @param ctx context + * @param rs result set record + * @param trxName transaction + */ + public MInvoice (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MInvoice + + /** + * Create Invoice from Order + * @param order order + * @param C_DocTypeTarget_ID target document type + * @param invoiceDate date or null + */ + public MInvoice (MOrder order, int C_DocTypeTarget_ID, Timestamp invoiceDate) + { + this (order.getCtx(), 0, order.get_TrxName()); + setClientOrg(order); + setOrder(order); // set base settings + // + if (C_DocTypeTarget_ID == 0) + C_DocTypeTarget_ID = DB.getSQLValue(null, + "SELECT C_DocTypeInvoice_ID FROM C_DocType WHERE C_DocType_ID=?", + order.getC_DocType_ID()); + setC_DocTypeTarget_ID(C_DocTypeTarget_ID); + if (invoiceDate != null) + setDateInvoiced(invoiceDate); + setDateAcct(getDateInvoiced()); + // + setSalesRep_ID(order.getSalesRep_ID()); + // + setC_BPartner_ID(order.getBill_BPartner_ID()); + setC_BPartner_Location_ID(order.getBill_Location_ID()); + setAD_User_ID(order.getBill_User_ID()); + } // MInvoice + + /** + * Create Invoice from Shipment + * @param ship shipment + * @param invoiceDate date or null + */ + public MInvoice (MInOut ship, Timestamp invoiceDate) + { + this (ship.getCtx(), 0, ship.get_TrxName()); + setClientOrg(ship); + setShipment(ship); // set base settings + // + setC_DocTypeTarget_ID(); + if (invoiceDate != null) + setDateInvoiced(invoiceDate); + setDateAcct(getDateInvoiced()); + // + setSalesRep_ID(ship.getSalesRep_ID()); + setAD_User_ID(ship.getAD_User_ID()); + } // MInvoice + + /** + * Create Invoice from Batch Line + * @param batch batch + * @param line batch line + */ + public MInvoice (MInvoiceBatch batch, MInvoiceBatchLine line) + { + this (line.getCtx(), 0, line.get_TrxName()); + setClientOrg(line); + setDocumentNo(line.getDocumentNo()); + // + setIsSOTrx(batch.isSOTrx()); + MBPartner bp = new MBPartner (line.getCtx(), line.getC_BPartner_ID(), line.get_TrxName()); + setBPartner(bp); // defaults + // + setIsTaxIncluded(line.isTaxIncluded()); + // May conflict with default price list + setC_Currency_ID(batch.getC_Currency_ID()); + setC_ConversionType_ID(batch.getC_ConversionType_ID()); + // + // setPaymentRule(order.getPaymentRule()); + // setC_PaymentTerm_ID(order.getC_PaymentTerm_ID()); + // setPOReference(""); + setDescription(batch.getDescription()); + // setDateOrdered(order.getDateOrdered()); + // + setAD_OrgTrx_ID(line.getAD_OrgTrx_ID()); + setC_Project_ID(line.getC_Project_ID()); + // setC_Campaign_ID(line.getC_Campaign_ID()); + setC_Activity_ID(line.getC_Activity_ID()); + setUser1_ID(line.getUser1_ID()); + setUser2_ID(line.getUser2_ID()); + // + setC_DocTypeTarget_ID(line.getC_DocType_ID()); + setDateInvoiced(line.getDateInvoiced()); + setDateAcct(line.getDateAcct()); + // + setSalesRep_ID(batch.getSalesRep_ID()); + // + setC_BPartner_ID(line.getC_BPartner_ID()); + setC_BPartner_Location_ID(line.getC_BPartner_Location_ID()); + setAD_User_ID(line.getAD_User_ID()); + } // MInvoice + + /** Open Amount */ + private BigDecimal m_openAmt = null; + + /** Invoice Lines */ + private MInvoiceLine[] m_lines; + /** Invoice Taxes */ + private MInvoiceTax[] m_taxes; + /** Logger */ + private static CLogger s_log = CLogger.getCLogger(MInvoice.class); + + /** + * Overwrite Client/Org if required + * @param AD_Client_ID client + * @param AD_Org_ID org + */ + public void setClientOrg (int AD_Client_ID, int AD_Org_ID) + { + super.setClientOrg(AD_Client_ID, AD_Org_ID); + } // setClientOrg + + /** + * Set Business Partner Defaults & Details + * @param bp business partner + */ + public void setBPartner (MBPartner bp) + { + if (bp == null) + return; + + setC_BPartner_ID(bp.getC_BPartner_ID()); + // Set Defaults + int ii = 0; + if (isSOTrx()) + ii = bp.getC_PaymentTerm_ID(); + else + ii = bp.getPO_PaymentTerm_ID(); + if (ii != 0) + setC_PaymentTerm_ID(ii); + // + if (isSOTrx()) + ii = bp.getM_PriceList_ID(); + else + ii = bp.getPO_PriceList_ID(); + if (ii != 0) + setM_PriceList_ID(ii); + // + String ss = bp.getPaymentRule(); + if (ss != null) + setPaymentRule(ss); + + + // Set Locations + MBPartnerLocation[] locs = bp.getLocations(false); + if (locs != null) + { + for (int i = 0; i < locs.length; i++) + { + if ((locs[i].isBillTo() && isSOTrx()) + || (locs[i].isPayFrom() && !isSOTrx())) + setC_BPartner_Location_ID(locs[i].getC_BPartner_Location_ID()); + } + // set to first + if (getC_BPartner_Location_ID() == 0 && locs.length > 0) + setC_BPartner_Location_ID(locs[0].getC_BPartner_Location_ID()); + } + if (getC_BPartner_Location_ID() == 0) + log.log(Level.SEVERE, "Has no To Address: " + bp); + + // Set Contact + MUser[] contacts = bp.getContacts(false); + if (contacts != null && contacts.length > 0) // get first User + setAD_User_ID(contacts[0].getAD_User_ID()); + } // setBPartner + + /** + * Set Order References + * @param order order + */ + public void setOrder (MOrder order) + { + if (order == null) + return; + + setC_Order_ID(order.getC_Order_ID()); + setIsSOTrx(order.isSOTrx()); + setIsDiscountPrinted(order.isDiscountPrinted()); + setIsSelfService(order.isSelfService()); + setSendEMail(order.isSendEMail()); + // + setM_PriceList_ID(order.getM_PriceList_ID()); + setIsTaxIncluded(order.isTaxIncluded()); + setC_Currency_ID(order.getC_Currency_ID()); + setC_ConversionType_ID(order.getC_ConversionType_ID()); + // + setPaymentRule(order.getPaymentRule()); + setC_PaymentTerm_ID(order.getC_PaymentTerm_ID()); + setPOReference(order.getPOReference()); + setDescription(order.getDescription()); + setDateOrdered(order.getDateOrdered()); + // + setAD_OrgTrx_ID(order.getAD_OrgTrx_ID()); + setC_Project_ID(order.getC_Project_ID()); + setC_Campaign_ID(order.getC_Campaign_ID()); + setC_Activity_ID(order.getC_Activity_ID()); + setUser1_ID(order.getUser1_ID()); + setUser2_ID(order.getUser2_ID()); + } // setOrder + + /** + * Set Shipment References + * @param ship shipment + */ + public void setShipment (MInOut ship) + { + if (ship == null) + return; + + setIsSOTrx(ship.isSOTrx()); + // + MBPartner bp = new MBPartner (getCtx(), ship.getC_BPartner_ID(), null); + setBPartner (bp); + // + setSendEMail(ship.isSendEMail()); + // + setPOReference(ship.getPOReference()); + setDescription(ship.getDescription()); + setDateOrdered(ship.getDateOrdered()); + // + setAD_OrgTrx_ID(ship.getAD_OrgTrx_ID()); + setC_Project_ID(ship.getC_Project_ID()); + setC_Campaign_ID(ship.getC_Campaign_ID()); + setC_Activity_ID(ship.getC_Activity_ID()); + setUser1_ID(ship.getUser1_ID()); + setUser2_ID(ship.getUser2_ID()); + // + if (ship.getC_Order_ID() != 0) + { + setC_Order_ID(ship.getC_Order_ID()); + MOrder order = new MOrder (getCtx(), ship.getC_Order_ID(), get_TrxName()); + setIsDiscountPrinted(order.isDiscountPrinted()); + setM_PriceList_ID(order.getM_PriceList_ID()); + setIsTaxIncluded(order.isTaxIncluded()); + setC_Currency_ID(order.getC_Currency_ID()); + setC_ConversionType_ID(order.getC_ConversionType_ID()); + setPaymentRule(order.getPaymentRule()); + setC_PaymentTerm_ID(order.getC_PaymentTerm_ID()); + // + MDocType dt = MDocType.get(getCtx(), order.getC_DocType_ID()); + if (dt.getC_DocTypeInvoice_ID() != 0) + setC_DocTypeTarget_ID(dt.getC_DocTypeInvoice_ID()); + // Overwrite Invoice Address + setC_BPartner_Location_ID(order.getBill_Location_ID()); + } + } // setShipment + + /** + * Set Target Document Type + * @param DocBaseType doc type MDocType.DOCBASETYPE_ + */ + public void setC_DocTypeTarget_ID (String DocBaseType) + { + String sql = "SELECT C_DocType_ID FROM C_DocType " + + "WHERE AD_Client_ID=? AND DocBaseType=?" + + " AND IsActive='Y' " + + "ORDER BY IsDefault DESC"; + int C_DocType_ID = DB.getSQLValue(null, sql, getAD_Client_ID(), DocBaseType); + if (C_DocType_ID <= 0) + log.log(Level.SEVERE, "Not found for AC_Client_ID=" + + getAD_Client_ID() + " - " + DocBaseType); + else + { + log.fine(DocBaseType); + setC_DocTypeTarget_ID (C_DocType_ID); + boolean isSOTrx = MDocType.DOCBASETYPE_ARInvoice.equals(DocBaseType) + || MDocType.DOCBASETYPE_ARCreditMemo.equals(DocBaseType); + setIsSOTrx (isSOTrx); + } + } // setC_DocTypeTarget_ID + + /** + * Set Target Document Type. + * Based on SO flag AP/AP Invoice + */ + public void setC_DocTypeTarget_ID () + { + if (getC_DocTypeTarget_ID() > 0) + return; + if (isSOTrx()) + setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_ARInvoice); + else + setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_APInvoice); + } // setC_DocTypeTarget_ID + + + /** + * Get Grand Total + * @param creditMemoAdjusted adjusted for CM (negative) + * @return grand total + */ + public BigDecimal getGrandTotal (boolean creditMemoAdjusted) + { + if (!creditMemoAdjusted) + return super.getGrandTotal(); + // + BigDecimal amt = getGrandTotal(); + if (isCreditMemo()) + return amt.negate(); + return amt; + } // getGrandTotal + + + /** + * Get Invoice Lines of Invoice + * @param whereClause starting with AND + * @return lines + */ + private MInvoiceLine[] getLines (String whereClause) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_InvoiceLine WHERE C_Invoice_ID=? "; + if (whereClause != null) + sql += whereClause; + sql += " ORDER BY Line"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_Invoice_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + MInvoiceLine il = new MInvoiceLine(getCtx(), rs, get_TrxName()); + il.setInvoice(this); + list.add(il); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getLines", e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + + // + MInvoiceLine[] lines = new MInvoiceLine[list.size()]; + list.toArray(lines); + return lines; + } // getLines + + /** + * Get Invoice Lines + * @param requery + * @return lines + */ + public MInvoiceLine[] getLines (boolean requery) + { + if (m_lines == null || m_lines.length == 0 || requery) + m_lines = getLines(null); + return m_lines; + } // getLines + + /** + * Get Lines of Invoice + * @return lines + */ + public MInvoiceLine[] getLines() + { + return getLines(false); + } // getLines + + + /** + * Renumber Lines + * @param step start and step + */ + public void renumberLines (int step) + { + int number = step; + MInvoiceLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MInvoiceLine line = lines[i]; + line.setLine(number); + line.save(); + number += step; + } + m_lines = null; + } // renumberLines + + /** + * Copy Lines From other Invoice. + * @param otherInvoice invoice + * @param counter create counter links + * @param setOrder set order links + * @return number of lines copied + */ + public int copyLinesFrom (MInvoice otherInvoice, boolean counter, boolean setOrder) + { + if (isProcessed() || isPosted() || otherInvoice == null) + return 0; + MInvoiceLine[] fromLines = otherInvoice.getLines(false); + int count = 0; + for (int i = 0; i < fromLines.length; i++) + { + MInvoiceLine line = new MInvoiceLine (getCtx(), 0, get_TrxName()); + MInvoiceLine fromLine = fromLines[i]; + if (counter) // header + PO.copyValues (fromLine, line, getAD_Client_ID(), getAD_Org_ID()); + else + PO.copyValues (fromLine, line, fromLine.getAD_Client_ID(), fromLine.getAD_Org_ID()); + line.setC_Invoice_ID(getC_Invoice_ID()); + line.setInvoice(this); + line.set_ValueNoCheck ("C_InvoiceLine_ID", I_ZERO); // new + // Reset + if (!setOrder) + line.setC_OrderLine_ID(0); + line.setRef_InvoiceLine_ID(0); + line.setM_InOutLine_ID(0); + line.setA_Asset_ID(0); + line.setM_AttributeSetInstance_ID(0); + line.setS_ResourceAssignment_ID(0); + // New Tax + if (getC_BPartner_ID() != otherInvoice.getC_BPartner_ID()) + line.setTax(); // recalculate + // + if (counter) + { + line.setRef_InvoiceLine_ID(fromLine.getC_InvoiceLine_ID()); + if (fromLine.getC_OrderLine_ID() != 0) + { + MOrderLine peer = new MOrderLine (getCtx(), fromLine.getC_OrderLine_ID(), get_TrxName()); + if (peer.getRef_OrderLine_ID() != 0) + line.setC_OrderLine_ID(peer.getRef_OrderLine_ID()); + } + line.setM_InOutLine_ID(0); + if (fromLine.getM_InOutLine_ID() != 0) + { + MInOutLine peer = new MInOutLine (getCtx(), fromLine.getM_InOutLine_ID(), get_TrxName()); + if (peer.getRef_InOutLine_ID() != 0) + line.setM_InOutLine_ID(peer.getRef_InOutLine_ID()); + } + } + // + line.setProcessed(false); + if (line.save(get_TrxName())) + count++; + // Cross Link + if (counter) + { + fromLine.setRef_InvoiceLine_ID(line.getC_InvoiceLine_ID()); + fromLine.save(get_TrxName()); + } + } + if (fromLines.length != count) + log.log(Level.SEVERE, "Line difference - From=" + fromLines.length + " <> Saved=" + count); + return count; + } // copyLinesFrom + + /** Reversal Flag */ + private boolean m_reversal = false; + + /** + * Set Reversal + * @param reversal reversal + */ + private void setReversal(boolean reversal) + { + m_reversal = reversal; + } // setReversal + /** + * Is Reversal + * @return reversal + */ + private boolean isReversal() + { + return m_reversal; + } // isReversal + + /** + * Get Taxes + * @param requery requery + * @return array of taxes + */ + public MInvoiceTax[] getTaxes (boolean requery) + { + if (m_taxes != null && !requery) + return m_taxes; + String sql = "SELECT * FROM C_InvoiceTax WHERE C_Invoice_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_Invoice_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MInvoiceTax(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getTaxes", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + m_taxes = new MInvoiceTax[list.size ()]; + list.toArray (m_taxes); + return m_taxes; + } // getTaxes + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * Is it a Credit Memo? + * @return true if CM + */ + public boolean isCreditMemo() + { + MDocType dt = MDocType.get(getCtx(), + getC_DocType_ID()==0 ? getC_DocTypeTarget_ID() : getC_DocType_ID()); + return MDocType.DOCBASETYPE_APCreditMemo.equals(dt.getDocBaseType()) + || MDocType.DOCBASETYPE_ARCreditMemo.equals(dt.getDocBaseType()); + } // isCreditMemo + + /** + * Set Processed. + * Propergate to Lines/Taxes + * @param processed processed + */ + public void setProcessed (boolean processed) + { + super.setProcessed (processed); + if (get_ID() == 0) + return; + String set = "SET Processed='" + + (processed ? "Y" : "N") + + "' WHERE C_Invoice_ID=" + getC_Invoice_ID(); + int noLine = DB.executeUpdate("UPDATE C_InvoiceLine " + set, get_TrxName()); + int noTax = DB.executeUpdate("UPDATE C_InvoiceTax " + set, get_TrxName()); + m_lines = null; + m_taxes = null; + log.fine(processed + " - Lines=" + noLine + ", Tax=" + noTax); + } // setProcessed + + /** + * Validate Invoice Pay Schedule + * @return pay schedule is valid + */ + public boolean validatePaySchedule() + { + MInvoicePaySchedule[] schedule = MInvoicePaySchedule.getInvoicePaySchedule + (getCtx(), getC_Invoice_ID(), 0, get_TrxName()); + log.fine("#" + schedule.length); + if (schedule.length == 0) + { + setIsPayScheduleValid(false); + return false; + } + // Add up due amounts + BigDecimal total = Env.ZERO; + for (int i = 0; i < schedule.length; i++) + { + schedule[i].setParent(this); + BigDecimal due = schedule[i].getDueAmt(); + if (due != null) + total = total.add(due); + } + boolean valid = getGrandTotal().compareTo(total) == 0; + setIsPayScheduleValid(valid); + + // Update Schedule Lines + for (int i = 0; i < schedule.length; i++) + { + if (schedule[i].isValid() != valid) + { + schedule[i].setIsValid(valid); + schedule[i].save(get_TrxName()); + } + } + return valid; + } // validatePaySchedule + + + /************************************************************************** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + log.fine(""); + // No Partner Info - set Template + if (getC_BPartner_ID() == 0) + setBPartner(MBPartner.getTemplate(getCtx(), getAD_Client_ID())); + if (getC_BPartner_Location_ID() == 0) + setBPartner(new MBPartner(getCtx(), getC_BPartner_ID(), null)); + + // Price List + if (getM_PriceList_ID() == 0) + { + int ii = Env.getContextAsInt(getCtx(), "#M_PriceList_ID"); + if (ii != 0) + setM_PriceList_ID(ii); + else + { + String sql = "SELECT M_PriceList_ID FROM M_PriceList WHERE AD_Client_ID=? AND IsDefault='Y'"; + ii = DB.getSQLValue (null, sql, getAD_Client_ID()); + if (ii != 0) + setM_PriceList_ID (ii); + } + } + + // Currency + if (getC_Currency_ID() == 0) + { + String sql = "SELECT C_Currency_ID FROM M_PriceList WHERE M_PriceList_ID=?"; + int ii = DB.getSQLValue (null, sql, getM_PriceList_ID()); + if (ii != 0) + setC_Currency_ID (ii); + else + setC_Currency_ID(Env.getContextAsInt(getCtx(), "#C_Currency_ID")); + } + + // Sales Rep + if (getSalesRep_ID() == 0) + { + int ii = Env.getContextAsInt(getCtx(), "#SalesRep_ID"); + if (ii != 0) + setSalesRep_ID (ii); + } + + // Document Type + if (getC_DocType_ID() == 0) + setC_DocType_ID (0); // make sure it's set to 0 + if (getC_DocTypeTarget_ID() == 0) + setC_DocTypeTarget_ID(isSOTrx() ? MDocType.DOCBASETYPE_ARInvoice : MDocType.DOCBASETYPE_APInvoice); + + // Payment Term + if (getC_PaymentTerm_ID() == 0) + { + int ii = Env.getContextAsInt(getCtx(), "#C_PaymentTerm_ID"); + if (ii != 0) + setC_PaymentTerm_ID (ii); + else + { + String sql = "SELECT C_PaymentTerm_ID FROM C_PaymentTerm WHERE AD_Client_ID=? AND IsDefault='Y'"; + ii = DB.getSQLValue(null, sql, getAD_Client_ID()); + if (ii != 0) + setC_PaymentTerm_ID (ii); + } + } + return true; + } // beforeSave + + /** + * Before Delete + * @return true if it can be deleted + */ + protected boolean beforeDelete () + { + if (getC_Order_ID() != 0) + { + log.saveError("Error", Msg.getMsg(getCtx(), "CannotDelete")); + return false; + } + return true; + } // beforeDelete + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MInvoice[") + .append(get_ID()).append("-").append(getDocumentNo()) + .append(",GrandTotal=").append(getGrandTotal()); + if (m_lines != null) + sb.append(" (#").append(m_lines.length).append(")"); + sb.append ("]"); + return sb.toString (); + } // toString + + /** + * Get Document Info + * @return document info (untranslated) + */ + public String getDocumentInfo() + { + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + return dt.getName() + " " + getDocumentNo(); + } // getDocumentInfo + + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success || newRecord) + return success; + + if (is_ValueChanged("AD_Org_ID")) + { + String sql = "UPDATE C_InvoiceLine ol" + + " SET AD_Org_ID =" + + "(SELECT AD_Org_ID" + + " FROM C_Invoice o WHERE ol.C_Invoice_ID=o.C_Invoice_ID) " + + "WHERE C_Invoice_ID=" + getC_Order_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + log.fine("Lines -> #" + no); + } + return true; + } // afterSave + + + /** + * Set Price List (and Currency) when valid + * @param M_PriceList_ID price list + */ + public void setM_PriceList_ID (int M_PriceList_ID) + { + String sql = "SELECT M_PriceList_ID, C_Currency_ID " + + "FROM M_PriceList WHERE M_PriceList_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, M_PriceList_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + super.setM_PriceList_ID (rs.getInt(1)); + setC_Currency_ID (rs.getInt(2)); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "setM_PriceList_ID", e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + } // setM_PriceList_ID + + + /** + * Get Allocated Amt in Invoice Currency + * @return pos/neg amount or null + */ + public BigDecimal getAllocatedAmt () + { + BigDecimal retValue = null; + String sql = "SELECT SUM(currencyConvert(al.Amount+al.DiscountAmt+al.WriteOffAmt," + + "ah.C_Currency_ID, i.C_Currency_ID,ah.DateTrx,i.C_ConversionType_ID, al.AD_Client_ID,al.AD_Org_ID)) " + + "FROM C_AllocationLine al" + + " INNER JOIN C_AllocationHdr ah ON (al.C_AllocationHdr_ID=ah.C_AllocationHdr_ID)" + + " INNER JOIN C_Invoice i ON (al.C_Invoice_ID=i.C_Invoice_ID) " + + "WHERE al.C_Invoice_ID=?" + + " AND ah.IsActive='Y' AND al.IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_Invoice_ID()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + retValue = rs.getBigDecimal(1); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // log.fine("getAllocatedAmt - " + retValue); + // ? ROUND(NVL(v_AllocatedAmt,0), 2); + return retValue; + } // getAllocatedAmt + + /** + * Test Allocation (and set paid flag) + * @return true if updated + */ + public boolean testAllocation() + { + BigDecimal alloc = getAllocatedAmt(); // absolute + if (alloc == null) + alloc = Env.ZERO; + BigDecimal total = getGrandTotal(); + if (!isSOTrx()) + total = total.negate(); + if (isCreditMemo()) + total = total.negate(); + boolean test = total.compareTo(alloc) == 0; + boolean change = test != isPaid(); + if (change) + setIsPaid(test); + log.fine("Paid=" + test + + " (" + alloc + "=" + total + ")"); + return change; + } // testAllocation + + /** + * Set Paid Flag for invoices + * @param ctx context + * @param C_BPartner_ID if 0 all + * @param trxName transaction + */ + public static void setIsPaid (Properties ctx, int C_BPartner_ID, String trxName) + { + int counter = 0; + String sql = "SELECT * FROM C_Invoice " + + "WHERE IsPaid='N' AND DocStatus IN ('CO','CL')"; + if (C_BPartner_ID > 1) + sql += " AND C_BPartner_ID=?"; + else + sql += " AND AD_Client_ID=" + Env.getAD_Client_ID(ctx); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + if (C_BPartner_ID > 1) + pstmt.setInt (1, C_BPartner_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MInvoice invoice = new MInvoice(ctx, rs, trxName); + if (invoice.testAllocation()) + if (invoice.save()) + counter++; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + s_log.config("#" + counter); + /**/ + } // setIsPaid + + /** + * Get Open Amount. + * Used by web interface + * @return Open Amt + */ + public BigDecimal getOpenAmt () + { + return getOpenAmt (true, null); + } // getOpenAmt + + /** + * Get Open Amount + * @param creditMemoAdjusted adjusted for CM (negative) + * @param paymentDate ignored Payment Date + * @return Open Amt + */ + public BigDecimal getOpenAmt (boolean creditMemoAdjusted, Timestamp paymentDate) + { + if (isPaid()) + return Env.ZERO; + // + if (m_openAmt == null) + { + m_openAmt = getGrandTotal(); + if (paymentDate != null) + { + // Payment Discount + // Payment Schedule + } + BigDecimal allocated = getAllocatedAmt(); + if (allocated != null) + { + allocated = allocated.abs(); // is absolute + m_openAmt = m_openAmt.subtract(allocated); + } + } + // + if (!creditMemoAdjusted) + return m_openAmt; + if (isCreditMemo()) + return m_openAmt.negate(); + return m_openAmt; + } // getOpenAmt + + + /** + * Get Document Status + * @return Document Status Clear Text + */ + public String getDocStatusName() + { + return MRefList.getListName(getCtx(), 131, getDocStatus()); + } // getDocStatusName + + + /************************************************************************** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.INVOICE, getC_Invoice_ID()); + if (re == null) + return null; + return re.getPDF(file); + } // createPDF + + /** + * Get PDF File Name + * @param documentDir directory + * @return file name + */ + public String getPDFFileName (String documentDir) + { + return getPDFFileName (documentDir, getC_Invoice_ID()); + } // getPDFFileName + + /** + * Get ISO Code of Currency + * @return Currency ISO + */ + public String getCurrencyISO() + { + return MCurrency.getISO_Code (getCtx(), getC_Currency_ID()); + } // getCurrencyISO + + /** + * Get Currency Precision + * @return precision + */ + public int getPrecision() + { + return MCurrency.getStdPrecision(getCtx(), getC_Currency_ID()); + } // getPrecision + + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // process + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info("unlockIt - " + toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info("invalidateIt - " + toString()); + setDocAction(DOCACTION_Prepare); + return true; + } // invalidateIt + + /** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + MDocType dt = MDocType.get(getCtx(), getC_DocTypeTarget_ID()); + + // Std Period open? + if (!MPeriod.isOpen(getCtx(), getDateAcct(), dt.getDocBaseType())) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + // Lines + MInvoiceLine[] lines = getLines(true); + if (lines.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + // No Cash Book + if (PAYMENTRULE_Cash.equals(getPaymentRule()) + && MCashBook.get(getCtx(), getAD_Org_ID(), getC_Currency_ID()) == null) + { + m_processMsg = "@NoCashBook@"; + return DocAction.STATUS_Invalid; + } + + // Convert/Check DocType + if (getC_DocType_ID() != getC_DocTypeTarget_ID() ) + setC_DocType_ID(getC_DocTypeTarget_ID()); + if (getC_DocType_ID() == 0) + { + m_processMsg = "No Document Type"; + return DocAction.STATUS_Invalid; + } + + explodeBOM(); + if (!calculateTaxTotal()) // setTotals + { + m_processMsg = "Error calculating Tax"; + return DocAction.STATUS_Invalid; + } + + createPaySchedule(); + + // Credit Status + if (isSOTrx() && !isReversal()) + { + MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), null); + if (MBPartner.SOCREDITSTATUS_CreditStop.equals(bp.getSOCreditStatus())) + { + m_processMsg = "@BPartnerCreditStop@ - @TotalOpenBalance@=" + + bp.getTotalOpenBalance() + + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); + return DocAction.STATUS_Invalid; + } + } + + // Landed Costs + if (!isSOTrx()) + { + for (int i = 0; i < lines.length; i++) + { + MInvoiceLine line = lines[i]; + String error = line.allocateLandedCosts(); + if (error != null && error.length() > 0) + { + m_processMsg = error; + return DocAction.STATUS_Invalid; + } + } + } + + // Add up Amounts + m_justPrepared = true; + if (!DOCACTION_Complete.equals(getDocAction())) + setDocAction(DOCACTION_Complete); + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Explode non stocked BOM. + */ + private void explodeBOM () + { + String where = "AND IsActive='Y' AND EXISTS " + + "(SELECT * FROM M_Product p WHERE C_InvoiceLine.M_Product_ID=p.M_Product_ID" + + " AND p.IsBOM='Y' AND p.IsVerified='Y' AND p.IsStocked='N')"; + // + String sql = "SELECT COUNT(*) FROM C_InvoiceLine " + + "WHERE C_Invoice_ID=? " + where; + int count = DB.getSQLValue(get_TrxName(), sql, getC_Invoice_ID()); + while (count != 0) + { + renumberLines (100); + + // Order Lines with non-stocked BOMs + MInvoiceLine[] lines = getLines (where); + for (int i = 0; i < lines.length; i++) + { + MInvoiceLine line = lines[i]; + MProduct product = MProduct.get (getCtx(), line.getM_Product_ID()); + log.fine(product.getName()); + // New Lines + int lineNo = line.getLine (); + MProductBOM[] boms = MProductBOM.getBOMLines (product); + for (int j = 0; j < boms.length; j++) + { + MProductBOM bom = boms[j]; + MInvoiceLine newLine = new MInvoiceLine (this); + newLine.setLine (++lineNo); + newLine.setM_Product_ID (bom.getProduct().getM_Product_ID(), + bom.getProduct().getC_UOM_ID()); + newLine.setQty (line.getQtyInvoiced().multiply( + bom.getBOMQty ())); // Invoiced/Entered + if (bom.getDescription () != null) + newLine.setDescription (bom.getDescription ()); + // + newLine.setPrice (); + newLine.save (get_TrxName()); + } + // Convert into Comment Line + line.setM_Product_ID (0); + line.setM_AttributeSetInstance_ID (0); + line.setPriceEntered (Env.ZERO); + line.setPriceActual (Env.ZERO); + line.setPriceLimit (Env.ZERO); + line.setPriceList (Env.ZERO); + line.setLineNetAmt (Env.ZERO); + // + String description = product.getName (); + if (product.getDescription () != null) + description += " " + product.getDescription (); + if (line.getDescription () != null) + description += " " + line.getDescription (); + line.setDescription (description); + line.save (get_TrxName()); + } // for all lines with BOM + + m_lines = null; + count = DB.getSQLValue (get_TrxName(), sql, getC_Invoice_ID ()); + renumberLines (10); + } // while count != 0 + } // explodeBOM + + /** + * Calculate Tax and Total + * @return true if calculated + */ + private boolean calculateTaxTotal() + { + log.fine(""); + // Delete Taxes + DB.executeUpdate("DELETE C_InvoiceTax WHERE C_Invoice_ID=" + getC_Invoice_ID(), get_TrxName()); + m_taxes = null; + + // Lines + BigDecimal totalLines = Env.ZERO; + ArrayList taxList = new ArrayList(); + MInvoiceLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MInvoiceLine line = lines[i]; + /** Sync ownership for SO + if (isSOTrx() && line.getAD_Org_ID() != getAD_Org_ID()) + { + line.setAD_Org_ID(getAD_Org_ID()); + line.save(); + } **/ + Integer taxID = new Integer(line.getC_Tax_ID()); + if (!taxList.contains(taxID)) + { + MInvoiceTax iTax = MInvoiceTax.get (line, getPrecision(), + false, get_TrxName()); // current Tax + if (iTax != null) + { + iTax.setIsTaxIncluded(isTaxIncluded()); + if (!iTax.calculateTaxFromLines()) + return false; + if (!iTax.save()) + return false; + taxList.add(taxID); + } + } + totalLines = totalLines.add(line.getLineNetAmt()); + } + + // Taxes + BigDecimal grandTotal = totalLines; + MInvoiceTax[] taxes = getTaxes(true); + for (int i = 0; i < taxes.length; i++) + { + MInvoiceTax iTax = taxes[i]; + MTax tax = iTax.getTax(); + if (tax.isSummary()) + { + MTax[] cTaxes = tax.getChildTaxes(false); // Multiple taxes + for (int j = 0; j < cTaxes.length; j++) + { + MTax cTax = cTaxes[j]; + BigDecimal taxAmt = cTax.calculateTax(iTax.getTaxBaseAmt(), isTaxIncluded(), getPrecision()); + // + MInvoiceTax newITax = new MInvoiceTax(getCtx(), 0, get_TrxName()); + newITax.setClientOrg(this); + newITax.setC_Invoice_ID(getC_Invoice_ID()); + newITax.setC_Tax_ID(cTax.getC_Tax_ID()); + newITax.setPrecision(getPrecision()); + newITax.setIsTaxIncluded(isTaxIncluded()); + newITax.setTaxBaseAmt(iTax.getTaxBaseAmt()); + newITax.setTaxAmt(taxAmt); + if (!newITax.save(get_TrxName())) + return false; + // + if (!isTaxIncluded()) + grandTotal = grandTotal.add(taxAmt); + } + if (!iTax.delete(true, get_TrxName())) + return false; + } + else + { + if (!isTaxIncluded()) + grandTotal = grandTotal.add(iTax.getTaxAmt()); + } + } + // + setTotalLines(totalLines); + setGrandTotal(grandTotal); + return true; + } // calculateTaxTotal + + + /** + * (Re) Create Pay Schedule + * @return true if valid schedule + */ + private boolean createPaySchedule() + { + if (getC_PaymentTerm_ID() == 0) + return false; + MPaymentTerm pt = new MPaymentTerm(getCtx(), getC_PaymentTerm_ID(), null); + log.fine(pt.toString()); + return pt.apply(this); // calls validate pay schedule + } // createPaySchedule + + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info(toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info(toString()); + setIsApproved(false); + return true; + } // rejectIt + + /** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + // Implicit Approval + if (!isApproved()) + approveIt(); + log.info(toString()); + StringBuffer info = new StringBuffer(); + + // Create Cash + if (PAYMENTRULE_Cash.equals(getPaymentRule())) + { + MCash cash = MCash.get (getCtx(), getAD_Org_ID(), + getDateInvoiced(), getC_Currency_ID(), get_TrxName()); + if (cash == null || cash.get_ID() == 0) + { + m_processMsg = "@NoCashBook@"; + return DocAction.STATUS_Invalid; + } + MCashLine cl = new MCashLine (cash); + cl.setInvoice(this); + if (!cl.save(get_TrxName())) + { + m_processMsg = "Could not save Cash Journal Line"; + return DocAction.STATUS_Invalid; + } + info.append("@C_Cash_ID@: " + cash.getName() + " #" + cl.getLine()); + setC_CashLine_ID(cl.getC_CashLine_ID()); + } // CashBook + + // Update Order & Match + int matchInv = 0; + int matchPO = 0; + MInvoiceLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MInvoiceLine line = lines[i]; + + // Update Order Line + MOrderLine ol = null; + if (line.getC_OrderLine_ID() != 0) + { + if (isSOTrx() + || line.getM_Product_ID() == 0) + { + ol = new MOrderLine (getCtx(), line.getC_OrderLine_ID(), get_TrxName()); + if (line.getQtyInvoiced() != null) + ol.setQtyInvoiced(ol.getQtyInvoiced().add(line.getQtyInvoiced())); + if (!ol.save(get_TrxName())) + { + m_processMsg = "Could not update Order Line"; + return DocAction.STATUS_Invalid; + } + } + // Order Invoiced Qty updated via Matching Inv-PO + else if (!isSOTrx() + && line.getM_Product_ID() != 0 + && !isReversal()) + { + // MatchPO is created also from MInOut when Invoice exists before Shipment + BigDecimal matchQty = line.getQtyInvoiced(); + MMatchPO po = MMatchPO.create (line, null, + getDateInvoiced(), matchQty); + if (!po.save(get_TrxName())) + { + m_processMsg = "Could not create PO Matching"; + return DocAction.STATUS_Invalid; + } + else + matchPO++; + } + } + + // Matching - Inv-Shipment + if (!isSOTrx() + && line.getM_InOutLine_ID() != 0 + && line.getM_Product_ID() != 0 + && !isReversal()) + { + BigDecimal matchQty = line.getQtyInvoiced(); + MMatchInv inv = new MMatchInv(line, getDateInvoiced(), matchQty); + if (!inv.save(get_TrxName())) + { + m_processMsg = "Could not create Invoice Matching"; + return DocAction.STATUS_Invalid; + } + else + matchInv++; + } + } // for all lines + if (matchInv > 0) + info.append(" @M_MatchInv_ID@#").append(matchInv).append(" "); + if (matchPO > 0) + info.append(" @M_MatchPO_ID@#").append(matchPO).append(" "); + + + + // Update BP Statistics + MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName()); + // Update total revenue and balance / credit limit (reversed on AllocationLine.processIt) + BigDecimal invAmt = MConversionRate.convertBase(getCtx(), getGrandTotal(true), // CM adjusted + getC_Currency_ID(), getDateAcct(), 0, getAD_Client_ID(), getAD_Org_ID()); + if (invAmt == null) + { + m_processMsg = "Could not convert C_Currency_ID=" + getC_Currency_ID() + + " to base C_Currency_ID=" + MClient.get(Env.getCtx()).getC_Currency_ID(); + return DocAction.STATUS_Invalid; + } + // Total Balance + BigDecimal newBalance = bp.getTotalOpenBalance(false); + if (newBalance == null) + newBalance = Env.ZERO; + if (isSOTrx()) + { + newBalance = newBalance.add(invAmt); + // + if (bp.getFirstSale() == null) + bp.setFirstSale(getDateInvoiced()); + BigDecimal newLifeAmt = bp.getActualLifeTimeValue(); + if (newLifeAmt == null) + newLifeAmt = invAmt; + else + newLifeAmt = newLifeAmt.add(invAmt); + BigDecimal newCreditAmt = bp.getSO_CreditUsed(); + if (newCreditAmt == null) + newCreditAmt = invAmt; + else + newCreditAmt = newCreditAmt.add(invAmt); + // + log.fine("GrandTotal=" + getGrandTotal(true) + "(" + invAmt + + ") BP Life=" + bp.getActualLifeTimeValue() + "->" + newLifeAmt + + ", Credit=" + bp.getSO_CreditUsed() + "->" + newCreditAmt + + ", Balance=" + bp.getTotalOpenBalance(false) + " -> " + newBalance); + bp.setActualLifeTimeValue(newLifeAmt); + bp.setSO_CreditUsed(newCreditAmt); + } // SO + else + { + newBalance = newBalance.subtract(invAmt); + log.fine("GrandTotal=" + getGrandTotal(true) + "(" + invAmt + + ") Balance=" + bp.getTotalOpenBalance(false) + " -> " + newBalance); + } + bp.setTotalOpenBalance(newBalance); + bp.setSOCreditStatus(); + if (!bp.save(get_TrxName())) + { + m_processMsg = "Could not update Business Partner"; + return DocAction.STATUS_Invalid; + } + + // User - Last Result/Contact + if (getAD_User_ID() != 0) + { + MUser user = new MUser (getCtx(), getAD_User_ID(), get_TrxName()); + user.setLastContact(new Timestamp(System.currentTimeMillis())); + user.setLastResult(Msg.translate(getCtx(), "C_Invoice_ID") + ": " + getDocumentNo()); + if (!user.save(get_TrxName())) + { + m_processMsg = "Could not update Business Partner User"; + return DocAction.STATUS_Invalid; + } + } // user + + // Update Project + if (isSOTrx() && getC_Project_ID() != 0) + { + MProject project = new MProject (getCtx(), getC_Project_ID(), get_TrxName()); + BigDecimal amt = getGrandTotal(true); + int C_CurrencyTo_ID = project.getC_Currency_ID(); + if (C_CurrencyTo_ID != getC_Currency_ID()) + amt = MConversionRate.convert(getCtx(), amt, getC_Currency_ID(), C_CurrencyTo_ID, + getDateAcct(), 0, getAD_Client_ID(), getAD_Org_ID()); + if (amt == null) + { + m_processMsg = "Could not convert C_Currency_ID=" + getC_Currency_ID() + + " to Project C_Currency_ID=" + C_CurrencyTo_ID; + return DocAction.STATUS_Invalid; + } + BigDecimal newAmt = project.getInvoicedAmt(); + if (newAmt == null) + newAmt = amt; + else + newAmt = newAmt.add(amt); + log.fine("GrandTotal=" + getGrandTotal(true) + "(" + amt + + ") Project " + project.getName() + + " - Invoiced=" + project.getInvoicedAmt() + "->" + newAmt); + project.setInvoicedAmt(newAmt); + if (!project.save(get_TrxName())) + { + m_processMsg = "Could not update Project"; + return DocAction.STATUS_Invalid; + } + } // project + + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + m_processMsg = valid; + return DocAction.STATUS_Invalid; + } + + // Counter Documents + MInvoice counter = createCounterDoc(); + if (counter != null) + info.append(" - @CounterDoc@: @C_Invoice_ID@=").append(counter.getDocumentNo()); + + m_processMsg = info.toString().trim(); + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + /** + * Create Counter Document + * @return counter invoice + */ + private MInvoice createCounterDoc() + { + // Is this a counter doc ? + if (getRef_Invoice_ID() != 0) + return null; + + // Org Must be linked to BPartner + MOrg org = MOrg.get(getCtx(), getAD_Org_ID()); + int counterC_BPartner_ID = org.getLinkedC_BPartner_ID(); + if (counterC_BPartner_ID == 0) + return null; + // Business Partner needs to be linked to Org + MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), null); + int counterAD_Org_ID = bp.getAD_OrgBP_ID_Int(); + if (counterAD_Org_ID == 0) + return null; + + MBPartner counterBP = new MBPartner (getCtx(), counterC_BPartner_ID, null); + MOrgInfo counterOrgInfo = MOrgInfo.get(getCtx(), counterAD_Org_ID); + log.info("Counter BP=" + counterBP.getName()); + + // Document Type + int C_DocTypeTarget_ID = 0; + MDocTypeCounter counterDT = MDocTypeCounter.getCounterDocType(getCtx(), getC_DocType_ID()); + if (counterDT != null) + { + log.fine(counterDT.toString()); + if (!counterDT.isCreateCounter() || !counterDT.isValid()) + return null; + C_DocTypeTarget_ID = counterDT.getCounter_C_DocType_ID(); + } + else // indirect + { + C_DocTypeTarget_ID = MDocTypeCounter.getCounterDocType_ID(getCtx(), getC_DocType_ID()); + log.fine("Indirect C_DocTypeTarget_ID=" + C_DocTypeTarget_ID); + if (C_DocTypeTarget_ID <= 0) + return null; + } + + // Deep Copy + MInvoice counter = copyFrom(this, getDateInvoiced(), + C_DocTypeTarget_ID, !isSOTrx(), true, get_TrxName(), true); + // + counter.setAD_Org_ID(counterAD_Org_ID); + // counter.setM_Warehouse_ID(counterOrgInfo.getM_Warehouse_ID()); + // + counter.setBPartner(counterBP); + // Refernces (Should not be required + counter.setSalesRep_ID(getSalesRep_ID()); + counter.save(get_TrxName()); + + // Update copied lines + MInvoiceLine[] counterLines = counter.getLines(true); + for (int i = 0; i < counterLines.length; i++) + { + MInvoiceLine counterLine = counterLines[i]; + counterLine.setClientOrg(counter); + counterLine.setInvoice(counter); // copies header values (BP, etc.) + counterLine.setPrice(); + counterLine.setTax(); + // + counterLine.save(get_TrxName()); + } + + log.fine(counter.toString()); + + // Document Action + if (counterDT != null) + { + if (counterDT.getDocAction() != null) + { + counter.setDocAction(counterDT.getDocAction()); + counter.processIt(counterDT.getDocAction()); + counter.save(get_TrxName()); + } + } + return counter; + } // createCounterDoc + + /** + * Void Document. + * @return true if success + */ + public boolean voidIt() + { + log.info(toString()); + if (DOCSTATUS_Closed.equals(getDocStatus()) + || DOCSTATUS_Reversed.equals(getDocStatus()) + || DOCSTATUS_Voided.equals(getDocStatus())) + { + m_processMsg = "Document Closed: " + getDocStatus(); + setDocAction(DOCACTION_None); + return false; + } + + // Not Processed + if (DOCSTATUS_Drafted.equals(getDocStatus()) + || DOCSTATUS_Invalid.equals(getDocStatus()) + || DOCSTATUS_InProgress.equals(getDocStatus()) + || DOCSTATUS_Approved.equals(getDocStatus()) + || DOCSTATUS_NotApproved.equals(getDocStatus()) ) + { + // Set lines to 0 + MInvoiceLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MInvoiceLine line = lines[i]; + BigDecimal old = line.getQtyInvoiced(); + if (old.compareTo(Env.ZERO) != 0) + { + line.setQty(Env.ZERO); + line.setTaxAmt(Env.ZERO); + line.setLineNetAmt(Env.ZERO); + line.setLineTotalAmt(Env.ZERO); + line.addDescription(Msg.getMsg(getCtx(), "Voided") + " (" + old + ")"); + // Unlink Shipment + if (line.getM_InOutLine_ID() != 0) + { + MInOutLine ioLine = new MInOutLine(getCtx(), line.getM_InOutLine_ID(), get_TrxName()); + ioLine.setIsInvoiced(false); + ioLine.save(get_TrxName()); + line.setM_InOutLine_ID(0); + } + line.save(get_TrxName()); + } + } + addDescription(Msg.getMsg(getCtx(), "Voided")); + setIsPaid(true); + setC_Payment_ID(0); + } + else + { + return reverseCorrectIt(); + } + + setProcessed(true); + setDocAction(DOCACTION_None); + return true; + } // voidIt + + /** + * Close Document. + * @return true if success + */ + public boolean closeIt() + { + log.info(toString()); + setProcessed(true); + setDocAction(DOCACTION_None); + return true; + } // closeIt + + /** + * Reverse Correction - same date + * @return true if success + */ + public boolean reverseCorrectIt() + { + log.info(toString()); + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + if (!MPeriod.isOpen(getCtx(), getDateAcct(), dt.getDocBaseType())) + { + m_processMsg = "@PeriodClosed@"; + return false; + } + // + MAllocationHdr[] allocations = MAllocationHdr.getOfInvoice(getCtx(), + getC_Invoice_ID(), get_TrxName()); + for (int i = 0; i < allocations.length; i++) + { + allocations[i].setDocAction(DocAction.ACTION_Reverse_Correct); + allocations[i].reverseCorrectIt(); + allocations[i].save(get_TrxName()); + } + // Reverse/Delete Matching + if (!isSOTrx()) + { + MMatchInv[] mInv = MMatchInv.getInvoice(getCtx(), getC_Invoice_ID(), get_TrxName()); + for (int i = 0; i < mInv.length; i++) + mInv[i].delete(true); + MMatchPO[] mPO = MMatchPO.getInvoice(getCtx(), getC_Invoice_ID(), get_TrxName()); + for (int i = 0; i < mPO.length; i++) + { + if (mPO[i].getM_InOutLine_ID() == 0) + mPO[i].delete(true); + else + { + mPO[i].setC_InvoiceLine_ID(null); + mPO[i].save(get_TrxName()); + } + } + } + // + load(get_TrxName()); // reload allocation reversal info + + // Deep Copy + MInvoice reversal = copyFrom (this, getDateInvoiced(), + getC_DocType_ID(), isSOTrx(), false, get_TrxName(), true); + if (reversal == null) + { + m_processMsg = "Could not create Invoice Reversal"; + return false; + } + reversal.setReversal(true); + + // Reverse Line Qty + MInvoiceLine[] rLines = reversal.getLines(false); + for (int i = 0; i < rLines.length; i++) + { + MInvoiceLine rLine = rLines[i]; + rLine.setQtyEntered(rLine.getQtyEntered().negate()); + rLine.setQtyInvoiced(rLine.getQtyInvoiced().negate()); + rLine.setLineNetAmt(rLine.getLineNetAmt().negate()); + if (rLine.getTaxAmt() != null && rLine.getTaxAmt().compareTo(Env.ZERO) != 0) + rLine.setTaxAmt(rLine.getTaxAmt().negate()); + if (rLine.getLineTotalAmt() != null && rLine.getLineTotalAmt().compareTo(Env.ZERO) != 0) + rLine.setLineTotalAmt(rLine.getLineTotalAmt().negate()); + if (!rLine.save(get_TrxName())) + { + m_processMsg = "Could not correct Invoice Reversal Line"; + return false; + } + } + reversal.setC_Order_ID(getC_Order_ID()); + reversal.addDescription("{->" + getDocumentNo() + ")"); + // + if (!reversal.processIt(DocAction.ACTION_Complete)) + { + m_processMsg = "Reversal ERROR: " + reversal.getProcessMsg(); + return false; + } + reversal.setC_Payment_ID(0); + reversal.setIsPaid(true); + reversal.closeIt(); + reversal.setDocStatus(DOCSTATUS_Reversed); + reversal.setDocAction(DOCACTION_None); + reversal.save(get_TrxName()); + m_processMsg = reversal.getDocumentNo(); + // + addDescription("(" + reversal.getDocumentNo() + "<-)"); + + // Clean up Reversed (this) + MInvoiceLine[] iLines = getLines(false); + for (int i = 0; i < iLines.length; i++) + { + MInvoiceLine iLine = iLines[i]; + if (iLine.getM_InOutLine_ID() != 0) + { + MInOutLine ioLine = new MInOutLine(getCtx(), iLine.getM_InOutLine_ID(), get_TrxName()); + ioLine.setIsInvoiced(false); + ioLine.save(get_TrxName()); + // Reconsiliation + iLine.setM_InOutLine_ID(0); + iLine.save(get_TrxName()); + } + } + setProcessed(true); + setDocStatus(DOCSTATUS_Reversed); // may come from void + setDocAction(DOCACTION_None); + setC_Payment_ID(0); + setIsPaid(true); + + // Create Allocation + MAllocationHdr alloc = new MAllocationHdr(getCtx(), false, getDateAcct(), + getC_Currency_ID(), + Msg.translate(getCtx(), "C_Invoice_ID") + ": " + getDocumentNo() + "/" + reversal.getDocumentNo(), + get_TrxName()); + alloc.setAD_Org_ID(getAD_Org_ID()); + if (alloc.save()) + { + // Amount + BigDecimal gt = getGrandTotal(true); + if (!isSOTrx()) + gt = gt.negate(); + // Orig Line + MAllocationLine aLine = new MAllocationLine (alloc, gt, + Env.ZERO, Env.ZERO, Env.ZERO); + aLine.setC_Invoice_ID(getC_Invoice_ID()); + aLine.save(); + // Reversal Line + MAllocationLine rLine = new MAllocationLine (alloc, gt.negate(), + Env.ZERO, Env.ZERO, Env.ZERO); + rLine.setC_Invoice_ID(reversal.getC_Invoice_ID()); + rLine.save(); + // Process It + if (alloc.processIt(DocAction.ACTION_Complete)) + alloc.save(); + } + + return true; + } // reverseCorrectIt + + /** + * Reverse Accrual - none + * @return false + */ + public boolean reverseAccrualIt() + { + log.info(toString()); + return false; + } // reverseAccrualIt + + /** + * Re-activate + * @return false + */ + public boolean reActivateIt() + { + log.info(toString()); + return false; + } // reActivateIt + + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getDocumentNo()); + // : Grand Total = 123.00 (#1) + sb.append(": "). + append(Msg.translate(getCtx(),"GrandTotal")).append("=").append(getGrandTotal()) + .append(" (#").append(getLines(false).length).append(")"); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner (Responsible) + * @return AD_User_ID + */ + public int getDoc_User_ID() + { + return getSalesRep_ID(); + } // getDoc_User_ID + + /** + * Get Document Approval Amount + * @return amount + */ + public BigDecimal getApprovalAmt() + { + return getGrandTotal(); + } // getApprovalAmt + + +} // MInvoice diff --git a/base/src/org/compiere/model/MInvoiceBatch.java b/base/src/org/compiere/model/MInvoiceBatch.java new file mode 100644 index 0000000000..d0dabbb180 --- /dev/null +++ b/base/src/org/compiere/model/MInvoiceBatch.java @@ -0,0 +1,134 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Invoice Batch Header Model + * + * @author Jorg Janke + * @version $Id: MInvoiceBatch.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MInvoiceBatch extends X_C_InvoiceBatch +{ + + /** + * Standard Constructor + * @param ctx context + * @param C_InvoiceBatch_ID id + * @param trxName trx + */ + public MInvoiceBatch (Properties ctx, int C_InvoiceBatch_ID, String trxName) + { + super (ctx, C_InvoiceBatch_ID, trxName); + if (C_InvoiceBatch_ID == 0) + { + // setDocumentNo (null); + // setC_Currency_ID (0); // @$C_Currency_ID@ + setControlAmt (Env.ZERO); // 0 + setDateDoc (new Timestamp(System.currentTimeMillis())); // @#Date@ + setDocumentAmt (Env.ZERO); + setIsSOTrx (false); // N + setProcessed (false); + // setSalesRep_ID (0); + } + } // MInvoiceBatch + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MInvoiceBatch (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MInvoiceBatch + + /** The Lines */ + private MInvoiceBatchLine[] m_lines = null; + + + /** + * Get Lines + * @param reload reload data + * @return array of lines + */ + public MInvoiceBatchLine[] getLines (boolean reload) + { + if (m_lines != null && !reload) + return m_lines; + String sql = "SELECT * FROM C_InvoiceBatchLine WHERE C_InvoiceBatch_ID=? ORDER BY Line"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_InvoiceBatch_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + list.add (new MInvoiceBatchLine (getCtx(), rs, get_TrxName())); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + m_lines = new MInvoiceBatchLine[list.size ()]; + list.toArray (m_lines); + return m_lines; + } // getLines + + + /** + * Set Processed + * @param processed processed + */ + public void setProcessed (boolean processed) + { + super.setProcessed (processed); + if (get_ID() == 0) + return; + String set = "SET Processed='" + + (processed ? "Y" : "N") + + "' WHERE C_InvoiceBatch_ID=" + getC_InvoiceBatch_ID(); + int noLine = DB.executeUpdate("UPDATE C_InvoiceBatchLine " + set, get_TrxName()); + m_lines = null; + log.fine(processed + " - Lines=" + noLine); + } // setProcessed + +} // MInvoiceBatch diff --git a/base/src/org/compiere/model/MInvoiceBatchLine.java b/base/src/org/compiere/model/MInvoiceBatchLine.java new file mode 100644 index 0000000000..98cbac3af0 --- /dev/null +++ b/base/src/org/compiere/model/MInvoiceBatchLine.java @@ -0,0 +1,114 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + + +/** + * Invoice Batch Line Model + * + * @author Jorg Janke + * @version $Id: MInvoiceBatchLine.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MInvoiceBatchLine extends X_C_InvoiceBatchLine +{ + /** + * Standard Constructor + * @param ctx context + * @param C_InvoiceBatchLine_ID id + * @param trxName trx + */ + public MInvoiceBatchLine (Properties ctx, int C_InvoiceBatchLine_ID, + String trxName) + { + super (ctx, C_InvoiceBatchLine_ID, trxName); + if (C_InvoiceBatchLine_ID == 0) + { + // setC_InvoiceBatch_ID (0); + /** + setC_BPartner_ID (0); + setC_BPartner_Location_ID (0); + setC_Charge_ID (0); + setC_DocType_ID (0); // @C_DocType_ID@ + setC_Tax_ID (0); + setDocumentNo (null); + setLine (0); // @SQL=SELECT NVL(MAX(Line),0)+10 AS DefaultValue FROM C_InvoiceBatchLine WHERE C_InvoiceBatch_ID=@C_InvoiceBatch_ID@ + **/ + setDateAcct (new Timestamp(System.currentTimeMillis())); // @DateDoc@ + setDateInvoiced (new Timestamp(System.currentTimeMillis())); // @DateDoc@ + setIsTaxIncluded (false); + setLineNetAmt (Env.ZERO); + setLineTotalAmt (Env.ZERO); + setPriceEntered (Env.ZERO); + setQtyEntered (Env.ONE); // 1 + setTaxAmt (Env.ZERO); + setProcessed (false); + } + } // MInvoiceBatchLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MInvoiceBatchLine (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MInvoiceBatchLine + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Amount + if (getPriceEntered().signum() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "PriceEntered")); + return false; + } + return true; + } // beforeSave + + /** + * After Save. + * Update Header + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (success) + { + String sql = "UPDATE C_InvoiceBatch h " + + "SET DocumentAmt = NVL((SELECT SUM(LineTotalAmt) FROM C_InvoiceBatchLine l " + + "WHERE h.C_InvoiceBatch_ID=l.C_InvoiceBatch_ID AND l.IsActive='Y'),0) " + + "WHERE C_InvoiceBatch_ID=" + getC_InvoiceBatch_ID(); + DB.executeUpdate(sql, get_TrxName()); + } + return success; + } // afterSave + +} // MInvoiceBatchLine diff --git a/base/src/org/compiere/model/MInvoiceLine.java b/base/src/org/compiere/model/MInvoiceLine.java new file mode 100644 index 0000000000..9327bca66e --- /dev/null +++ b/base/src/org/compiere/model/MInvoiceLine.java @@ -0,0 +1,1065 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Invoice Line Model + * + * @author Jorg Janke + * @version $Id: MInvoiceLine.java,v 1.5 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MInvoiceLine extends X_C_InvoiceLine +{ + /** + * Get Invoice Line referencing InOut Line + * @param sLine shipment line + * @return (first) invoice line + */ + public static MInvoiceLine getOfInOutLine (MInOutLine sLine) + { + if (sLine == null) + return null; + MInvoiceLine retValue = null; + String sql = "SELECT * FROM C_InvoiceLine WHERE M_InOutLine_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, sLine.get_TrxName()); + pstmt.setInt (1, sLine.getM_InOutLine_ID()); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + retValue = new MInvoiceLine (sLine.getCtx(), rs, sLine.get_TrxName()); + if (rs.next()) + s_log.warning("More than one C_InvoiceLine of " + sLine); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return retValue; + } // getOfInOutLine + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MInvoiceLine.class); + + + /************************************************************************** + * Invoice Line Constructor + * @param ctx context + * @param C_InvoiceLine_ID invoice line or 0 + * @param trxName transaction name + */ + public MInvoiceLine (Properties ctx, int C_InvoiceLine_ID, String trxName) + { + super (ctx, C_InvoiceLine_ID, trxName); + if (C_InvoiceLine_ID == 0) + { + setIsDescription(false); + setIsPrinted (true); + setLineNetAmt (Env.ZERO); + setPriceEntered (Env.ZERO); + setPriceActual (Env.ZERO); + setPriceLimit (Env.ZERO); + setPriceList (Env.ZERO); + setM_AttributeSetInstance_ID(0); + setTaxAmt(Env.ZERO); + // + setQtyEntered(Env.ZERO); + setQtyInvoiced(Env.ZERO); + } + } // MInvoiceLine + + /** + * Parent Constructor + * @param invoice parent + */ + public MInvoiceLine (MInvoice invoice) + { + this (invoice.getCtx(), 0, invoice.get_TrxName()); + if (invoice.get_ID() == 0) + throw new IllegalArgumentException("Header not saved"); + setClientOrg(invoice.getAD_Client_ID(), invoice.getAD_Org_ID()); + setC_Invoice_ID (invoice.getC_Invoice_ID()); + setInvoice(invoice); + } // MInvoiceLine + + + /** + * Load Constructor + * @param ctx context + * @param rs result set record + * @param trxName transaction + */ + public MInvoiceLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MInvoiceLine + + private int m_M_PriceList_ID = 0; + private Timestamp m_DateInvoiced = null; + private int m_C_BPartner_ID = 0; + private int m_C_BPartner_Location_ID = 0; + private boolean m_IsSOTrx = true; + private boolean m_priceSet = false; + private MProduct m_product = null; + + /** Cached Name of the line */ + private String m_name = null; + /** Cached Precision */ + private Integer m_precision = null; + /** Product Pricing */ + private MProductPricing m_productPricing = null; + /** Parent */ + private MInvoice m_parent = null; + + /** + * Set Defaults from Order. + * Called also from copy lines from invoice + * Does not set Parent !! + * @param invoice invoice + */ + public void setInvoice (MInvoice invoice) + { + m_parent = invoice; + m_M_PriceList_ID = invoice.getM_PriceList_ID(); + m_DateInvoiced = invoice.getDateInvoiced(); + m_C_BPartner_ID = invoice.getC_BPartner_ID(); + m_C_BPartner_Location_ID = invoice.getC_BPartner_Location_ID(); + m_IsSOTrx = invoice.isSOTrx(); + m_precision = new Integer(invoice.getPrecision()); + } // setOrder + + /** + * Get Parent + * @return parent + */ + public MInvoice getParent() + { + if (m_parent == null) + m_parent = new MInvoice(getCtx(), getC_Invoice_ID(), get_TrxName()); + return m_parent; + } // getParent + + /** + * Set values from Order Line. + * Does not set quantity! + * @param oLine line + */ + public void setOrderLine (MOrderLine oLine) + { + setC_OrderLine_ID(oLine.getC_OrderLine_ID()); + // + setLine(oLine.getLine()); + setIsDescription(oLine.isDescription()); + setDescription(oLine.getDescription()); + // + setC_Charge_ID(oLine.getC_Charge_ID()); + // + setM_Product_ID(oLine.getM_Product_ID()); + setM_AttributeSetInstance_ID(oLine.getM_AttributeSetInstance_ID()); + setS_ResourceAssignment_ID(oLine.getS_ResourceAssignment_ID()); + setC_UOM_ID(oLine.getC_UOM_ID()); + // + setPriceEntered(oLine.getPriceEntered()); + setPriceActual(oLine.getPriceActual()); + setPriceLimit(oLine.getPriceLimit()); + setPriceList(oLine.getPriceList()); + // + setC_Tax_ID(oLine.getC_Tax_ID()); + setLineNetAmt(oLine.getLineNetAmt()); + // + setC_Project_ID(oLine.getC_Project_ID()); + setC_ProjectPhase_ID(oLine.getC_ProjectPhase_ID()); + setC_ProjectTask_ID(oLine.getC_ProjectTask_ID()); + setC_Activity_ID(oLine.getC_Activity_ID()); + setC_Campaign_ID(oLine.getC_Campaign_ID()); + setAD_OrgTrx_ID(oLine.getAD_OrgTrx_ID()); + setUser1_ID(oLine.getUser1_ID()); + setUser2_ID(oLine.getUser2_ID()); + // + setRRAmt(oLine.getRRAmt()); + setRRStartDate(oLine.getRRStartDate()); + } // setOrderLine + + /** + * Set values from Shipment Line. + * Does not set quantity! + * @param sLine ship line + */ + public void setShipLine (MInOutLine sLine) + { + setM_InOutLine_ID(sLine.getM_InOutLine_ID()); + setC_OrderLine_ID(sLine.getC_OrderLine_ID()); + + // + setLine(sLine.getLine()); + setIsDescription(sLine.isDescription()); + setDescription(sLine.getDescription()); + // + setM_Product_ID(sLine.getM_Product_ID()); + setC_UOM_ID(sLine.getC_UOM_ID()); + setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); + // setS_ResourceAssignment_ID(sLine.getS_ResourceAssignment_ID()); + setC_Charge_ID(sLine.getC_Charge_ID()); + // + int C_OrderLine_ID = sLine.getC_OrderLine_ID(); + if (C_OrderLine_ID != 0) + { + MOrderLine oLine = new MOrderLine (getCtx(), C_OrderLine_ID, get_TrxName()); + setS_ResourceAssignment_ID(oLine.getS_ResourceAssignment_ID()); + // + setPriceEntered(oLine.getPriceEntered()); + setPriceActual(oLine.getPriceActual()); + setPriceLimit(oLine.getPriceLimit()); + setPriceList(oLine.getPriceList()); + // + setC_Tax_ID(oLine.getC_Tax_ID()); + setLineNetAmt(oLine.getLineNetAmt()); + setC_Project_ID(oLine.getC_Project_ID()); + } + else + { + setPrice(); + setTax(); + } + // + setC_Project_ID(sLine.getC_Project_ID()); + setC_ProjectPhase_ID(sLine.getC_ProjectPhase_ID()); + setC_ProjectTask_ID(sLine.getC_ProjectTask_ID()); + setC_Activity_ID(sLine.getC_Activity_ID()); + setC_Campaign_ID(sLine.getC_Campaign_ID()); + setAD_OrgTrx_ID(sLine.getAD_OrgTrx_ID()); + setUser1_ID(sLine.getUser1_ID()); + setUser2_ID(sLine.getUser2_ID()); + } // setShipLine + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * Set M_AttributeSetInstance_ID + * @param M_AttributeSetInstance_ID id + */ + public void setM_AttributeSetInstance_ID (int M_AttributeSetInstance_ID) + { + if (M_AttributeSetInstance_ID == 0) // 0 is valid ID + set_Value("M_AttributeSetInstance_ID", new Integer(0)); + else + super.setM_AttributeSetInstance_ID (M_AttributeSetInstance_ID); + } // setM_AttributeSetInstance_ID + + + /************************************************************************** + * Set Price for Product and PriceList. + * Uses standard SO price list of not set by invoice constructor + */ + public void setPrice() + { + if (getM_Product_ID() == 0 || isDescription()) + return; + if (m_M_PriceList_ID == 0 || m_C_BPartner_ID == 0) + setInvoice(getParent()); + if (m_M_PriceList_ID == 0 || m_C_BPartner_ID == 0) + throw new IllegalStateException("setPrice - PriceList unknown!"); + setPrice (m_M_PriceList_ID, m_C_BPartner_ID); + } // setPrice + + /** + * Set Price for Product and PriceList + * @param M_PriceList_ID price list + * @param C_BPartner_ID business partner + */ + public void setPrice (int M_PriceList_ID, int C_BPartner_ID) + { + if (getM_Product_ID() == 0 || isDescription()) + return; + // + log.fine("M_PriceList_ID=" + M_PriceList_ID); + m_productPricing = new MProductPricing (getM_Product_ID(), + C_BPartner_ID, getQtyInvoiced(), m_IsSOTrx); + m_productPricing.setM_PriceList_ID(M_PriceList_ID); + m_productPricing.setPriceDate(m_DateInvoiced); + // + setPriceActual (m_productPricing.getPriceStd()); + setPriceList (m_productPricing.getPriceList()); + setPriceLimit (m_productPricing.getPriceLimit()); + // + if (getQtyEntered().compareTo(getQtyInvoiced()) == 0) + setPriceEntered(getPriceActual()); + else + setPriceEntered(getPriceActual().multiply(getQtyInvoiced() + .divide(getQtyEntered(), 6, BigDecimal.ROUND_HALF_UP))); // precision + // + if (getC_UOM_ID() == 0) + setC_UOM_ID(m_productPricing.getC_UOM_ID()); + // + m_priceSet = true; + } // setPrice + + /** + * Set Price Entered/Actual. + * Use this Method if the Line UOM is the Product UOM + * @param PriceActual price + */ + public void setPrice (BigDecimal PriceActual) + { + setPriceEntered(PriceActual); + setPriceActual (PriceActual); + } // setPrice + + /** + * Set Price Actual. + * (actual price is not updateable) + * @param PriceActual actual price + */ + public void setPriceActual (BigDecimal PriceActual) + { + if (PriceActual == null) + throw new IllegalArgumentException ("PriceActual is mandatory"); + set_ValueNoCheck("PriceActual", PriceActual); + } // setPriceActual + + + /** + * Set Tax - requires Warehouse + * @return true if found + */ + public boolean setTax() + { + if (isDescription()) + return true; + // + int M_Warehouse_ID = Env.getContextAsInt(getCtx(), "#M_Warehouse_ID"); + // + int C_Tax_ID = Tax.get(getCtx(), getM_Product_ID(), getC_Charge_ID() , m_DateInvoiced, m_DateInvoiced, + getAD_Org_ID(), M_Warehouse_ID, + m_C_BPartner_Location_ID, // should be bill to + m_C_BPartner_Location_ID, m_IsSOTrx); + if (C_Tax_ID == 0) + { + log.log(Level.SEVERE, "No Tax found"); + return false; + } + setC_Tax_ID (C_Tax_ID); + if (m_IsSOTrx) + { + } + return true; + } // setTax + + + /** + * Calculare Tax Amt. + * Assumes Line Net is calculated + */ + public void setTaxAmt () + { + BigDecimal TaxAmt = Env.ZERO; + if (getC_Tax_ID() == 0) + return; + // setLineNetAmt(); + MTax tax = MTax.get (getCtx(), getC_Tax_ID()); + if (tax.isDocumentLevel() && m_IsSOTrx) // AR Inv Tax + return; + // + TaxAmt = tax.calculateTax(getLineNetAmt(), isTaxIncluded(), getPrecision()); + if (isTaxIncluded()) + setLineTotalAmt(getLineNetAmt()); + else + setLineTotalAmt(getLineNetAmt().add(TaxAmt)); + super.setTaxAmt (TaxAmt); + } // setTaxAmt + + /** + * Calculate Extended Amt. + * May or may not include tax + */ + public void setLineNetAmt () + { + // Calculations & Rounding + BigDecimal net = getPriceActual().multiply(getQtyInvoiced()); + if (net.scale() > getPrecision()) + net = net.setScale(getPrecision(), BigDecimal.ROUND_HALF_UP); + super.setLineNetAmt (net); + } // setLineNetAmt + + /** + * Set Qty Invoiced/Entered. + * @param Qty Invoiced/Ordered + */ + public void setQty (int Qty) + { + setQty(new BigDecimal(Qty)); + } // setQtyInvoiced + + /** + * Set Qty Invoiced + * @param Qty Invoiced/Entered + */ + public void setQty (BigDecimal Qty) + { + setQtyEntered(Qty); + setQtyInvoiced(getQtyEntered()); + } // setQtyInvoiced + + /** + * Set Qty Entered - enforce entered UOM + * @param QtyEntered + */ + public void setQtyEntered (BigDecimal QtyEntered) + { + if (QtyEntered != null && getC_UOM_ID() != 0) + { + int precision = MUOM.getPrecision(getCtx(), getC_UOM_ID()); + QtyEntered = QtyEntered.setScale(precision, BigDecimal.ROUND_HALF_UP); + } + super.setQtyEntered (QtyEntered); + } // setQtyEntered + + /** + * Set Qty Invoiced - enforce Product UOM + * @param QtyInvoiced + */ + public void setQtyInvoiced (BigDecimal QtyInvoiced) + { + MProduct product = getProduct(); + if (QtyInvoiced != null && product != null) + { + int precision = product.getUOMPrecision(); + QtyInvoiced = QtyInvoiced.setScale(precision, BigDecimal.ROUND_HALF_UP); + } + super.setQtyInvoiced(QtyInvoiced); + } // setQtyInvoiced + + /** + * Set Product + * @param product product + */ + public void setProduct (MProduct product) + { + m_product = product; + if (m_product != null) + { + setM_Product_ID(m_product.getM_Product_ID()); + setC_UOM_ID (m_product.getC_UOM_ID()); + } + else + { + setM_Product_ID(0); + setC_UOM_ID (0); + } + setM_AttributeSetInstance_ID(0); + } // setProduct + + + /** + * Set M_Product_ID + * @param M_Product_ID product + * @param setUOM set UOM from product + */ + public void setM_Product_ID (int M_Product_ID, boolean setUOM) + { + if (setUOM) + setProduct(MProduct.get(getCtx(), M_Product_ID)); + else + super.setM_Product_ID (M_Product_ID); + setM_AttributeSetInstance_ID(0); + } // setM_Product_ID + + /** + * Set Product and UOM + * @param M_Product_ID product + * @param C_UOM_ID uom + */ + public void setM_Product_ID (int M_Product_ID, int C_UOM_ID) + { + super.setM_Product_ID (M_Product_ID); + super.setC_UOM_ID(C_UOM_ID); + setM_AttributeSetInstance_ID(0); + } // setM_Product_ID + + /** + * Get Product + * @return product or null + */ + public MProduct getProduct() + { + if (m_product == null && getM_Product_ID() != 0) + m_product = MProduct.get (getCtx(), getM_Product_ID()); + return m_product; + } // getProduct + + /** + * Get C_Project_ID + * @return project + */ + public int getC_Project_ID() + { + int ii = super.getC_Project_ID (); + if (ii == 0) + ii = getParent().getC_Project_ID(); + return ii; + } // getC_Project_ID + + /** + * Get C_Activity_ID + * @return Activity + */ + public int getC_Activity_ID() + { + int ii = super.getC_Activity_ID (); + if (ii == 0) + ii = getParent().getC_Activity_ID(); + return ii; + } // getC_Activity_ID + + /** + * Get C_Campaign_ID + * @return Campaign + */ + public int getC_Campaign_ID() + { + int ii = super.getC_Campaign_ID (); + if (ii == 0) + ii = getParent().getC_Campaign_ID(); + return ii; + } // getC_Campaign_ID + + /** + * Get User2_ID + * @return User2 + */ + public int getUser1_ID () + { + int ii = super.getUser1_ID (); + if (ii == 0) + ii = getParent().getUser1_ID(); + return ii; + } // getUser1_ID + + /** + * Get User2_ID + * @return User2 + */ + public int getUser2_ID () + { + int ii = super.getUser2_ID (); + if (ii == 0) + ii = getParent().getUser2_ID(); + return ii; + } // getUser2_ID + + /** + * Get AD_OrgTrx_ID + * @return trx org + */ + public int getAD_OrgTrx_ID() + { + int ii = super.getAD_OrgTrx_ID(); + if (ii == 0) + ii = getParent().getAD_OrgTrx_ID(); + return ii; + } // getAD_OrgTrx_ID + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MInvoiceLine[") + .append(get_ID()).append(",").append(getLine()) + .append(",QtyInvoiced=").append(getQtyInvoiced()) + .append(",LineNetAmt=").append(getLineNetAmt()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Get (Product/Charge) Name + * @return name + */ + public String getName () + { + if (m_name == null) + { + String sql = "SELECT COALESCE (p.Name, c.Name) " + + "FROM C_InvoiceLine il" + + " LEFT OUTER JOIN M_Product p ON (il.M_Product_ID=p.M_Product_ID)" + + " LEFT OUTER JOIN C_Charge C ON (il.C_Charge_ID=c.C_Charge_ID) " + + "WHERE C_InvoiceLine_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_InvoiceLine_ID()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + m_name = rs.getString(1); + rs.close(); + pstmt.close(); + pstmt = null; + if (m_name == null) + m_name = "??"; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getName", e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + } + return m_name; + } // getName + + /** + * Set Temporary (cached) Name + * @param tempName Cached Name + */ + public void setName (String tempName) + { + m_name = tempName; + } // setName + + /** + * Get Description Text. + * For jsp access (vs. isDescription) + * @return description + */ + public String getDescriptionText() + { + return super.getDescription(); + } // getDescriptionText + + /** + * Get Currency Precision + * @return precision + */ + public int getPrecision() + { + if (m_precision != null) + return m_precision.intValue(); + + String sql = "SELECT c.StdPrecision " + + "FROM C_Currency c INNER JOIN C_Invoice x ON (x.C_Currency_ID=c.C_Currency_ID) " + + "WHERE x.C_Invoice_ID=?"; + int i = DB.getSQLValue(get_TrxName(), sql, getC_Invoice_ID()); + if (i < 0) + { + log.warning("getPrecision = " + i + " - set to 2"); + i = 2; + } + m_precision = new Integer(i); + return m_precision.intValue(); + } // getPrecision + + /** + * Is Tax Included in Amount + * @return true if tax is included + */ + public boolean isTaxIncluded() + { + if (m_M_PriceList_ID == 0) + { + m_M_PriceList_ID = DB.getSQLValue(get_TrxName(), + "SELECT M_PriceList_ID FROM C_Invoice WHERE C_Invoice_ID=?", + getC_Invoice_ID()); + } + MPriceList pl = MPriceList.get(getCtx(), m_M_PriceList_ID, get_TrxName()); + return pl.isTaxIncluded(); + } // isTaxIncluded + + + /************************************************************************** + * Before Save + * @param newRecord + * @return true if save + */ + protected boolean beforeSave (boolean newRecord) + { + log.fine("New=" + newRecord); + // Charge + if (getC_Charge_ID() != 0) + { + if (getM_Product_ID() != 0) + setM_Product_ID(0); + } + else // Set Product Price + { + if (!m_priceSet + && Env.ZERO.compareTo(getPriceActual()) == 0 + && Env.ZERO.compareTo(getPriceList()) == 0) + setPrice(); + } + + // Set Tax + if (getC_Tax_ID() == 0) + setTax(); + + // Get Line No + if (getLine() == 0) + { + String sql = "SELECT COALESCE(MAX(Line),0)+10 FROM C_InvoiceLine WHERE C_Invoice_ID=?"; + int ii = DB.getSQLValue (get_TrxName(), sql, getC_Invoice_ID()); + setLine (ii); + } + // UOM + if (getC_UOM_ID() == 0) + { + int C_UOM_ID = MUOM.getDefault_UOM_ID(getCtx()); + if (C_UOM_ID > 0) + setC_UOM_ID (C_UOM_ID); + } + // Qty Precision + if (newRecord || is_ValueChanged("QtyEntered")) + setQtyEntered(getQtyEntered()); + if (newRecord || is_ValueChanged("QtyInvoiced")) + setQtyInvoiced(getQtyInvoiced()); + + // Calculations & Rounding + setLineNetAmt(); + if (getTaxAmt().compareTo(Env.ZERO) == 0) + setTaxAmt(); + // + return true; + } // beforeSave + + + /** + * After Save + * @param newRecord new + * @param success success + * @return saved + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + if (!newRecord && is_ValueChanged("C_Tax_ID")) + { + // Recalculate Tax for old Tax + MInvoiceTax tax = MInvoiceTax.get (this, getPrecision(), + true, get_TrxName()); // old Tax + if (tax != null) + { + if (!tax.calculateTaxFromLines()) + return false; + if (!tax.save(get_TrxName())) + return true; + } + } + return updateHeaderTax(); + } // afterSave + + /** + * After Delete + * @param success success + * @return deleted + */ + protected boolean afterDelete (boolean success) + { + if (!success) + return success; + return updateHeaderTax(); + } // afterDelete + + /** + * Update Tax & Header + * @return true if header updated with tax + */ + private boolean updateHeaderTax() + { + // Recalculate Tax for this Tax + MInvoiceTax tax = MInvoiceTax.get (this, getPrecision(), + false, get_TrxName()); // current Tax + if (tax != null) + { + if (!tax.calculateTaxFromLines()) + return false; + if (!tax.save(get_TrxName())) + return false; + } + + // Update Invoice Header + String sql = "UPDATE C_Invoice i" + + " SET TotalLines=" + + "(SELECT COALESCE(SUM(LineNetAmt),0) FROM C_InvoiceLine il WHERE i.C_Invoice_ID=il.C_Invoice_ID) " + + "WHERE C_Invoice_ID=" + getC_Invoice_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + if (no != 1) + log.warning("(1) #" + no); + + if (isTaxIncluded()) + sql = "UPDATE C_Invoice i " + + " SET GrandTotal=TotalLines " + + "WHERE C_Invoice_ID=" + getC_Invoice_ID(); + else + sql = "UPDATE C_Invoice i " + + " SET GrandTotal=TotalLines+" + + "(SELECT COALESCE(SUM(TaxAmt),0) FROM C_InvoiceTax it WHERE i.C_Invoice_ID=it.C_Invoice_ID) " + + "WHERE C_Invoice_ID=" + getC_Invoice_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 1) + log.warning("(2) #" + no); + m_parent = null; + + return no == 1; + } // updateHeaderTax + + + /************************************************************************** + * Allocate Landed Costs + * @return error message or "" + */ + public String allocateLandedCosts() + { + if (isProcessed()) + return "Processed"; + MLandedCost[] lcs = MLandedCost.getLandedCosts(this); + if (lcs.length == 0) + return ""; + String sql = "DELETE C_LandedCostAllocation WHERE C_InvoiceLine_ID=" + getC_InvoiceLine_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.info("Deleted #" + no); + + int inserted = 0; + // *** Single Criteria *** + if (lcs.length == 1) + { + MLandedCost lc = lcs[0]; + if (lc.getM_InOut_ID() != 0) + { + // Create List + ArrayList list = new ArrayList(); + MInOut ship = new MInOut (getCtx(), lc.getM_InOut_ID(), get_TrxName()); + MInOutLine[] lines = ship.getLines(); + for (int i = 0; i < lines.length; i++) + { + if (lines[i].isDescription() || lines[i].getM_Product_ID() == 0) + continue; + if (lc.getM_Product_ID() == 0 + || lc.getM_Product_ID() == lines[i].getM_Product_ID()) + list.add(lines[i]); + } + if (list.size() == 0) + return "No Matching Lines (with Product) in Shipment"; + // Calculate total & base + BigDecimal total = Env.ZERO; + for (int i = 0; i < list.size(); i++) + { + MInOutLine iol = (MInOutLine)list.get(i); + total = total.add(iol.getBase(lc.getLandedCostDistribution())); + } + if (total.signum() == 0) + return "Total of Base values is 0 - " + lc.getLandedCostDistribution(); + // Create Allocations + for (int i = 0; i < list.size(); i++) + { + MInOutLine iol = (MInOutLine)list.get(i); + MLandedCostAllocation lca = new MLandedCostAllocation (this, lc.getM_CostElement_ID()); + lca.setM_Product_ID(iol.getM_Product_ID()); + lca.setM_AttributeSetInstance_ID(iol.getM_AttributeSetInstance_ID()); + BigDecimal base = iol.getBase(lc.getLandedCostDistribution()); + lca.setBase(base); + if (base.signum() != 0) + { + double result = getLineNetAmt().multiply(base).doubleValue(); + result /= total.doubleValue(); + lca.setAmt(result, getPrecision()); + } + if (!lca.save()) + return "Cannot save line Allocation = " + lca; + inserted++; + } + log.info("Inserted " + inserted); + allocateLandedCostRounding(); + return ""; + } + // Single Line + else if (lc.getM_InOutLine_ID() != 0) + { + MInOutLine iol = new MInOutLine (getCtx(), lc.getM_InOutLine_ID(), get_TrxName()); + if (iol.isDescription() || iol.getM_Product_ID() == 0) + return "Invalid Receipt Line - " + iol; + MLandedCostAllocation lca = new MLandedCostAllocation (this, lc.getM_CostElement_ID()); + lca.setM_Product_ID(iol.getM_Product_ID()); + lca.setM_AttributeSetInstance_ID(iol.getM_AttributeSetInstance_ID()); + lca.setAmt(getLineNetAmt()); + if (lca.save()) + return ""; + return "Cannot save single line Allocation = " + lc; + } + // Single Product + else if (lc.getM_Product_ID() != 0) + { + MLandedCostAllocation lca = new MLandedCostAllocation (this, lc.getM_CostElement_ID()); + lca.setM_Product_ID(lc.getM_Product_ID()); // No ASI + lca.setAmt(getLineNetAmt()); + if (lca.save()) + return ""; + return "Cannot save Product Allocation = " + lc; + } + else + return "No Reference for " + lc; + } + + // *** Multiple Criteria *** + String LandedCostDistribution = lcs[0].getLandedCostDistribution(); + int M_CostElement_ID = lcs[0].getM_CostElement_ID(); + for (int i = 0; i < lcs.length; i++) + { + MLandedCost lc = lcs[i]; + if (!LandedCostDistribution.equals(lc.getLandedCostDistribution())) + return "Multiple Landed Cost Rules must have consistent Landed Cost Distribution"; + if (lc.getM_Product_ID() != 0 && lc.getM_InOut_ID() == 0 && lc.getM_InOutLine_ID() == 0) + return "Multiple Landed Cost Rules cannot directly allocate to a Product"; + if (M_CostElement_ID != lc.getM_CostElement_ID()) + return "Multiple Landed Cost Rules cannot different Cost Elements"; + } + // Create List + ArrayList list = new ArrayList(); + for (int ii = 0; ii < lcs.length; ii++) + { + MLandedCost lc = lcs[ii]; + if (lc.getM_InOut_ID() != 0 && lc.getM_InOutLine_ID() == 0) // entire receipt + { + MInOut ship = new MInOut (getCtx(), lc.getM_InOut_ID(), get_TrxName()); + MInOutLine[] lines = ship.getLines(); + for (int i = 0; i < lines.length; i++) + { + if (lines[i].isDescription() // decription or no product + || lines[i].getM_Product_ID() == 0) + continue; + if (lc.getM_Product_ID() == 0 // no restriction or product match + || lc.getM_Product_ID() == lines[i].getM_Product_ID()) + list.add(lines[i]); + } + } + else if (lc.getM_InOutLine_ID() != 0) // receipt line + { + MInOutLine iol = new MInOutLine (getCtx(), lc.getM_InOutLine_ID(), get_TrxName()); + if (!iol.isDescription() && iol.getM_Product_ID() != 0) + list.add(iol); + } + } + if (list.size() == 0) + return "No Matching Lines (with Product)"; + // Calculate total & base + BigDecimal total = Env.ZERO; + for (int i = 0; i < list.size(); i++) + { + MInOutLine iol = (MInOutLine)list.get(i); + total = total.add(iol.getBase(LandedCostDistribution)); + } + if (total.signum() == 0) + return "Total of Base values is 0 - " + LandedCostDistribution; + // Create Allocations + for (int i = 0; i < list.size(); i++) + { + MInOutLine iol = (MInOutLine)list.get(i); + MLandedCostAllocation lca = new MLandedCostAllocation (this, lcs[0].getM_CostElement_ID()); + lca.setM_Product_ID(iol.getM_Product_ID()); + lca.setM_AttributeSetInstance_ID(iol.getM_AttributeSetInstance_ID()); + BigDecimal base = iol.getBase(LandedCostDistribution); + lca.setBase(base); + if (base.signum() != 0) + { + double result = getLineNetAmt().multiply(base).doubleValue(); + result /= total.doubleValue(); + lca.setAmt(result, getPrecision()); + } + if (!lca.save()) + return "Cannot save line Allocation = " + lca; + inserted++; + } + + log.info("Inserted " + inserted); + allocateLandedCostRounding(); + return ""; + } // allocate Costs + + /** + * Allocate Landed Cost - Enforce Rounding + */ + private void allocateLandedCostRounding() + { + MLandedCostAllocation[] allocations = MLandedCostAllocation.getOfInvoiceLine( + getCtx(), getC_InvoiceLine_ID(), get_TrxName()); + MLandedCostAllocation largestAmtAllocation = null; + BigDecimal allocationAmt = Env.ZERO; + for (int i = 0; i < allocations.length; i++) + { + MLandedCostAllocation allocation = allocations[i]; + if (largestAmtAllocation == null + || allocation.getAmt().compareTo(largestAmtAllocation.getAmt()) > 0) + largestAmtAllocation = allocation; + allocationAmt = allocationAmt.add(allocation.getAmt()); + } + BigDecimal difference = getLineNetAmt().subtract(allocationAmt); + if (difference.signum() != 0) + { + largestAmtAllocation.setAmt(largestAmtAllocation.getAmt().add(difference)); + largestAmtAllocation.save(); + log.config("Difference=" + difference + + ", C_LandedCostAllocation_ID=" + largestAmtAllocation.getC_LandedCostAllocation_ID() + + ", Amt" + largestAmtAllocation.getAmt()); + } + } // allocateLandedCostRounding + +} // MInvoiceLine diff --git a/base/src/org/compiere/model/MInvoicePaySchedule.java b/base/src/org/compiere/model/MInvoicePaySchedule.java new file mode 100644 index 0000000000..e672e5404f --- /dev/null +++ b/base/src/org/compiere/model/MInvoicePaySchedule.java @@ -0,0 +1,239 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Invoice Payment Schedule Model + * + * @author Jorg Janke + * @version $Id: MInvoicePaySchedule.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MInvoicePaySchedule extends X_C_InvoicePaySchedule +{ + /** + * Get Payment Schedule of the invoice + * @param ctx context + * @param C_Invoice_ID invoice id (direct) + * @param C_InvoicePaySchedule_ID id (indirect) + * @param trxName transaction + * @return array of schedule + */ + public static MInvoicePaySchedule[] getInvoicePaySchedule(Properties ctx, + int C_Invoice_ID, int C_InvoicePaySchedule_ID, String trxName) + { + String sql = "SELECT * FROM C_InvoicePaySchedule ips "; + if (C_Invoice_ID != 0) + sql += "WHERE C_Invoice_ID=? "; + else + sql += "WHERE EXISTS (SELECT * FROM C_InvoicePaySchedule x" + + " WHERE x.C_InvoicePaySchedule_ID=? AND ips.C_Invoice_ID=x.C_Invoice_ID) "; + sql += "ORDER BY DueDate"; + // + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, trxName); + if (C_Invoice_ID != 0) + pstmt.setInt(1, C_Invoice_ID); + else + pstmt.setInt(1, C_InvoicePaySchedule_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + list.add (new MInvoicePaySchedule(ctx, rs, trxName)); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "getInvoicePaySchedule", e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + MInvoicePaySchedule[] retValue = new MInvoicePaySchedule[list.size()]; + list.toArray(retValue); + return retValue; + } // getSchedule + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MInvoicePaySchedule.class); + + /** 100 */ + private final static BigDecimal HUNDRED = new BigDecimal(100); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param C_InvoicePaySchedule_ID id + * @param trxName transaction + */ + public MInvoicePaySchedule (Properties ctx, int C_InvoicePaySchedule_ID, String trxName) + { + super(ctx, C_InvoicePaySchedule_ID, trxName); + if (C_InvoicePaySchedule_ID == 0) + { + // setC_Invoice_ID (0); + // setDiscountAmt (Env.ZERO); + // setDiscountDate (new Timestamp(System.currentTimeMillis())); + // setDueAmt (Env.ZERO); + // setDueDate (new Timestamp(System.currentTimeMillis())); + setIsValid (false); + } + } // MInvoicePaySchedule + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MInvoicePaySchedule (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MInvoicePaySchedule + + /** + * Parent Constructor + * @param invoice invoice + * @param paySchedule payment schedule + */ + public MInvoicePaySchedule (MInvoice invoice, MPaySchedule paySchedule) + { + super (invoice.getCtx(), 0, invoice.get_TrxName()); + m_parent = invoice; + setClientOrg(invoice); + setC_Invoice_ID(invoice.getC_Invoice_ID()); + setC_PaySchedule_ID(paySchedule.getC_PaySchedule_ID()); + + // Amounts + int scale = MCurrency.getStdPrecision(getCtx(), invoice.getC_Currency_ID()); + BigDecimal due = invoice.getGrandTotal(); + if (due.compareTo(Env.ZERO) == 0) + { + setDueAmt (Env.ZERO); + setDiscountAmt (Env.ZERO); + setIsValid(false); + } + else + { + due = due.multiply(paySchedule.getPercentage()) + .divide(HUNDRED, scale, BigDecimal.ROUND_HALF_UP); + setDueAmt (due); + BigDecimal discount = due.multiply(paySchedule.getDiscount()) + .divide(HUNDRED, scale, BigDecimal.ROUND_HALF_UP); + setDiscountAmt (discount); + setIsValid(true); + } + + // Dates + Timestamp dueDate = TimeUtil.addDays(invoice.getDateInvoiced(), paySchedule.getNetDays()); + setDueDate (dueDate); + Timestamp discountDate = TimeUtil.addDays(invoice.getDateInvoiced(), paySchedule.getDiscountDays()); + setDiscountDate (discountDate); + } // MInvoicePaySchedule + + /** Parent */ + private MInvoice m_parent = null; + + + /** + * @return Returns the parent. + */ + public MInvoice getParent () + { + if (m_parent == null) + m_parent = new MInvoice (getCtx(), getC_Invoice_ID(), get_TrxName()); + return m_parent; + } // getParent + + /** + * @param parent The parent to set. + */ + public void setParent (MInvoice parent) + { + m_parent = parent; + } // setParent + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("MInvoicePaySchedule["); + sb.append(get_ID()).append("-Due=" + getDueDate() + "/" + getDueAmt()) + .append(";Discount=").append(getDiscountDate() + "/" + getDiscountAmt()) + .append("]"); + return sb.toString(); + } // toString + + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (is_ValueChanged("DueAmt")) + { + log.fine("beforeSave"); + setIsValid(false); + } + return true; + } // beforeSave + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (is_ValueChanged("DueAmt")) + { + log.fine("afterSave"); + getParent(); + m_parent.validatePaySchedule(); + m_parent.save(); + } + return success; + } // afterSave + + +} // MInvoicePaySchedule diff --git a/base/src/org/compiere/model/MInvoiceSchedule.java b/base/src/org/compiere/model/MInvoiceSchedule.java new file mode 100644 index 0000000000..73ceee115b --- /dev/null +++ b/base/src/org/compiere/model/MInvoiceSchedule.java @@ -0,0 +1,199 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Invoice Schedule Model + * + * @author Jorg Janke + * @version $Id: MInvoiceSchedule.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MInvoiceSchedule extends X_C_InvoiceSchedule +{ + /** + * Get MInvoiceSchedule from Cache + * @param ctx context + * @param C_InvoiceSchedule_ID id + * @param trxName transaction + * @return MInvoiceSchedule + */ + public static MInvoiceSchedule get (Properties ctx, int C_InvoiceSchedule_ID, String trxName) + { + Integer key = new Integer (C_InvoiceSchedule_ID); + MInvoiceSchedule retValue = (MInvoiceSchedule) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MInvoiceSchedule (ctx, C_InvoiceSchedule_ID, trxName); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("C_InvoiceSchedule", 5); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param C_InvoiceSchedule_ID id + * @param trxName transaction + */ + public MInvoiceSchedule (Properties ctx, int C_InvoiceSchedule_ID, String trxName) + { + super (ctx, C_InvoiceSchedule_ID, trxName); + } // MInvoiceSchedule + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MInvoiceSchedule (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MInvoiceSchedule + + /** + * Can I send Invoice + * @param xDate date + * @param orderAmt order amount + * @return true if I can send Invoice + */ + public boolean canInvoice (Timestamp xDate, BigDecimal orderAmt) + { + // Amount + if (isAmount() && getAmt() != null && orderAmt != null + && orderAmt.compareTo(getAmt()) >= 0) + return true; + + // Daily + if (INVOICEFREQUENCY_Daily.equals(getInvoiceFrequency())) + return true; + + // Remove time + xDate = TimeUtil.getDay(xDate); + Calendar today = TimeUtil.getToday(); + + // Weekly + if (INVOICEFREQUENCY_Weekly.equals(getInvoiceFrequency())) + { + Calendar cutoff = TimeUtil.getToday(); + cutoff.set(Calendar.DAY_OF_WEEK, getCalendarDay(getInvoiceWeekDayCutoff())); + if (cutoff.after(today)) + cutoff.add(Calendar.DAY_OF_YEAR, -7); + Timestamp cutoffDate = new Timestamp (cutoff.getTimeInMillis()); + log.fine("canInvoice - Date=" + xDate + " > Cutoff=" + cutoffDate + + " - " + xDate.after(cutoffDate)); + if (xDate.after(cutoffDate)) + return false; + // + Calendar invoice = TimeUtil.getToday(); + invoice.set(Calendar.DAY_OF_WEEK, getCalendarDay(getInvoiceWeekDay())); + if (invoice.after(today)) + invoice.add(Calendar.DAY_OF_YEAR, -7); + Timestamp invoiceDate = new Timestamp (invoice.getTimeInMillis()); + log.fine("canInvoice - Date=" + xDate + " > Invoice=" + invoiceDate + + " - " + xDate.after(invoiceDate)); + if (xDate.after(invoiceDate)) + return false; + return true; + } + + // Monthly + if (INVOICEFREQUENCY_Monthly.equals(getInvoiceFrequency()) + || INVOICEFREQUENCY_TwiceMonthly.equals(getInvoiceFrequency())) + { + if (getInvoiceDayCutoff() > 0) + { + Calendar cutoff = TimeUtil.getToday(); + cutoff.set(Calendar.DAY_OF_MONTH, getInvoiceDayCutoff()); + if (cutoff.after(today)) + cutoff.add(Calendar.MONTH, -1); + Timestamp cutoffDate = new Timestamp (cutoff.getTimeInMillis()); + log.fine("canInvoice - Date=" + xDate + " > Cutoff=" + cutoffDate + + " - " + xDate.after(cutoffDate)); + if (xDate.after(cutoffDate)) + return false; + } + Calendar invoice = TimeUtil.getToday(); + invoice.set(Calendar.DAY_OF_MONTH, getInvoiceDay()); + if (invoice.after(today)) + invoice.add(Calendar.MONTH, -1); + Timestamp invoiceDate = new Timestamp (invoice.getTimeInMillis()); + log.fine("canInvoice - Date=" + xDate + " > Invoice=" + invoiceDate + + " - " + xDate.after(invoiceDate)); + if (xDate.after(invoiceDate)) + return false; + return true; + } + + // Bi-Monthly (+15) + if (INVOICEFREQUENCY_TwiceMonthly.equals(getInvoiceFrequency())) + { + if (getInvoiceDayCutoff() > 0) + { + Calendar cutoff = TimeUtil.getToday(); + cutoff.set(Calendar.DAY_OF_MONTH, getInvoiceDayCutoff() +15); + if (cutoff.after(today)) + cutoff.add(Calendar.MONTH, -1); + Timestamp cutoffDate = new Timestamp (cutoff.getTimeInMillis()); + if (xDate.after(cutoffDate)) + return false; + } + Calendar invoice = TimeUtil.getToday(); + invoice.set(Calendar.DAY_OF_MONTH, getInvoiceDay() +15); + if (invoice.after(today)) + invoice.add(Calendar.MONTH, -1); + Timestamp invoiceDate = new Timestamp (invoice.getTimeInMillis()); + if (xDate.after(invoiceDate)) + return false; + return true; + } + return false; + } // canInvoice + + /** + * Convert to Calendar day + * @param day Invoice Week Day + * @return day + */ + private int getCalendarDay (String day) + { + if (INVOICEWEEKDAY_Friday.equals(day)) + return Calendar.FRIDAY; + if (INVOICEWEEKDAY_Saturday.equals(day)) + return Calendar.SATURDAY; + if (INVOICEWEEKDAY_Sunday.equals(day)) + return Calendar.SUNDAY; + if (INVOICEWEEKDAY_Monday.equals(day)) + return Calendar.MONDAY; + if (INVOICEWEEKDAY_Tuesday.equals(day)) + return Calendar.TUESDAY; + if (INVOICEWEEKDAY_Wednesday.equals(day)) + return Calendar.WEDNESDAY; + // if (INVOICEWEEKDAY_Thursday.equals(day)) + return Calendar.THURSDAY; + } // getCalendarDay + +} // MInvoiceSchedule diff --git a/base/src/org/compiere/model/MInvoiceTax.java b/base/src/org/compiere/model/MInvoiceTax.java new file mode 100644 index 0000000000..94723cd344 --- /dev/null +++ b/base/src/org/compiere/model/MInvoiceTax.java @@ -0,0 +1,273 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Invoice Tax Model + * + * @author Jorg Janke + * @version $Id: MInvoiceTax.java,v 1.5 2006/10/06 00:42:24 jjanke Exp $ + */ +public class MInvoiceTax extends X_C_InvoiceTax +{ + /** + * Get Tax Line for Invoice Line + * @param line invoice line + * @param precision currency precision + * @param oldTax if true old tax is returned + * @param trxName transaction name + * @return existing or new tax + */ + public static MInvoiceTax get (MInvoiceLine line, int precision, + boolean oldTax, String trxName) + { + MInvoiceTax retValue = null; + if (line == null || line.getC_Invoice_ID() == 0) + return null; + int C_Tax_ID = line.getC_Tax_ID(); + if (oldTax && line.is_ValueChanged("C_Tax_ID")) + { + Object old = line.get_ValueOld("C_Tax_ID"); + if (old == null) + return null; + C_Tax_ID = ((Integer)old).intValue(); + } + if (C_Tax_ID == 0) + { + s_log.warning("C_Tax_ID=0"); + return null; + } + + String sql = "SELECT * FROM C_InvoiceTax WHERE C_Invoice_ID=? AND C_Tax_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, line.getC_Invoice_ID()); + pstmt.setInt (2, C_Tax_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + retValue = new MInvoiceTax (line.getCtx(), rs, trxName); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (retValue != null) + { + retValue.set_TrxName(trxName); + retValue.setPrecision(precision); + s_log.fine("(old=" + oldTax + ") " + retValue); + return retValue; + } + + // Create New + retValue = new MInvoiceTax(line.getCtx(), 0, trxName); + retValue.set_TrxName(trxName); + retValue.setClientOrg(line); + retValue.setC_Invoice_ID(line.getC_Invoice_ID()); + retValue.setC_Tax_ID(line.getC_Tax_ID()); + retValue.setPrecision(precision); + retValue.setIsTaxIncluded(line.isTaxIncluded()); + s_log.fine("(new) " + retValue); + return retValue; + } // get + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MInvoiceTax.class); + + + /************************************************************************** + * Persistency Constructor + * @param ctx context + * @param ignored ignored + * @param trxName transaction + */ + public MInvoiceTax (Properties ctx, int ignored, String trxName) + { + super(ctx, 0, trxName); + if (ignored != 0) + throw new IllegalArgumentException("Multi-Key"); + setTaxAmt (Env.ZERO); + setTaxBaseAmt (Env.ZERO); + setIsTaxIncluded(false); + } // MInvoiceTax + + /** + * Load Constructor. + * Set Precision and TaxIncluded for tax calculations! + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MInvoiceTax (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MInvoiceTax + + /** Tax */ + private MTax m_tax = null; + /** Cached Precision */ + private Integer m_precision = null; + + + /** + * Get Precision + * @return Returns the precision or 2 + */ + private int getPrecision () + { + if (m_precision == null) + return 2; + return m_precision.intValue(); + } // getPrecision + + /** + * Set Precision + * @param precision The precision to set. + */ + protected void setPrecision (int precision) + { + m_precision = new Integer(precision); + } // setPrecision + + /** + * Get Tax + * @return tax + */ + protected MTax getTax() + { + if (m_tax == null) + m_tax = MTax.get(getCtx(), getC_Tax_ID()); + return m_tax; + } // getTax + + + /************************************************************************** + * Calculate/Set Tax Base Amt from Invoice Lines + * @return true if tax calculated + */ + public boolean calculateTaxFromLines () + { + BigDecimal taxBaseAmt = Env.ZERO; + BigDecimal taxAmt = Env.ZERO; + // + boolean documentLevel = getTax().isDocumentLevel(); + MTax tax = getTax(); + // + String sql = "SELECT il.LineNetAmt, COALESCE(il.TaxAmt,0), i.IsSOTrx " + + "FROM C_InvoiceLine il" + + " INNER JOIN C_Invoice i ON (il.C_Invoice_ID=i.C_Invoice_ID) " + + "WHERE il.C_Invoice_ID=? AND il.C_Tax_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_Invoice_ID()); + pstmt.setInt (2, getC_Tax_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + // BaseAmt + BigDecimal baseAmt = rs.getBigDecimal(1); + taxBaseAmt = taxBaseAmt.add(baseAmt); + // TaxAmt + BigDecimal amt = rs.getBigDecimal(2); + if (amt == null) + amt = Env.ZERO; + boolean isSOTrx = "Y".equals(rs.getString(3)); + // + if (documentLevel || baseAmt.signum() == 0) + amt = Env.ZERO; + else if (amt.signum() != 0 && !isSOTrx) // manually entered + ; + else // calculate line tax + amt = tax.calculateTax(baseAmt, isTaxIncluded(), getPrecision()); + // + taxAmt = taxAmt.add(amt); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "setTaxBaseAmt", e); + taxBaseAmt = null; + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (taxBaseAmt == null) + return false; + + // Calculate Tax + if (documentLevel || taxAmt.signum() == 0) + taxAmt = tax.calculateTax(taxBaseAmt, isTaxIncluded(), getPrecision()); + setTaxAmt(taxAmt); + + // Set Base + if (isTaxIncluded()) + setTaxBaseAmt (taxBaseAmt.subtract(taxAmt)); + else + setTaxBaseAmt (taxBaseAmt); + return true; + } // calculateTaxFromLines + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MInvoiceTax["); + sb.append("C_Invoice_ID=").append(getC_Invoice_ID()) + .append(",C_Tax_ID=").append(getC_Tax_ID()) + .append(", Base=").append(getTaxBaseAmt()).append(",Tax=").append(getTaxAmt()) + .append ("]"); + return sb.toString (); + } // toString + +} // MInvoiceTax diff --git a/base/src/org/compiere/model/MJournal.java b/base/src/org/compiere/model/MJournal.java new file mode 100644 index 0000000000..91af1db21c --- /dev/null +++ b/base/src/org/compiere/model/MJournal.java @@ -0,0 +1,755 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * GL Journal Model + * + * @author Jorg Janke + * @version $Id: MJournal.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MJournal extends X_GL_Journal implements DocAction +{ + /** + * Standard Constructor + * @param ctx context + * @param GL_Journal_ID id + * @param trxName transaction + */ + public MJournal (Properties ctx, int GL_Journal_ID, String trxName) + { + super (ctx, GL_Journal_ID, trxName); + if (GL_Journal_ID == 0) + { + // setGL_Journal_ID (0); // PK + // setC_AcctSchema_ID (0); + // setC_Currency_ID (0); + // setC_DocType_ID (0); + // setC_Period_ID (0); + // + setCurrencyRate (Env.ONE); + // setC_ConversionType_ID(0); + setDateAcct (new Timestamp(System.currentTimeMillis())); + setDateDoc (new Timestamp(System.currentTimeMillis())); + // setDescription (null); + setDocAction (DOCACTION_Complete); + setDocStatus (DOCSTATUS_Drafted); + // setDocumentNo (null); + // setGL_Category_ID (0); + setPostingType (POSTINGTYPE_Actual); + setTotalCr (Env.ZERO); + setTotalDr (Env.ZERO); + setIsApproved (false); + setIsPrinted (false); + setPosted (false); + setProcessed(false); + } + } // MJournal + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MJournal (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MJournal + + /** + * Parent Constructor. + * @param parent batch + */ + public MJournal (MJournalBatch parent) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setGL_JournalBatch_ID(parent.getGL_JournalBatch_ID()); + setC_DocType_ID(parent.getC_DocType_ID()); + setPostingType(parent.getPostingType()); + // + setDateDoc(parent.getDateDoc()); + setC_Period_ID(parent.getC_Period_ID()); + setDateAcct(parent.getDateAcct()); + setC_Currency_ID(parent.getC_Currency_ID()); + } // MJournal + + /** + * Copy Constructor. + * Dos not copy: Dates/Period + * @param original original + */ + public MJournal (MJournal original) + { + 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()); + setGL_Category_ID(original.getGL_Category_ID()); + setPostingType(original.getPostingType()); + setDescription(original.getDescription()); + setC_DocType_ID(original.getC_DocType_ID()); + setControlAmt(original.getControlAmt()); + // + setC_Currency_ID(original.getC_Currency_ID()); + setC_ConversionType_ID(original.getC_ConversionType_ID()); + setCurrencyRate(original.getCurrencyRate()); + + // setDateDoc(original.getDateDoc()); + // setDateAcct(original.getDateAcct()); + // setC_Period_ID(original.getC_Period_ID()); + } // MJournal + + + /** + * Overwrite Client/Org if required + * @param AD_Client_ID client + * @param AD_Org_ID org + */ + public void setClientOrg (int AD_Client_ID, int AD_Org_ID) + { + super.setClientOrg(AD_Client_ID, AD_Org_ID); + } // setClientOrg + + /** + * Set Accounting Date. + * Set also Period if not set earlier + * @param DateAcct date + */ + public void setDateAcct (Timestamp DateAcct) + { + super.setDateAcct(DateAcct); + if (DateAcct == null) + return; + if (getC_Period_ID() != 0) + return; + int C_Period_ID = MPeriod.getC_Period_ID(getCtx(), DateAcct); + if (C_Period_ID == 0) + log.warning("setDateAcct - Period not found"); + else + setC_Period_ID(C_Period_ID); + } // setDateAcct + + /** + * Set Currency Info + * @param C_Currency_ID currenct + * @param C_ConversionType_ID type + * @param CurrencyRate rate + */ + public void setCurrency (int C_Currency_ID, int C_ConversionType_ID, BigDecimal CurrencyRate) + { + if (C_Currency_ID != 0) + setC_Currency_ID(C_Currency_ID); + if (C_ConversionType_ID != 0) + setC_ConversionType_ID(C_ConversionType_ID); + if (CurrencyRate != null && CurrencyRate.compareTo(Env.ZERO) == 0) + setCurrencyRate(CurrencyRate); + } // setCurrency + + + /************************************************************************** + * Get Journal Lines + * @param requery requery + * @return Array of lines + */ + public MJournalLine[] getLines (boolean requery) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM GL_JournalLine WHERE GL_Journal_ID=? ORDER BY Line"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getGL_Journal_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MJournalLine (getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, "getLines", ex); + } + try + { + if (pstmt != null) + pstmt.close(); + } + catch (SQLException ex1) + { + } + pstmt = null; + // + MJournalLine[] retValue = new MJournalLine[list.size()]; + list.toArray(retValue); + return retValue; + } // getLines + + /** + * Copy Lines from other Journal + * @param fromJournal Journal + * @param dateAcct date used - if null original + * @param typeCR type of copying (C)orrect=negate - (R)everse=flip dr/cr - otherwise just copy + * @return number of lines copied + */ + public int copyLinesFrom (MJournal fromJournal, Timestamp dateAcct, char typeCR) + { + if (isProcessed() || fromJournal == null) + return 0; + int count = 0; + MJournalLine[] fromLines = fromJournal.getLines(false); + for (int i = 0; i < fromLines.length; i++) + { + MJournalLine toLine = new MJournalLine (getCtx(), 0, fromJournal.get_TrxName()); + PO.copyValues(fromLines[i], toLine, getAD_Client_ID(), getAD_Org_ID()); + toLine.setGL_Journal_ID(getGL_Journal_ID()); + // + if (dateAcct != null) + toLine.setDateAcct(dateAcct); + // Amounts + if (typeCR == 'C') // correct + { + toLine.setAmtSourceDr(fromLines[i].getAmtSourceDr().negate()); + toLine.setAmtSourceCr(fromLines[i].getAmtSourceCr().negate()); + } + else if (typeCR == 'R') // reverse + { + toLine.setAmtSourceDr(fromLines[i].getAmtSourceCr()); + toLine.setAmtSourceCr(fromLines[i].getAmtSourceDr()); + } + toLine.setIsGenerated(true); + toLine.setProcessed(false); + if (toLine.save()) + count++; + } + if (fromLines.length != count) + log.log(Level.SEVERE, "copyLinesFrom - Line difference - JournalLines=" + fromLines.length + " <> Saved=" + count); + + return count; + } // copyLinesFrom + + /** + * Set Processed. + * Propergate to Lines/Taxes + * @param processed processed + */ + public void setProcessed (boolean processed) + { + super.setProcessed (processed); + if (get_ID() == 0) + return; + String sql = "UPDATE GL_JournalLine SET Processed='" + + (processed ? "Y" : "N") + + "' WHERE GL_Journal_ID=" + getGL_Journal_ID(); + int noLine = DB.executeUpdate(sql, get_TrxName()); + log.fine(processed + " - Lines=" + noLine); + } // setProcessed + + + /************************************************************************** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Imported Journals may not have date + if (getDateDoc() == null) + { + if (getDateAcct() == null) + setDateDoc(new Timestamp(System.currentTimeMillis())); + else + setDateDoc(getDateAcct()); + } + if (getDateAcct() == null) + setDateAcct(getDateDoc()); + return true; + } // beforeSave + + + /** + * After Save. + * Update Batch Total + * @param newRecord true if new record + * @param success true if success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + return updateBatch(); + } // afterSave + + /** + * After Delete + * @param success true if deleted + * @return true if success + */ + protected boolean afterDelete (boolean success) + { + if (!success) + return success; + return updateBatch(); + } // afterDelete + + /** + * Update Batch total + * @return true if ok + */ + private boolean updateBatch() + { + String sql = "UPDATE GL_JournalBatch jb" + + " SET (TotalDr, TotalCr) = (SELECT COALESCE(SUM(TotalDr),0), COALESCE(SUM(TotalCr),0)" + + " FROM GL_Journal j WHERE j.IsActive='Y' AND jb.GL_JournalBatch_ID=j.GL_JournalBatch_ID) " + + "WHERE GL_JournalBatch_ID=" + getGL_JournalBatch_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + if (no != 1) + log.warning("afterSave - Update Batch #" + no); + return no == 1; + } // updateBatch + + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // process + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info(toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info(toString()); + return true; + } // invalidateIt + + /** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + + // Get Period + MPeriod period = MPeriod.get (getCtx(), getDateAcct()); + if (period == null) + { + log.warning("No Period for " + getDateAcct()); + m_processMsg = "@PeriodNotFound@"; + return DocAction.STATUS_Invalid; + } + // Standard Period + if (period.getC_Period_ID() != getC_Period_ID() + && period.isStandardPeriod()) + { + m_processMsg = "@PeriodNotValid@"; + return DocAction.STATUS_Invalid; + } + boolean open = period.isOpen(dt.getDocBaseType()); + if (!open) + { + log.warning(period.getName() + + ": Not open for " + dt.getDocBaseType() + " (" + getDateAcct() + ")"); + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + + // Lines + MJournalLine[] lines = getLines(true); + if (lines.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + + // Add up Amounts + BigDecimal AmtSourceDr = Env.ZERO; + BigDecimal AmtSourceCr = Env.ZERO; + for (int i = 0; i < lines.length; i++) + { + MJournalLine line = lines[i]; + if (!isActive()) + continue; + // + if (line.isDocControlled()) + { + m_processMsg = "@DocControlledError@ - @Line@=" + line.getLine() + + " - " + line.getAccountElementValue(); + return DocAction.STATUS_Invalid; + } + // + AmtSourceDr = AmtSourceDr.add(line.getAmtSourceDr()); + AmtSourceCr = AmtSourceCr.add(line.getAmtSourceCr()); + } + setTotalDr(AmtSourceDr); + setTotalCr(AmtSourceCr); + + // Control Amount + if (Env.ZERO.compareTo(getControlAmt()) != 0 + && getControlAmt().compareTo(getTotalDr()) != 0) + { + m_processMsg = "@ControlAmtError@"; + return DocAction.STATUS_Invalid; + } + + // Unbalanced Jornal & Not Suspense + if (AmtSourceDr.compareTo(AmtSourceCr) != 0) + { + MAcctSchemaGL gl = MAcctSchemaGL.get(getCtx(), getC_AcctSchema_ID()); + if (gl == null || !gl.isUseSuspenseBalancing()) + { + m_processMsg = "@UnbalancedJornal@"; + return DocAction.STATUS_Invalid; + } + } + + if (!DOCACTION_Complete.equals(getDocAction())) + setDocAction(DOCACTION_Complete); + m_justPrepared = true; + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info(toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info(toString()); + setIsApproved(false); + return true; + } // rejectIt + + /** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + // Implicit Approval + if (!isApproved()) + approveIt(); + log.info(toString()); + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + m_processMsg = valid; + return DocAction.STATUS_Invalid; + } + // + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + /** + * Void Document. + * @return true if success + */ + public boolean voidIt() + { + log.info(toString()); + if (DOCSTATUS_Drafted.equals(getDocStatus()) + || DOCSTATUS_Invalid.equals(getDocStatus())) + { + setProcessed(true); + setDocAction(DOCACTION_None); + return true; + } + return false; + } // voidIt + + /** + * Close Document. + * Cancel not delivered Qunatities + * @return true if success + */ + public boolean closeIt() + { + log.info(toString()); + if (DOCSTATUS_Completed.equals(getDocStatus())) + { + setProcessed(true); + setDocAction(DOCACTION_None); + return true; + } + return false; + } // closeIt + + /** + * Reverse Correction (in same batch). + * As if nothing happened - same date + * @return true if success + */ + public boolean reverseCorrectIt() + { + return reverseCorrectIt(getGL_JournalBatch_ID()) != null; + } // reverseCorrectIt + + /** + * Reverse Correction. + * As if nothing happened - same date + * @param GL_JournalBatch_ID reversal batch + * @return reversed Journal or null + */ + public MJournal reverseCorrectIt (int GL_JournalBatch_ID) + { + log.info(toString()); + // Journal + MJournal reverse = new MJournal (this); + reverse.setGL_JournalBatch_ID(GL_JournalBatch_ID); + reverse.setDateDoc(getDateDoc()); + reverse.setC_Period_ID(getC_Period_ID()); + reverse.setDateAcct(getDateAcct()); + // Reverse indicator + String description = reverse.getDescription(); + if (description == null) + description = "** " + getDocumentNo() + " **"; + else + description += " ** " + getDocumentNo() + " **"; + reverse.setDescription(description); + if (!reverse.save()) + return null; + + // Lines + reverse.copyLinesFrom(this, null, 'C'); + // + setProcessed(true); + setDocAction(DOCACTION_None); + return reverse; + } // reverseCorrectionIt + + /** + * Reverse Accrual (sane batch). + * Flip Dr/Cr - Use Today's date + * @return true if success + */ + public boolean reverseAccrualIt() + { + return reverseAccrualIt (getGL_JournalBatch_ID()) != null; + } // reverseAccrualIt + + /** + * Reverse Accrual. + * Flip Dr/Cr - Use Today's date + * @param GL_JournalBatch_ID reversal batch + * @return reversed journal or null + */ + public MJournal reverseAccrualIt (int GL_JournalBatch_ID) + { + log.info(toString()); + // Journal + MJournal reverse = new MJournal (this); + reverse.setGL_JournalBatch_ID(GL_JournalBatch_ID); + reverse.setC_Period_ID(0); + reverse.setDateDoc(new Timestamp(System.currentTimeMillis())); + reverse.setDateAcct(reverse.getDateDoc()); + // Reverse indicator + String description = reverse.getDescription(); + if (description == null) + description = "** " + getDocumentNo() + " **"; + else + description += " ** " + getDocumentNo() + " **"; + reverse.setDescription(description); + if (!reverse.save()) + return null; + + // Lines + reverse.copyLinesFrom(this, reverse.getDateAcct(), 'R'); + // + setProcessed(true); + setDocAction(DOCACTION_None); + return reverse; + } // reverseAccrualIt + + /** + * Re-activate + * @return true if success + */ + public boolean reActivateIt() + { + log.info(toString()); + return false; + } // reActivateIt + + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getDocumentNo()); + // : Total Lines = 123.00 (#1) + sb.append(": ") + .append(Msg.translate(getCtx(),"TotalDr")).append("=").append(getTotalDr()) + .append(" ") + .append(Msg.translate(getCtx(),"TotalCR")).append("=").append(getTotalCr()) + .append(" (#").append(getLines(false).length).append(")"); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MJournal["); + sb.append(get_ID()).append(",").append(getDescription()) + .append(",DR=").append(getTotalDr()) + .append(",CR=").append(getTotalCr()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Get Document Info + * @return document info (untranslated) + */ + public String getDocumentInfo() + { + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + return dt.getName() + " " + getDocumentNo(); + } // getDocumentInfo + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + // ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.INVOICE, getC_Invoice_ID()); + // if (re == null) + return null; + // return re.getPDF(file); + } // createPDF + + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner (Responsible) + * @return AD_User_ID (Created) + */ + public int getDoc_User_ID() + { + return getCreatedBy(); + } // getDoc_User_ID + + /** + * Get Document Approval Amount + * @return DR amount + */ + public BigDecimal getApprovalAmt() + { + return getTotalDr(); + } // getApprovalAmt + +} // MJournal diff --git a/base/src/org/compiere/model/MJournalBatch.java b/base/src/org/compiere/model/MJournalBatch.java new file mode 100644 index 0000000000..92d65682ef --- /dev/null +++ b/base/src/org/compiere/model/MJournalBatch.java @@ -0,0 +1,757 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Journal Batch Model + * + * @author Jorg Janke + * @version $Id: MJournalBatch.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MJournalBatch extends X_GL_JournalBatch implements DocAction +{ + /** + * Create new Journal Batch by copying + * @param ctx context + * @param GL_JournalBatch_ID journal batch + * @param dateDoc date of the document date + * @param trxName transaction + * @return Journal Batch + */ + public static MJournalBatch copyFrom (Properties ctx, int GL_JournalBatch_ID, + Timestamp dateDoc, String trxName) + { + MJournalBatch from = new MJournalBatch (ctx, GL_JournalBatch_ID, trxName); + if (from.getGL_JournalBatch_ID() == 0) + throw new IllegalArgumentException ("From Journal Batch not found GL_JournalBatch_ID=" + GL_JournalBatch_ID); + // + MJournalBatch to = new MJournalBatch (ctx, 0, trxName); + PO.copyValues(from, to, from.getAD_Client_ID(), from.getAD_Org_ID()); + to.set_ValueNoCheck ("DocumentNo", null); + to.setDateAcct(dateDoc); + to.setDateDoc(dateDoc); + to.setDocStatus(DOCSTATUS_Drafted); + to.setDocAction(DOCACTION_Complete); + to.setIsApproved(false); + // + if (!to.save()) + throw new IllegalStateException("Could not create Journal Batch"); + + if (to.copyDetailsFrom(from) == 0) + throw new IllegalStateException("Could not create Journal Batch Details"); + + return to; + } // copyFrom + + + /************************************************************************** + * Standard Construvtore + * @param ctx context + * @param GL_JournalBatch_ID id if 0 - create actual batch + * @param trxName transaction + */ + public MJournalBatch (Properties ctx, int GL_JournalBatch_ID, String trxName) + { + super (ctx, GL_JournalBatch_ID, trxName); + if (GL_JournalBatch_ID == 0) + { + // setGL_JournalBatch_ID (0); PK + // setDescription (null); + // setDocumentNo (null); + // setC_DocType_ID (0); + setPostingType (POSTINGTYPE_Actual); + setDocAction (DOCACTION_Complete); + setDocStatus (DOCSTATUS_Drafted); + setTotalCr (Env.ZERO); + setTotalDr (Env.ZERO); + setProcessed (false); + setProcessing (false); + setIsApproved(false); + } + } // MJournalBatch + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MJournalBatch (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MJournalBatch + + /** + * Copy Constructor. + * Dos not copy: Dates/Period + * @param original original + */ + public MJournalBatch (MJournalBatch original) + { + 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()); + setGL_Category_ID(original.getGL_Category_ID()); + setPostingType(original.getPostingType()); + setDescription(original.getDescription()); + setC_DocType_ID(original.getC_DocType_ID()); + setControlAmt(original.getControlAmt()); + // + setC_Currency_ID(original.getC_Currency_ID()); + // setC_ConversionType_ID(original.getC_ConversionType_ID()); + // setCurrencyRate(original.getCurrencyRate()); + + // setDateDoc(original.getDateDoc()); + // setDateAcct(original.getDateAcct()); + // setC_Period_ID(original.getC_Period_ID()); + } // MJournal + + + + /** + * Overwrite Client/Org if required + * @param AD_Client_ID client + * @param AD_Org_ID org + */ + public void setClientOrg (int AD_Client_ID, int AD_Org_ID) + { + super.setClientOrg(AD_Client_ID, AD_Org_ID); + } // setClientOrg + + /** + * Set Accounting Date. + * Set also Period if not set earlier + * @param DateAcct date + */ + public void setDateAcct (Timestamp DateAcct) + { + super.setDateAcct(DateAcct); + if (DateAcct == null) + return; + if (getC_Period_ID() != 0) + return; + int C_Period_ID = MPeriod.getC_Period_ID(getCtx(), DateAcct); + if (C_Period_ID == 0) + log.warning("Period not found"); + else + setC_Period_ID(C_Period_ID); + } // setDateAcct + + /** + * Get Journal Lines + * @param requery requery + * @return Array of lines + */ + public MJournal[] getJournals (boolean requery) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM GL_Journal WHERE GL_JournalBatch_ID=? ORDER BY DocumentNo"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getGL_JournalBatch_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MJournal (getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close(); + } + catch (SQLException ex1) + { + } + pstmt = null; + // + MJournal[] retValue = new MJournal[list.size()]; + list.toArray(retValue); + return retValue; + } // getJournals + + /** + * Copy Journal/Lines from other Journal Batch + * @param jb Journal Batch + * @return number of journals + lines copied + */ + public int copyDetailsFrom (MJournalBatch jb) + { + if (isProcessed() || jb == null) + return 0; + int count = 0; + int lineCount = 0; + MJournal[] fromJournals = jb.getJournals(false); + for (int i = 0; i < fromJournals.length; i++) + { + MJournal toJournal = new MJournal (getCtx(), 0, jb.get_TrxName()); + PO.copyValues(fromJournals[i], toJournal, getAD_Client_ID(), getAD_Org_ID()); + toJournal.setGL_JournalBatch_ID(getGL_JournalBatch_ID()); + toJournal.set_ValueNoCheck ("DocumentNo", null); // create new + toJournal.setC_Period_ID(0); + toJournal.setDateDoc(getDateDoc()); // dates from this Batch + toJournal.setDateAcct(getDateAcct()); + toJournal.setDocStatus(MJournal.DOCSTATUS_Drafted); + toJournal.setDocAction(MJournal.DOCACTION_Complete); + toJournal.setTotalCr(Env.ZERO); + toJournal.setTotalDr(Env.ZERO); + toJournal.setIsApproved(false); + toJournal.setIsPrinted(false); + toJournal.setPosted(false); + toJournal.setProcessed(false); + if (toJournal.save()) + { + count++; + lineCount += toJournal.copyLinesFrom(fromJournals[i], getDateAcct(), 'x'); + } + } + if (fromJournals.length != count) + log.log(Level.SEVERE, "copyDetailsFrom - Line difference - Journals=" + fromJournals.length + " <> Saved=" + count); + + return count + lineCount; + } // copyLinesFrom + + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // process + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info("unlockIt - " + toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info("invalidateIt - " + toString()); + return true; + } // invalidateIt + + /** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + + // Std Period open? + if (!MPeriod.isOpen(getCtx(), getDateAcct(), dt.getDocBaseType())) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + + // Add up Amounts & prepare them + MJournal[] journals = getJournals(false); + if (journals.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + + BigDecimal TotalDr = Env.ZERO; + BigDecimal TotalCr = Env.ZERO; + for (int i = 0; i < journals.length; i++) + { + MJournal journal = journals[i]; + if (!journal.isActive()) + continue; + // Prepare if not closed + if (DOCSTATUS_Closed.equals(journal.getDocStatus()) + || DOCSTATUS_Voided.equals(journal.getDocStatus()) + || DOCSTATUS_Reversed.equals(journal.getDocStatus()) + || DOCSTATUS_Completed.equals(journal.getDocStatus())) + ; + else + { + String status = journal.prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + { + journal.setDocStatus(status); + journal.save(); + m_processMsg = journal.getProcessMsg(); + return status; + } + journal.setDocStatus(DOCSTATUS_InProgress); + journal.save(); + } + // + TotalDr = TotalDr.add(journal.getTotalDr()); + TotalCr = TotalCr.add(journal.getTotalCr()); + } + setTotalDr(TotalDr); + setTotalCr(TotalCr); + + // Control Amount + if (Env.ZERO.compareTo(getControlAmt()) != 0 + && getControlAmt().compareTo(getTotalDr()) != 0) + { + m_processMsg = "@ControlAmtError@"; + return DocAction.STATUS_Invalid; + } + +// Bug 1353695 Currency Rate and COnbversion Type should get copied from journal to lines + for (int i = 0; i < journals.length; i++) + { + MJournal journal = journals[i]; + MJournalLine[] lines = journal.getLines(true); + if (journal.getCurrencyRate() != null && journal.getCurrencyRate().compareTo(Env.ZERO) != 0) + { + for (int j = 0; j < lines.length; j++) + { + MJournalLine line = lines[j]; + line.setCurrencyRate(journal.getCurrencyRate()); + line.save(); + } + } + if (journal.getC_ConversionType_ID() > 0) + { + for (int j = 0; j < lines.length; j++) + { + MJournalLine line = lines[j]; + line.setC_ConversionType_ID(journal.getC_ConversionType_ID()); + line.save(); + } + } + } + + // Add up Amounts + m_justPrepared = true; + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info("approveIt - " + toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info("rejectIt - " + toString()); + setIsApproved(false); + return true; + } // rejectIt + + /** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + log.info("completeIt - " + toString()); + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + // Implicit Approval + approveIt(); + + // Add up Amounts & complete them + MJournal[] journals = getJournals(true); + BigDecimal TotalDr = Env.ZERO; + BigDecimal TotalCr = Env.ZERO; + for (int i = 0; i < journals.length; i++) + { + MJournal journal = journals[i]; + if (!journal.isActive()) + { + journal.setProcessed(true); + journal.setDocStatus(DOCSTATUS_Voided); + journal.setDocAction(DOCACTION_None); + journal.save(); + continue; + } + // Complete if not closed + if (DOCSTATUS_Closed.equals(journal.getDocStatus()) + || DOCSTATUS_Voided.equals(journal.getDocStatus()) + || DOCSTATUS_Reversed.equals(journal.getDocStatus()) + || DOCSTATUS_Completed.equals(journal.getDocStatus())) + ; + else + { + String status = journal.completeIt(); + if (!DocAction.STATUS_Completed.equals(status)) + { + journal.setDocStatus(status); + journal.save(); + m_processMsg = journal.getProcessMsg(); + return status; + } + journal.setDocStatus(DOCSTATUS_Completed); + journal.save(); + } + // + TotalDr = TotalDr.add(journal.getTotalDr()); + TotalCr = TotalCr.add(journal.getTotalCr()); + } + setTotalDr(TotalDr); + setTotalCr(TotalCr); + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + m_processMsg = valid; + return DocAction.STATUS_Invalid; + } + // + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + /** + * Void Document. + * @return false + */ + public boolean voidIt() + { + log.info("voidIt - " + toString()); + return false; + } // voidIt + + /** + * Close Document. + * @return true if success + */ + public boolean closeIt() + { + log.info("closeIt - " + toString()); + MJournal[] journals = getJournals(true); + for (int i = 0; i < journals.length; i++) + { + MJournal journal = journals[i]; + if (!journal.isActive() && !journal.isProcessed()) + { + journal.setProcessed(true); + journal.setDocStatus(DOCSTATUS_Voided); + journal.setDocAction(DOCACTION_None); + journal.save(); + continue; + } + if (DOCSTATUS_Drafted.equals(journal.getDocStatus()) + || DOCSTATUS_InProgress.equals(journal.getDocStatus()) + || DOCSTATUS_Invalid.equals(journal.getDocStatus())) + { + m_processMsg = "Journal not Completed: " + journal.getSummary(); + return false; + } + + // Close if not closed + if (DOCSTATUS_Closed.equals(journal.getDocStatus()) + || DOCSTATUS_Voided.equals(journal.getDocStatus()) + || DOCSTATUS_Reversed.equals(journal.getDocStatus())) + ; + else + { + if (!journal.closeIt()) + { + m_processMsg = "Cannot close: " + journal.getSummary(); + return false; + } + journal.save(); + } + } + return true; + } // closeIt + + /** + * Reverse Correction. + * As if nothing happened - same date + * @return true if success + */ + public boolean reverseCorrectIt() + { + log.info("reverseCorrectIt - " + toString()); + MJournal[] journals = getJournals(true); + // check prerequisites + for (int i = 0; i < journals.length; i++) + { + MJournal journal = journals[i]; + if (!journal.isActive()) + continue; + // All need to be closed/Completed + if (DOCSTATUS_Completed.equals(journal.getDocStatus())) + ; + else + { + m_processMsg = "All Journals need to be Compleded: " + journal.getSummary(); + return false; + } + } + + // Reverse it + MJournalBatch reverse = new MJournalBatch (this); + reverse.setDateDoc(getDateDoc()); + reverse.setC_Period_ID(getC_Period_ID()); + reverse.setDateAcct(getDateAcct()); + // Reverse indicator + String description = reverse.getDescription(); + if (description == null) + description = "** " + getDocumentNo() + " **"; + else + description += " ** " + getDocumentNo() + " **"; + reverse.setDescription(description); + reverse.save(); + // + + // Reverse Journals + for (int i = 0; i < journals.length; i++) + { + MJournal journal = journals[i]; + if (!journal.isActive()) + continue; + if (journal.reverseCorrectIt(reverse.getGL_JournalBatch_ID()) == null) + { + m_processMsg = "Could not reverse " + journal; + return false; + } + journal.save(); + } + return true; + } // reverseCorrectionIt + + /** + * Reverse Accrual. + * Flip Dr/Cr - Use Today's date + * @return true if success + */ + public boolean reverseAccrualIt() + { + log.info("reverseAccrualIt - " + toString()); + MJournal[] journals = getJournals(true); + // check prerequisites + for (int i = 0; i < journals.length; i++) + { + MJournal journal = journals[i]; + if (!journal.isActive()) + continue; + // All need to be closed/Completed + if (DOCSTATUS_Completed.equals(journal.getDocStatus())) + ; + else + { + m_processMsg = "All Journals need to be Compleded: " + journal.getSummary(); + return false; + } + } + // Reverse it + MJournalBatch reverse = new MJournalBatch (this); + reverse.setC_Period_ID(0); + reverse.setDateDoc(new Timestamp(System.currentTimeMillis())); + reverse.setDateAcct(reverse.getDateDoc()); + // Reverse indicator + String description = reverse.getDescription(); + if (description == null) + description = "** " + getDocumentNo() + " **"; + else + description += " ** " + getDocumentNo() + " **"; + reverse.setDescription(description); + reverse.save(); + + // Reverse Journals + for (int i = 0; i < journals.length; i++) + { + MJournal journal = journals[i]; + if (!journal.isActive()) + continue; + if (journal.reverseAccrualIt(reverse.getGL_JournalBatch_ID()) == null) + { + m_processMsg = "Could not reverse " + journal; + return false; + } + journal.save(); + } + return true; + } // reverseAccrualIt + + /** + * Re-activate - same as reverse correct + * @return true if success + */ + public boolean reActivateIt() + { + log.info("reActivateIt - " + toString()); + // setProcessed(false); + if (reverseCorrectIt()) + return true; + return false; + } // reActivateIt + + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getDocumentNo()); + // : Total Lines = 123.00 (#1) + sb.append(": ") + .append(Msg.translate(getCtx(),"TotalDr")).append("=").append(getTotalDr()) + .append(" ") + .append(Msg.translate(getCtx(),"TotalCR")).append("=").append(getTotalCr()) + .append(" (#").append(getJournals(false).length).append(")"); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MJournalBatch["); + sb.append(get_ID()).append(",").append(getDescription()) + .append(",DR=").append(getTotalDr()) + .append(",CR=").append(getTotalCr()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Get Document Info + * @return document info (untranslated) + */ + public String getDocumentInfo() + { + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + return dt.getName() + " " + getDocumentNo(); + } // getDocumentInfo + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + // ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.INVOICE, getC_Invoice_ID()); + // if (re == null) + return null; + // return re.getPDF(file); + } // createPDF + + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner (Responsible) + * @return AD_User_ID (Created By) + */ + public int getDoc_User_ID() + { + return getCreatedBy(); + } // getDoc_User_ID + + /** + * Get Document Approval Amount + * @return DR amount + */ + public BigDecimal getApprovalAmt() + { + return getTotalDr(); + } // getApprovalAmt + +} // MJournalBatch diff --git a/base/src/org/compiere/model/MJournalLine.java b/base/src/org/compiere/model/MJournalLine.java new file mode 100644 index 0000000000..7044874ddd --- /dev/null +++ b/base/src/org/compiere/model/MJournalLine.java @@ -0,0 +1,339 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Journal Line Model + * + * @author Jorg Janke + * @version $Id: MJournalLine.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MJournalLine extends X_GL_JournalLine +{ + /** + * Standard Constructor + * @param ctx context + * @param GL_JournalLine_ID id + * @param trxName transaction + */ + public MJournalLine (Properties ctx, int GL_JournalLine_ID, String trxName) + { + super (ctx, GL_JournalLine_ID, trxName); + if (GL_JournalLine_ID == 0) + { + // setGL_JournalLine_ID (0); // PK + // setGL_Journal_ID (0); // Parent + // setC_Currency_ID (0); + // setC_ValidCombination_ID (0); + setLine (0); + setAmtAcctCr (Env.ZERO); + setAmtAcctDr (Env.ZERO); + setAmtSourceCr (Env.ZERO); + setAmtSourceDr (Env.ZERO); + setCurrencyRate (Env.ONE); + // setC_ConversionType_ID (0); + setDateAcct (new Timestamp(System.currentTimeMillis())); + setIsGenerated (true); + } + } // MJournalLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MJournalLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MJournalLine + + /** + * Parent Constructor + * @param parent journal + */ + public MJournalLine (MJournal parent) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setGL_Journal_ID(parent.getGL_Journal_ID()); + setC_Currency_ID(parent.getC_Currency_ID()); + setC_ConversionType_ID(parent.getC_ConversionType_ID()); + setDateAcct(parent.getDateAcct()); + + } // MJournalLine + + /** Currency Precision */ + private int m_precision = 2; + /** Account Combination */ + private MAccount m_account = null; + /** Account Element */ + private MElementValue m_accountElement = null; + + /** + * Set Currency Info + * @param C_Currency_ID currenct + * @param C_ConversionType_ID type + * @param CurrencyRate rate + */ + public void setCurrency (int C_Currency_ID, int C_ConversionType_ID, BigDecimal CurrencyRate) + { + setC_Currency_ID(C_Currency_ID); + if (C_ConversionType_ID != 0) + setC_ConversionType_ID(C_ConversionType_ID); + if (CurrencyRate != null && CurrencyRate.signum() == 0) + setCurrencyRate(CurrencyRate); + } // setCurrency + + /** + * Set C_Currency_ID and precision + * @param C_Currency_ID currency + */ + public void setC_Currency_ID (int C_Currency_ID) + { + if (C_Currency_ID == 0) + return; + super.setC_Currency_ID (C_Currency_ID); + m_precision = MCurrency.getStdPrecision(getCtx(), C_Currency_ID); + } // setC_Currency_ID + + /** + * Get Currency Precision + * @return precision + */ + public int getPrecision() + { + return m_precision; + } // getPrecision + + /** + * Set Currency Rate + * @param CurrencyRate check for null (->one) + */ + public void setCurrencyRate (BigDecimal CurrencyRate) + { + if (CurrencyRate == null) + { + log.warning("was NULL - set to 1"); + super.setCurrencyRate (Env.ONE); + } + else if (CurrencyRate.signum() < 0) + { + log.warning("negative - " + CurrencyRate + " - set to 1"); + super.setCurrencyRate (Env.ONE); + } + else + super.setCurrencyRate (CurrencyRate); + } // setCurrencyRate + + /** + * Set Accounted Amounts only if not 0. + * Amounts overwritten in beforeSave - set conversion rate + * @param AmtAcctDr Dr + * @param AmtAcctCr Cr + */ + public void setAmtAcct (BigDecimal AmtAcctDr, BigDecimal AmtAcctCr) + { + // setConversion + double rateDR = 0; + if (AmtAcctDr != null && AmtAcctDr.signum() != 0) + { + rateDR = AmtAcctDr.doubleValue() / getAmtSourceDr().doubleValue(); + super.setAmtAcctDr(AmtAcctDr); + } + double rateCR = 0; + if (AmtAcctCr != null && AmtAcctCr.signum() != 0) + { + rateCR = AmtAcctCr.doubleValue() / getAmtSourceCr().doubleValue(); + super.setAmtAcctCr(AmtAcctCr); + } + if (rateDR != 0 && rateCR != 0 && rateDR != rateCR) + { + log.warning("Rates Different DR=" + rateDR + "(used) <> CR=" + rateCR + "(ignored)"); + rateCR = 0; + } + if (rateDR < 0 || Double.isInfinite(rateDR) || Double.isNaN(rateDR)) + { + log.warning("DR Rate ignored - " + rateDR); + return; + } + if (rateCR < 0 || Double.isInfinite(rateCR) || Double.isNaN(rateCR)) + { + log.warning("CR Rate ignored - " + rateCR); + return; + } + + if (rateDR != 0) + setCurrencyRate(new BigDecimal(rateDR)); + if (rateCR != 0) + setCurrencyRate(new BigDecimal(rateCR)); + } // setAmtAcct + + + /** + * Set C_ValidCombination_ID + * @param C_ValidCombination_ID id + */ + public void setC_ValidCombination_ID (int C_ValidCombination_ID) + { + super.setC_ValidCombination_ID (C_ValidCombination_ID); + m_account = null; + m_accountElement = null; + } // setC_ValidCombination_ID + + /** + * Set C_ValidCombination_ID + * @param acct account + */ + public void setC_ValidCombination_ID (MAccount acct) + { + if (acct == null) + throw new IllegalArgumentException("Account is null"); + super.setC_ValidCombination_ID (acct.getC_ValidCombination_ID()); + m_account = acct; + m_accountElement = null; + } // setC_ValidCombination_ID + + /** + * Get Account (Valid Combination) + * @return combination or null + */ + public MAccount getAccount() + { + if (m_account == null && getC_ValidCombination_ID() != 0) + m_account = new MAccount (getCtx(), getC_ValidCombination_ID(), get_TrxName()); + return m_account; + } // getValidCombination + + /** + * Get Natural Account Element Value + * @return account + */ + public MElementValue getAccountElementValue() + { + if (m_accountElement == null) + { + MAccount vc = getAccount(); + if (vc != null && vc.getAccount_ID() != 0) + m_accountElement = new MElementValue (getCtx(), vc.getAccount_ID(), get_TrxName()); + } + return m_accountElement; + } // getAccountElement + + /** + * Is it posting to a Control Acct + * @return true if control acct + */ + public boolean isDocControlled() + { + MElementValue acct = getAccountElementValue(); + if (acct == null) + { + log.warning ("Account not found for C_ValidCombination_ID=" + getC_ValidCombination_ID()); + return false; + } + return acct.isDocControlled(); + } // isDocControlled + + + /************************************************************************** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Acct Amts + BigDecimal rate = getCurrencyRate(); + BigDecimal amt = rate.multiply(getAmtSourceDr()); + if (amt.scale() > getPrecision()) + amt = amt.setScale(getPrecision(), BigDecimal.ROUND_HALF_UP); + setAmtAcctDr(amt); + amt = rate.multiply(getAmtSourceCr()); + if (amt.scale() > getPrecision()) + amt = amt.setScale(getPrecision(), BigDecimal.ROUND_HALF_UP); + setAmtAcctCr(amt); + // Set Line Org to Acct Org + if (newRecord + || is_ValueChanged("C_ValidCombination_ID") + || is_ValueChanged("AD_Org_ID")) + setAD_Org_ID(getAccount().getAD_Org_ID()); + return true; + } // beforeSave + + /** + * After Save. + * Update Journal/Batch Total + * @param newRecord true if new record + * @param success true if success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + return updateJournalTotal(); + } // afterSave + + + /** + * After Delete + * @param success true if deleted + * @return true if success + */ + protected boolean afterDelete (boolean success) + { + if (!success) + return success; + return updateJournalTotal(); + } // afterDelete + + + /** + * Update Journal and Batch Total + * @return true if success + */ + private boolean updateJournalTotal() + { + // Update Journal Total + String sql = "UPDATE GL_Journal j" + + " SET (TotalDr, TotalCr) = (SELECT COALESCE(SUM(AmtSourceDr),0), COALESCE(SUM(AmtSourceCr),0)" + + " FROM GL_JournalLine jl WHERE jl.IsActive='Y' AND j.GL_Journal_ID=jl.GL_Journal_ID) " + + "WHERE GL_Journal_ID=" + getGL_Journal_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + if (no != 1) + log.warning("afterSave - Update Journal #" + no); + + // Update Batch Total + sql = "UPDATE GL_JournalBatch jb" + + " SET (TotalDr, TotalCr) = (SELECT COALESCE(SUM(TotalDr),0), COALESCE(SUM(TotalCr),0)" + + " FROM GL_Journal j WHERE jb.GL_JournalBatch_ID=j.GL_JournalBatch_ID) " + + "WHERE GL_JournalBatch_ID=" + + "(SELECT DISTINCT GL_JournalBatch_ID FROM GL_Journal WHERE GL_Journal_ID=" + + getGL_Journal_ID() + ")"; + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 1) + log.warning("Update Batch #" + no); + return no == 1; + } // updateJournalTotal + +} // MJournalLine diff --git a/base/src/org/compiere/model/MKCategory.java b/base/src/org/compiere/model/MKCategory.java new file mode 100644 index 0000000000..c17defb8f7 --- /dev/null +++ b/base/src/org/compiere/model/MKCategory.java @@ -0,0 +1,35 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +public class MKCategory extends X_K_Category +{ + + public MKCategory (Properties ctx, int K_Category_ID, String trxName) + { + super (ctx, K_Category_ID, trxName); + } + + public MKCategory (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } +} diff --git a/base/src/org/compiere/model/MLandedCost.java b/base/src/org/compiere/model/MLandedCost.java new file mode 100644 index 0000000000..92ceefc913 --- /dev/null +++ b/base/src/org/compiere/model/MLandedCost.java @@ -0,0 +1,162 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Landed Cost Model + * @author Jorg Janke + * @version $Id: MLandedCost.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MLandedCost extends X_C_LandedCost +{ + /** + * Get Costs of Invoice Line + * @param il invoice line + * @return array of landed cost lines + */ + public static MLandedCost[] getLandedCosts (MInvoiceLine il) + { + ArrayList list = new ArrayList (); + String sql = "SELECT * FROM C_LandedCost WHERE C_InvoiceLine_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, il.get_TrxName()); + pstmt.setInt (1, il.getC_InvoiceLine_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + list.add (new MLandedCost (il.getCtx(), rs, il.get_TrxName())); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + MLandedCost[] retValue = new MLandedCost[list.size ()]; + list.toArray (retValue); + return retValue; + } // getLandedCosts + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MLandedCost.class); + + + /*************************************************************************** + * Standard Constructor + * + * @param ctx context + * @param C_LandedCost_ID id + * @param trxName trx + */ + public MLandedCost (Properties ctx, int C_LandedCost_ID, String trxName) + { + super (ctx, C_LandedCost_ID, trxName); + if (C_LandedCost_ID == 0) + { + // setC_InvoiceLine_ID (0); + // setM_CostElement_ID (0); + setLandedCostDistribution (LANDEDCOSTDISTRIBUTION_Quantity); // Q + } + } // MLandedCost + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MLandedCost (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MLandedCost + + /** + * Before Save + * @param newRecord new + * @return true if ok + */ + protected boolean beforeSave (boolean newRecord) + { + // One Reference + if (getM_Product_ID() == 0 + && getM_InOut_ID() == 0 + && getM_InOutLine_ID() == 0) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), + "@NotFound@ @M_Product_ID@ | @M_InOut_ID@ | @M_InOutLine_ID@")); + return false; + } + // No Product if Line entered + if (getM_InOutLine_ID() != 0 && getM_Product_ID() != 0) + setM_Product_ID(0); + + return true; + } // beforeSave + + /** + * Allocate Costs. + * Done at Invoice Line Level + * @return error message or "" + */ + public String allocateCosts() + { + MInvoiceLine il = new MInvoiceLine (getCtx(), getC_InvoiceLine_ID(), get_TrxName()); + return il.allocateLandedCosts(); + } // allocateCosts + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MLandedCost["); + sb.append (get_ID ()) + .append (",CostDistribution=").append (getLandedCostDistribution()) + .append(",M_CostElement_ID=").append(getM_CostElement_ID()); + if (getM_InOut_ID() != 0) + sb.append (",M_InOut_ID=").append (getM_InOut_ID()); + if (getM_InOutLine_ID() != 0) + sb.append (",M_InOutLine_ID=").append (getM_InOutLine_ID()); + if (getM_Product_ID() != 0) + sb.append (",M_Product_ID=").append (getM_Product_ID()); + sb.append ("]"); + return sb.toString (); + } // toString + +} // MLandedCost diff --git a/base/src/org/compiere/model/MLandedCostAllocation.java b/base/src/org/compiere/model/MLandedCostAllocation.java new file mode 100644 index 0000000000..53dd54c823 --- /dev/null +++ b/base/src/org/compiere/model/MLandedCostAllocation.java @@ -0,0 +1,146 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Landed Cost Allocation Model + * @author Jorg Janke + * @version $Id: MLandedCostAllocation.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MLandedCostAllocation extends X_C_LandedCostAllocation +{ + /** + * Get Cost Allocations for invoice Line + * @param ctx context + * @param C_InvoiceLine_ID invoice line + * @param trxName trx + * @return landed cost alloc + */ + public static MLandedCostAllocation[] getOfInvoiceLine (Properties ctx, + int C_InvoiceLine_ID, String trxName) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_LandedCostAllocation WHERE C_InvoiceLine_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, C_InvoiceLine_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MLandedCostAllocation (ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MLandedCostAllocation[] retValue = new MLandedCostAllocation[list.size ()]; + list.toArray (retValue); + return retValue; + } // getOfInvliceLine + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MLandedCostAllocation.class); + + + /*************************************************************************** + * Standard Constructor + * @param ctx context + * @param C_LandedCostAllocation_ID id + * @param trxName trx + */ + public MLandedCostAllocation (Properties ctx, int C_LandedCostAllocation_ID, String trxName) + { + super (ctx, C_LandedCostAllocation_ID, trxName); + if (C_LandedCostAllocation_ID == 0) + { + // setM_CostElement_ID(0); + setAmt (Env.ZERO); + setQty (Env.ZERO); + setBase (Env.ZERO); + } + } // MLandedCostAllocation + + /** + * Load Constructor + * @param ctx context + * @param rs result name + * @param trxName trx + */ + public MLandedCostAllocation (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MLandedCostAllocation + + + /** + * Parent Constructor + * @param parent parent + * @param M_CostElement_ID cost element + */ + public MLandedCostAllocation (MInvoiceLine parent, int M_CostElement_ID) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setC_InvoiceLine_ID(parent.getC_InvoiceLine_ID()); + setM_CostElement_ID(M_CostElement_ID); + } // MLandedCostAllocation + + /** + * Set Amt + * @param Amt amount + * @param precision precision + */ + public void setAmt (double Amt, int precision) + { + BigDecimal bd = new BigDecimal(Amt); + if (bd.scale() > precision) + bd = bd.setScale(precision, BigDecimal.ROUND_HALF_UP); + super.setAmt(bd); + } // setAmt + + /** + * Set Allocation Qty (e.g. free products) + * @param Qty + */ + public void setQty (BigDecimal Qty) + { + super.setQty (Qty); + } // setQty + + +} // MLandedCostAllocation diff --git a/base/src/org/compiere/model/MLot.java b/base/src/org/compiere/model/MLot.java new file mode 100644 index 0000000000..7e36f3a3b7 --- /dev/null +++ b/base/src/org/compiere/model/MLot.java @@ -0,0 +1,213 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Product Lot + * + * @author Jorg Janke + * @version $Id: MLot.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MLot extends X_M_Lot +{ + /** Logger */ + private static CLogger s_log = CLogger.getCLogger(MLot.class); + + /** + * Get Lots for Product + * @param ctx context + * @param M_Product_ID product + * @param trxName transaction + * @return Array of Lots for Product + */ + public static MLot[] getProductLots (Properties ctx, int M_Product_ID, String trxName) + { + String sql = "SELECT * FROM M_Lot WHERE M_Product_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_Product_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MLot (ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (SQLException ex) + { + s_log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + // + MLot[] retValue = new MLot[list.size()]; + list.toArray(retValue); + return retValue; + } // getProductLots + + /** + * Get Lot for Product + * @param ctx context + * @param M_Product_ID product + * @param lot + * @param trxName transaction + * @return Array of Lots for Product + */ + public static MLot getProductLot (Properties ctx, int M_Product_ID, String lot, String trxName) + { + String sql = "SELECT * FROM M_Lot WHERE M_Product_ID=? AND Name=?"; + MLot retValue = null; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_Product_ID); + pstmt.setString(2, lot); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + retValue = new MLot (ctx, rs, trxName); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (SQLException ex) + { + s_log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + return retValue; + } // getProductLot + + /** + * Get Lot Key Name Pairs for Product + * @param M_Product_ID product + * @param trxName transaction + * @return Array of Lot Key Name Pairs for Product + */ + public static KeyNamePair[] getProductLotPairs (int M_Product_ID, String trxName) + { + String sql = "SELECT M_Lot_ID, Name FROM M_Lot WHERE M_Product_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_Product_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new KeyNamePair (rs.getInt(1), rs.getString(2))); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (SQLException ex) + { + s_log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + // + KeyNamePair[] retValue = new KeyNamePair[list.size()]; + list.toArray(retValue); + return retValue; + } // getProductLotPairs + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_Lot_ID ID + * @param trxName transaction + */ + public MLot (Properties ctx, int M_Lot_ID, String trxName) + { + super (ctx, M_Lot_ID, trxName); + /** if (M_Lot_ID == 0) + { + setM_Lot_ID (0); + setM_Product_ID (0); + setName (null); + } + **/ + } // MLot + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MLot (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MLot + + /** + * Parent Constructor + * @param ctl lot control + * @param M_Product_ID product + * @param Name name + */ + public MLot (MLotCtl ctl, int M_Product_ID, String Name) + { + this (ctl.getCtx(), 0, ctl.get_TrxName()); + setClientOrg(ctl); + setM_LotCtl_ID(ctl.getM_LotCtl_ID()); + setM_Product_ID (M_Product_ID); + setName (Name); + } // MLot + + /** + * String Representation + * @return info + */ + public String toString() + { + return getName(); + } // toString + +} // MLot diff --git a/base/src/org/compiere/model/MLotCtl.java b/base/src/org/compiere/model/MLotCtl.java new file mode 100644 index 0000000000..09cef07cca --- /dev/null +++ b/base/src/org/compiere/model/MLotCtl.java @@ -0,0 +1,85 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Lot Control Model + * + * @author Jorg Janke + * @version $Id: MLotCtl.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MLotCtl extends X_M_LotCtl +{ + /** + * Standard Constructor + * @param ctx context + * @param M_LotCtl_ID id + * @param trxName transaction + */ + public MLotCtl (Properties ctx, int M_LotCtl_ID, String trxName) + { + super (ctx, M_LotCtl_ID, trxName); + if (M_LotCtl_ID == 0) + { + // setM_LotCtl_ID (0); + setStartNo (1); + setCurrentNext (1); + setIncrementNo (1); + // setName (null); + } + } // MLotCtl + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MLotCtl (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MLotCtl + + /** + * Create new Lot. + * Increments Current Next and Commits + * @param M_Product_ID product + * @return saved Lot + */ + public MLot createLot (int M_Product_ID) + { + StringBuffer name = new StringBuffer(); + if (getPrefix() != null) + name.append(getPrefix()); + int no = getCurrentNext(); + name.append(no); + if (getSuffix() != null) + name.append(getSuffix()); + // + no += getIncrementNo(); + setCurrentNext(no); + save(); + // + MLot retValue = new MLot (this, M_Product_ID, name.toString()); + retValue.save(); + return retValue; + } // createLot + +} // MLotCtl diff --git a/base/src/org/compiere/model/MMailMsg.java b/base/src/org/compiere/model/MMailMsg.java new file mode 100644 index 0000000000..e0c2bbb040 --- /dev/null +++ b/base/src/org/compiere/model/MMailMsg.java @@ -0,0 +1,83 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Wab Store Mail Message Model + * @author Jorg Janke + * @version $Id: MMailMsg.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MMailMsg extends X_W_MailMsg +{ + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param W_MailMsg_ID id + * @param trxName trx + */ + public MMailMsg (Properties ctx, int W_MailMsg_ID, String trxName) + { + super (ctx, W_MailMsg_ID, trxName); + if (W_MailMsg_ID == 0) + { + // setW_Store_ID (0); + // setMailMsgType (null); + // setName (null); + // setSubject (null); + // setMessage (null); + } + } // MMailMsg + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MMailMsg (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MMailMsg + + /** + * Full Constructor + * @param parent store + * @param MailMsgType msg type + * @param Name name + * @param Subject subject + * @param Message message + * @param Message2 message + * @param Message3 message + */ + public MMailMsg (MStore parent, String MailMsgType, + String Name, String Subject, String Message, String Message2, String Message3) + { + this (parent.getCtx(), 0, parent.get_TrxName());; + setClientOrg(parent); + setW_Store_ID(parent.getW_Store_ID()); + setMailMsgType (MailMsgType); + setName (Name); + setSubject (Subject); + setMessage (Message); + setMessage2 (Message2); + setMessage3 (Message3); + } // MMailMsg + +} // MMailMsg diff --git a/base/src/org/compiere/model/MMailText.java b/base/src/org/compiere/model/MMailText.java new file mode 100644 index 0000000000..bfbd0eb834 --- /dev/null +++ b/base/src/org/compiere/model/MMailText.java @@ -0,0 +1,387 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Request Mail Template Model. + * Cannot be cached as it holds PO/BPartner/User to parse + * @author Jorg Janke + * @version $Id: MMailText.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MMailText extends X_R_MailText +{ + /** + * Standard Constructor + * @param ctx context + * @param R_MailText_ID id + * @param trxName transaction + */ + public MMailText(Properties ctx, int R_MailText_ID, String trxName) + { + super (ctx, R_MailText_ID, trxName); + } // MMailText + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MMailText (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MMailText + + /** Parse User */ + private MUser m_user = null; + /** Parse BPartner */ + private MBPartner m_bpartner = null; + /** Parse PO */ + private PO m_po = null; + /** Translated Header */ + private String m_MailHeader = null; + /** Translated Text */ + private String m_MailText = null; + /** Translated Text 2 */ + private String m_MailText2 = null; + /** Translated Text 3 */ + private String m_MailText3 = null; + /** Translation Cache */ + private static CCache s_cacheTrl = new CCache ("", 20); + + /** + * Get parsed/translated Mail Text + * @param all concatinate all + * @return parsed/translated text + */ + public String getMailText(boolean all) + { + if (m_MailText == null) + translate(); + if (!all) + return parse(m_MailText); + // + StringBuffer sb = new StringBuffer(); + sb.append(m_MailText); + String s = m_MailText2; + if (s != null && s.length() > 0) + sb.append("\n").append(s); + s = m_MailText3; + if (s != null && s.length() > 0) + sb.append("\n").append(s); + // + return parse(sb.toString()); + } // getMailText + + /** + * Get parsed/translated Mail Text + * @return parsed/translated text + */ + public String getMailText() + { + if (m_MailText == null) + translate(); + return parse (m_MailText); + } // getMailText + + /** + * Get parsed/translated Mail Text 2 + * @return parsed/translated text + */ + public String getMailText2() + { + if (m_MailText == null) + translate(); + return parse (m_MailText2); + } // getMailText2 + + /** + * Get parsed/translated Mail Text 2 + * @return parsed/translated text + */ + public String getMailText3() + { + if (m_MailText == null) + translate(); + return parse (m_MailText3); + } // getMailText3 + + /** + * Get parsed/translated Mail Header + * @return parsed/translated text + */ + public String getMailHeader() + { + if (m_MailHeader == null) + translate(); + return parse(m_MailHeader); + } // getMailHeader + + /************************************************************************** + * Parse Text + * @param text text + * @return parsed text + */ + private String parse (String text) + { + if (text.indexOf("@") == -1) + return text; + // Parse User + text = parse (text, m_user); + // Parse BP + text = parse (text, m_bpartner); + // Parse PO + text = parse (text, m_po); + // + return text; + } // parse + + /** + * Parse text + * @param text text + * @param po object + * @return parsed text + */ + private String parse (String text, PO po) + { + if (po == null || text.indexOf("@") == -1) + return text; + + String inStr = text; + String token; + StringBuffer outStr = new StringBuffer(); + + int i = inStr.indexOf("@"); + while (i != -1) + { + outStr.append(inStr.substring(0, i)); // up to @ + inStr = inStr.substring(i+1, inStr.length()); // from first @ + + int j = inStr.indexOf("@"); // next @ + if (j < 0) // no second tag + { + inStr = "@" + inStr; + break; + } + + token = inStr.substring(0, j); + outStr.append(parseVariable(token, po)); // replace context + + inStr = inStr.substring(j+1, inStr.length()); // from second @ + i = inStr.indexOf("@"); + } + + outStr.append(inStr); // add remainder + return outStr.toString(); + } // parse + + /** + * Parse Variable + * @param variable variable + * @param po po + * @return translated variable or if not found the original tag + */ + private String parseVariable (String variable, PO po) + { + int index = po.get_ColumnIndex(variable); + if (index == -1) + return "@" + variable + "@"; // keep for next + // + Object value = po.get_Value(index); + if (value == null) + return ""; + return value.toString(); + } // translate + + /** + * Set User for parse + * @param AD_User_ID user + */ + public void setUser (int AD_User_ID) + { + m_user = MUser.get (getCtx(), AD_User_ID); + } // setUser + + /** + * Set User for parse + * @param user user + */ + public void setUser (MUser user) + { + m_user = user; + } // setUser + + /** + * Set BPartner for parse + * @param C_BPartner_ID bp + */ + public void setBPartner (int C_BPartner_ID) + { + m_bpartner = new MBPartner (getCtx(), C_BPartner_ID, get_TrxName()); + } // setBPartner + + /** + * Set BPartner for parse + * @param bpartner bp + */ + public void setBPartner (MBPartner bpartner) + { + m_bpartner = bpartner; + } // setBPartner + + /** + * Set PO for parse + * @param po po + */ + public void setPO (PO po) + { + m_po = po; + } // setPO + + /** + * Set PO for parse + * @param po po + * @param analyse if set to true, search for BPartner/User + */ + public void setPO (PO po, boolean analyse) + { + m_po = po; + if (analyse) + { + int index = po.get_ColumnIndex("C_BPartner_ID"); + if (index > 0) + { + Object oo = po.get_Value(index); + if (oo instanceof Integer) + { + int C_BPartner_ID = ((Integer)oo).intValue(); + setBPartner(C_BPartner_ID); + } + } + index = po.get_ColumnIndex("AD_User_ID"); + if (index > 0) + { + Object oo = po.get_Value(index); + if (oo instanceof Integer) + { + int AD_User_ID = ((Integer)oo).intValue(); + setUser(AD_User_ID); + } + } + } + } // setPO + + /** + * Translate to BPartner Language + */ + private void translate() + { + if (m_bpartner != null && m_bpartner.getAD_Language() != null) + { + String key = m_bpartner.getAD_Language() + get_ID(); + MMailTextTrl trl = s_cacheTrl.get(key); + if (trl == null) + { + trl = getTranslation(m_bpartner.getAD_Language()); + if (trl != null) + s_cacheTrl.put(key, trl); + } + if (trl != null) + { + m_MailHeader = trl.MailHeader; + m_MailText = trl.MailText; + m_MailText2 = trl.MailText2; + m_MailText3 = trl.MailText3; + } + } + // No Translation + m_MailHeader = super.getMailHeader(); + m_MailText = super.getMailText(); + m_MailText2 = super.getMailText2(); + m_MailText3 = super.getMailText3(); + } // translate + + /** + * Get Translation + * @param AD_Language language + * @return trl + */ + private MMailTextTrl getTranslation (String AD_Language) + { + MMailTextTrl trl = null; + PreparedStatement pstmt = null; + String sql = "SELECT * FROM R_MailText_Trl WHERE R_MailText_ID=? AND AD_Language=?"; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getR_MailText_ID()); + pstmt.setString(2, AD_Language); + ResultSet rs = pstmt.executeQuery (); + if (rs.next()) + { + trl = new MMailTextTrl(); + trl.AD_Language = rs.getString("AD_Language"); + trl.MailHeader = rs.getString("MailHeader"); + trl.MailText = rs.getString("MailText"); + trl.MailText2 = rs.getString("MailText2"); + trl.MailText3 = rs.getString("MailText3"); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return trl; + } // getTranslation + + /** + * MailText Translation VO + */ + class MMailTextTrl + { + /** Language */ + String AD_Language = null; + /** Translated Header */ + String MailHeader = null; + /** Translated Text */ + String MailText = null; + /** Translated Text 2 */ + String MailText2 = null; + /** Translated Text 3 */ + String MailText3 = null; + } // MMailTextTrl + +} // MMailText diff --git a/base/src/org/compiere/model/MMatchInv.java b/base/src/org/compiere/model/MMatchInv.java new file mode 100644 index 0000000000..696af88bd8 --- /dev/null +++ b/base/src/org/compiere/model/MMatchInv.java @@ -0,0 +1,391 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Match Invoice (Receipt<>Invoice) Model. + * Accounting: + * - Not Invoiced Receipts (relief) + * - IPV + * + * @author Jorg Janke + * @version $Id: MMatchInv.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MMatchInv extends X_M_MatchInv +{ + /** + * Get InOut-Invoice Matches + * @param ctx context + * @param M_InOutLine_ID shipment + * @param C_InvoiceLine_ID invoice + * @param trxName transaction + * @return array of matches + */ + public static MMatchInv[] get (Properties ctx, + int M_InOutLine_ID, int C_InvoiceLine_ID, String trxName) + { + if (M_InOutLine_ID == 0 || C_InvoiceLine_ID == 0) + return new MMatchInv[]{}; + // + String sql = "SELECT * FROM M_MatchInv WHERE M_InOutLine_ID=? AND C_InvoiceLine_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_InOutLine_ID); + pstmt.setInt (2, C_InvoiceLine_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MMatchInv (ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MMatchInv[] retValue = new MMatchInv[list.size()]; + list.toArray (retValue); + return retValue; + } // get + + /** + * Get Inv Matches for InOut + * @param ctx context + * @param M_InOut_ID shipment + * @param trxName transaction + * @return array of matches + */ + public static MMatchInv[] getInOut (Properties ctx, + int M_InOut_ID, String trxName) + { + if (M_InOut_ID == 0) + return new MMatchInv[]{}; + // + String sql = "SELECT * FROM M_MatchInv m" + + " INNER JOIN M_InOutLine l ON (m.M_InOutLine_ID=l.M_InOutLine_ID) " + + "WHERE l.M_InOut_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_InOut_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MMatchInv (ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MMatchInv[] retValue = new MMatchInv[list.size()]; + list.toArray (retValue); + return retValue; + } // getInOut + + /** + * Get Inv Matches for Invoice + * @param ctx context + * @param C_Invoice_ID invoice + * @param trxName transaction + * @return array of matches + */ + public static MMatchInv[] getInvoice (Properties ctx, + int C_Invoice_ID, String trxName) + { + if (C_Invoice_ID == 0) + return new MMatchInv[]{}; + // + String sql = "SELECT * FROM M_MatchInv mi" + + " INNER JOIN C_InvoiceLine il ON (mi.C_InvoiceLine_ID=il.C_InvoiceLine_ID) " + + "WHERE il.C_Invoice_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, C_Invoice_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MMatchInv (ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MMatchInv[] retValue = new MMatchInv[list.size()]; + list.toArray (retValue); + return retValue; + } // getInvoice + + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MMatchInv.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_MatchInv_ID id + * @param trxName transaction + */ + public MMatchInv (Properties ctx, int M_MatchInv_ID, String trxName) + { + super (ctx, M_MatchInv_ID, trxName); + if (M_MatchInv_ID == 0) + { + // setDateTrx (new Timestamp(System.currentTimeMillis())); + // setC_InvoiceLine_ID (0); + // setM_InOutLine_ID (0); + // setM_Product_ID (0); + setM_AttributeSetInstance_ID(0); + // setQty (Env.ZERO); + setPosted (false); + setProcessed (false); + setProcessing (false); + } + } // MMatchInv + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MMatchInv (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MMatchInv + + /** + * Invoice Line Constructor + * @param iLine invoice line + * @param dateTrx optional date + * @param qty matched quantity + */ + public MMatchInv (MInvoiceLine iLine, Timestamp dateTrx, BigDecimal qty) + { + this (iLine.getCtx(), 0, iLine.get_TrxName()); + setClientOrg(iLine); + setC_InvoiceLine_ID(iLine.getC_InvoiceLine_ID()); + setM_InOutLine_ID(iLine.getM_InOutLine_ID()); + if (dateTrx != null) + setDateTrx (dateTrx); + setM_Product_ID (iLine.getM_Product_ID()); + setM_AttributeSetInstance_ID(iLine.getM_AttributeSetInstance_ID()); + setQty (qty); + setProcessed(true); // auto + } // MMatchInv + + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Set Trx Date + if (getDateTrx() == null) + setDateTrx (new Timestamp(System.currentTimeMillis())); + // Set Acct Date + if (getDateAcct() == null) + { + Timestamp ts = getNewerDateAcct(); + if (ts == null) + ts = getDateTrx(); + setDateAcct (ts); + } + if (getM_AttributeSetInstance_ID() == 0 && getM_InOutLine_ID() != 0) + { + MInOutLine iol = new MInOutLine (getCtx(), getM_InOutLine_ID(), get_TrxName()); + setM_AttributeSetInstance_ID(iol.getM_AttributeSetInstance_ID()); + } + return true; + } // beforeSave + + /** + * Get the later Date Acct from invoice or shipment + * @return date or null + */ + private Timestamp getNewerDateAcct() + { + Timestamp invoiceDate = null; + Timestamp shipDate = null; + + String sql = "SELECT i.DateAcct " + + "FROM C_InvoiceLine il" + + " INNER JOIN C_Invoice i ON (i.C_Invoice_ID=il.C_Invoice_ID) " + + "WHERE C_InvoiceLine_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getC_InvoiceLine_ID()); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + invoiceDate = rs.getTimestamp(1); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + sql = "SELECT io.DateAcct " + + "FROM M_InOutLine iol" + + " INNER JOIN M_InOut io ON (io.M_InOut_ID=iol.M_InOut_ID) " + + "WHERE iol.M_InOutLine_ID=?"; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getM_InOutLine_ID()); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + shipDate = rs.getTimestamp(1); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + // + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + if (invoiceDate == null) + return shipDate; + if (shipDate == null) + return invoiceDate; + if (invoiceDate.after(shipDate)) + return invoiceDate; + return shipDate; + } // getNewerDateAcct + + + /** + * Before Delete + * @return true if acct was deleted + */ + protected boolean beforeDelete () + { + if (isPosted()) + { + if (!MPeriod.isOpen(getCtx(), getDateTrx(), MDocType.DOCBASETYPE_MatchInvoice)) + return false; + setPosted(false); + return MFactAcct.delete (Table_ID, get_ID(), get_TrxName()) >= 0; + } + return true; + } // beforeDelete + + + /** + * After Delete + * @param success success + * @return success + */ + protected boolean afterDelete (boolean success) + { + if (success) + { + // Get Order and decrease invoices + MInvoiceLine iLine = new MInvoiceLine (getCtx(), getC_InvoiceLine_ID(), get_TrxName()); + int C_OrderLine_ID = iLine.getC_OrderLine_ID(); + if (C_OrderLine_ID == 0) + { + MInOutLine ioLine = new MInOutLine (getCtx(), getM_InOutLine_ID(), get_TrxName()); + C_OrderLine_ID = ioLine.getC_OrderLine_ID(); + } + // No Order Found + if (C_OrderLine_ID == 0) + return success; + // Find MatchPO + MMatchPO[] mPO = MMatchPO.get(getCtx(), C_OrderLine_ID, + getC_InvoiceLine_ID(), get_TrxName()); + for (int i = 0; i < mPO.length; i++) + { + if (mPO[i].getM_InOutLine_ID() == 0) + mPO[i].delete(true); + else + { + mPO[i].setC_InvoiceLine_ID(null); + mPO[i].save(); + } + } + } + return success; + } // afterDelete + +} // MMatchInv diff --git a/base/src/org/compiere/model/MMatchPO.java b/base/src/org/compiere/model/MMatchPO.java new file mode 100644 index 0000000000..ede4195be6 --- /dev/null +++ b/base/src/org/compiere/model/MMatchPO.java @@ -0,0 +1,814 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Match PO Model. + * = Created when processing Shipment or Order + * - Updates Order (delivered, invoiced) + * - Creates PPV acct + * + * @author Jorg Janke + * @version $Id: MMatchPO.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MMatchPO extends X_M_MatchPO +{ + /** + * Get PO Match with order/invoice + * @param ctx context + * @param C_OrderLine_ID order + * @param C_InvoiceLine_ID invoice + * @param trxName transaction + * @return array of matches + */ + public static MMatchPO[] get (Properties ctx, + int C_OrderLine_ID, int C_InvoiceLine_ID, String trxName) + { + if (C_OrderLine_ID == 0 || C_InvoiceLine_ID == 0) + return new MMatchPO[]{}; + // + String sql = "SELECT * FROM M_MatchPO WHERE C_OrderLine_ID=? AND C_InvoiceLine_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, C_OrderLine_ID); + pstmt.setInt (2, C_InvoiceLine_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MMatchPO (ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MMatchPO[] retValue = new MMatchPO[list.size()]; + list.toArray (retValue); + return retValue; + } // get + + /** + * Get PO Matches of receipt + * @param ctx context + * @param M_InOut_ID receipt + * @param trxName transaction + * @return array of matches + */ + public static MMatchPO[] getInOut (Properties ctx, + int M_InOut_ID, String trxName) + { + if (M_InOut_ID == 0) + return new MMatchPO[]{}; + // + String sql = "SELECT * FROM M_MatchPO m" + + " INNER JOIN M_InOutLine l ON (m.M_InOutLine_ID=l.M_InOutLine_ID) " + + "WHERE l.M_InOut_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_InOut_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MMatchPO (ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MMatchPO[] retValue = new MMatchPO[list.size()]; + list.toArray (retValue); + return retValue; + } // getInOut + + /** + * Get PO Matches of Invoice + * @param ctx context + * @param C_Invoice_ID invoice + * @param trxName transaction + * @return array of matches + */ + public static MMatchPO[] getInvoice (Properties ctx, + int C_Invoice_ID, String trxName) + { + if (C_Invoice_ID == 0) + return new MMatchPO[]{}; + // + String sql = "SELECT * FROM M_MatchPO mi" + + " INNER JOIN C_InvoiceLine il ON (mi.C_InvoiceLine_ID=il.C_InvoiceLine_ID) " + + "WHERE il.C_Invoice_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, C_Invoice_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MMatchPO (ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MMatchPO[] retValue = new MMatchPO[list.size()]; + list.toArray (retValue); + return retValue; + } // getInvoice + + + /** + * Find/Create PO(Inv) Match + * @param iLine invoice line + * @param sLine receipt line + * @param dateTrx date + * @param qty qty + * @return Match Record + */ + public static MMatchPO create (MInvoiceLine iLine, MInOutLine sLine, + Timestamp dateTrx, BigDecimal qty) + { + String trxName = null; + Properties ctx = null; + int C_OrderLine_ID = 0; + if (iLine != null) + { + trxName = iLine.get_TrxName(); + ctx = iLine.getCtx(); + C_OrderLine_ID = iLine.getC_OrderLine_ID(); + } + if (sLine != null) + { + trxName = sLine.get_TrxName(); + ctx = sLine.getCtx(); + C_OrderLine_ID = sLine.getC_OrderLine_ID(); + } + + MMatchPO retValue = null; + String sql = "SELECT * FROM M_MatchPO WHERE C_OrderLine_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, C_OrderLine_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MMatchPO mpo = new MMatchPO (ctx, rs, trxName); + if (qty.compareTo(mpo.getQty()) == 0) + { + if (iLine != null) + { + if (mpo.getC_InvoiceLine_ID() == 0 + || mpo.getC_InvoiceLine_ID() == iLine.getC_InvoiceLine_ID()) + { + mpo.setC_InvoiceLine_ID(iLine); + if (iLine.getM_AttributeSetInstance_ID() != 0) + { + if (mpo.getM_AttributeSetInstance_ID() == 0) + mpo.setM_AttributeSetInstance_ID(iLine.getM_AttributeSetInstance_ID()); + else if (mpo.getM_AttributeSetInstance_ID() != iLine.getM_AttributeSetInstance_ID()) + continue; + } + } + else + continue; + } + if (sLine != null) + { + if (mpo.getM_InOutLine_ID() == 0 + || mpo.getM_InOutLine_ID() == sLine.getM_InOutLine_ID()) + { + mpo.setM_InOutLine_ID(sLine.getM_InOutLine_ID()); + if (sLine.getM_AttributeSetInstance_ID() != 0) + { + if (mpo.getM_AttributeSetInstance_ID() == 0) + mpo.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); + else if (mpo.getM_AttributeSetInstance_ID() != sLine.getM_AttributeSetInstance_ID()) + continue; + } + } + else + continue; + } + retValue = mpo; + break; + } + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + // Create New + if (retValue == null) + { + if (sLine != null) + { + retValue = new MMatchPO (sLine, dateTrx, qty); + if (iLine != null) + retValue.setC_InvoiceLine_ID(iLine); + } + else if (iLine != null) + { + retValue = new MMatchPO (iLine, dateTrx, qty); + } + } + + return retValue; + } // create + + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MMatchPO.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_MatchPO_ID id + * @param trxName transaction + */ + public MMatchPO (Properties ctx, int M_MatchPO_ID, String trxName) + { + super (ctx, M_MatchPO_ID, trxName); + if (M_MatchPO_ID == 0) + { + // setC_OrderLine_ID (0); + // setDateTrx (new Timestamp(System.currentTimeMillis())); + // setM_InOutLine_ID (0); + // setM_Product_ID (0); + setM_AttributeSetInstance_ID(0); + // setQty (Env.ZERO); + setPosted (false); + setProcessed (false); + setProcessing (false); + } + } // MMatchPO + + /** + * Load Construor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MMatchPO (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MMatchPO + + /** + * Shipment Line Constructor + * @param sLine shipment line + * @param dateTrx optional date + * @param qty matched quantity + */ + public MMatchPO (MInOutLine sLine, Timestamp dateTrx, BigDecimal qty) + { + this (sLine.getCtx(), 0, sLine.get_TrxName()); + setClientOrg(sLine); + setM_InOutLine_ID (sLine.getM_InOutLine_ID()); + setC_OrderLine_ID (sLine.getC_OrderLine_ID()); + if (dateTrx != null) + setDateTrx (dateTrx); + setM_Product_ID (sLine.getM_Product_ID()); + setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); + setQty (qty); + setProcessed(true); // auto + } // MMatchPO + + /** + * Invoice Line Constructor + * @param iLine invoice line + * @param dateTrx optional date + * @param qty matched quantity + */ + public MMatchPO (MInvoiceLine iLine, Timestamp dateTrx, BigDecimal qty) + { + this (iLine.getCtx(), 0, iLine.get_TrxName()); + setClientOrg(iLine); + setC_InvoiceLine_ID(iLine); + if (iLine.getC_OrderLine_ID() != 0) + setC_OrderLine_ID (iLine.getC_OrderLine_ID()); + if (dateTrx != null) + setDateTrx (dateTrx); + setM_Product_ID (iLine.getM_Product_ID()); + setM_AttributeSetInstance_ID(iLine.getM_AttributeSetInstance_ID()); + setQty (qty); + setProcessed(true); // auto + } // MMatchPO + + /** Invoice Changed */ + private boolean m_isInvoiceLineChange = false; + /** InOut Changed */ + private boolean m_isInOutLineChange = false; + /** Order Line */ + private MOrderLine m_oLine = null; + /** Invoice Line */ + private MInvoiceLine m_iLine = null; + + + /** + * Set C_InvoiceLine_ID + * @param line line + */ + public void setC_InvoiceLine_ID (MInvoiceLine line) + { + m_iLine = line; + if (line == null) + setC_InvoiceLine_ID(0); + else + setC_InvoiceLine_ID(line.getC_InvoiceLine_ID()); + } // setC_InvoiceLine_ID + + /** + * Set C_InvoiceLine_ID + * @param C_InvoiceLine_ID id + */ + public void setC_InvoiceLine_ID (int C_InvoiceLine_ID) + { + int old = getC_InvoiceLine_ID(); + if (old != C_InvoiceLine_ID) + { + super.setC_InvoiceLine_ID (C_InvoiceLine_ID); + m_isInvoiceLineChange = true; + } + } // setC_InvoiceLine_ID + + /** + * Get Invoice Line + * @return invoice line or null + */ + public MInvoiceLine getInvoiceLine() + { + if (m_iLine == null && getC_InvoiceLine_ID() != 0) + m_iLine = new MInvoiceLine(getCtx(), getC_InvoiceLine_ID(), get_TrxName()); + return m_iLine; + } // getInvoiceLine + + /** + * Set M_InOutLine_ID + * @param M_InOutLine_ID id + */ + public void setM_InOutLine_ID (int M_InOutLine_ID) + { + int old = getM_InOutLine_ID(); + if (old != M_InOutLine_ID) + { + super.setM_InOutLine_ID (M_InOutLine_ID); + m_isInOutLineChange = true; + } + } // setM_InOutLine_ID + + /** + * Set C_OrderLine_ID + * @param line line + */ + public void setC_OrderLine_ID (MOrderLine line) + { + m_oLine = line; + if (line == null) + setC_OrderLine_ID(0); + else + setC_OrderLine_ID(line.getC_OrderLine_ID()); + } // setC_InvoiceLine_ID + + /** + * Get Order Line + * @return order line or null + */ + public MOrderLine getOrderLine() + { + if ((m_oLine == null && getC_OrderLine_ID() != 0) + || getC_OrderLine_ID() != m_oLine.getC_OrderLine_ID()) + m_oLine = new MOrderLine(getCtx(), getC_OrderLine_ID(), get_TrxName()); + return m_oLine; + } // getOrderLine + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Set Trx Date + if (getDateTrx() == null) + setDateTrx (new Timestamp(System.currentTimeMillis())); + // Set Acct Date + if (getDateAcct() == null) + { + Timestamp ts = getNewerDateAcct(); + if (ts == null) + ts = getDateTrx(); + setDateAcct (ts); + } + // Set ASI from Receipt + if (getM_AttributeSetInstance_ID() == 0 && getM_InOutLine_ID() != 0) + { + MInOutLine iol = new MInOutLine (getCtx(), getM_InOutLine_ID(), get_TrxName()); + setM_AttributeSetInstance_ID(iol.getM_AttributeSetInstance_ID()); + } + + // Find OrderLine + if (getC_OrderLine_ID() == 0) + { + MInvoiceLine il = null; + if (getC_InvoiceLine_ID() != 0) + { + il = getInvoiceLine(); + if (il.getC_OrderLine_ID() != 0) + setC_OrderLine_ID(il.getC_OrderLine_ID()); + } // get from invoice + if (getC_OrderLine_ID() == 0 && getM_InOutLine_ID() != 0) + { + MInOutLine iol = new MInOutLine (getCtx(), getM_InOutLine_ID(), get_TrxName()); + if (iol.getC_OrderLine_ID() != 0) + { + setC_OrderLine_ID(iol.getC_OrderLine_ID()); + if (il != null) + { + il.setC_OrderLine_ID(iol.getC_OrderLine_ID()); + il.save(); + } + } + } // get from shipment + } // find order line + + // Price Match Approval + if (getC_OrderLine_ID() != 0 + && getC_InvoiceLine_ID() != 0 + && (newRecord || + is_ValueChanged("C_OrderLine_ID") || is_ValueChanged("C_InvoiceLine_ID"))) + { + BigDecimal poPrice = getOrderLine().getPriceActual(); + BigDecimal invPrice = getInvoiceLine().getPriceActual(); + BigDecimal difference = poPrice.subtract(invPrice); + if (difference.signum() != 0) + { + difference = difference.multiply(getQty()); + setPriceMatchDifference(difference); + // Approval + MBPGroup group = MBPGroup.getOfBPartner(getCtx(), getOrderLine().getC_BPartner_ID()); + BigDecimal mt = group.getPriceMatchTolerance(); + if (mt != null && mt.signum() != 0) + { + BigDecimal poAmt = poPrice.multiply(getQty()); + BigDecimal maxTolerance = poAmt.multiply(mt); + maxTolerance = maxTolerance.abs() + .divide(Env.ONEHUNDRED, 2, BigDecimal.ROUND_HALF_UP); + difference = difference.abs(); + boolean ok = difference.compareTo(maxTolerance) <= 0; + log.config("Difference=" + getPriceMatchDifference() + + ", Max=" + maxTolerance + " => " + ok); + setIsApproved(ok); + } + } + else + { + setPriceMatchDifference(difference); + setIsApproved(true); + } + } + + return true; + } // beforeSave + + /** + * After Save. + * Set Order Qty Delivered/Invoiced + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + // Purchase Order Delivered/Invoiced + // (Reserved in VMatch and MInOut.completeIt) + if (success && getC_OrderLine_ID() != 0) + { + MOrderLine orderLine = getOrderLine(); + // + if (m_isInOutLineChange) + { + if (getM_InOutLine_ID() != 0) // new delivery + orderLine.setQtyDelivered(orderLine.getQtyDelivered().add(getQty())); + else // if (getM_InOutLine_ID() == 0) // reset to 0 + orderLine.setQtyDelivered(orderLine.getQtyDelivered().subtract(getQty())); + orderLine.setDateDelivered(getDateTrx()); // overwrite=last + } + if (m_isInvoiceLineChange) + { + if (getC_InvoiceLine_ID() != 0) // first time + orderLine.setQtyInvoiced(orderLine.getQtyInvoiced().add(getQty())); + else // if (getC_InvoiceLine_ID() == 0) // set to 0 + orderLine.setQtyInvoiced(orderLine.getQtyInvoiced().subtract(getQty())); + orderLine.setDateInvoiced(getDateTrx()); // overwrite=last + } + + // Update Order ASI if full match + if (orderLine.getM_AttributeSetInstance_ID() == 0 + && getM_InOutLine_ID() != 0) + { + MInOutLine iol = new MInOutLine (getCtx(), getM_InOutLine_ID(), get_TrxName()); + if (iol.getMovementQty().compareTo(orderLine.getQtyOrdered()) == 0) + orderLine.setM_AttributeSetInstance_ID(iol.getM_AttributeSetInstance_ID()); + } + return orderLine.save(); + } + return success; + } // afterSave + + + /** + * Get the later Date Acct from invoice or shipment + * @return date or null + */ + private Timestamp getNewerDateAcct() + { + Timestamp orderDate = null; + Timestamp invoiceDate = null; + Timestamp shipDate = null; + + String sql = "SELECT i.DateAcct " + + "FROM C_InvoiceLine il" + + " INNER JOIN C_Invoice i ON (i.C_Invoice_ID=il.C_Invoice_ID) " + + "WHERE C_InvoiceLine_ID=?"; + PreparedStatement pstmt = null; + if (getC_InvoiceLine_ID() != 0) + { + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getC_InvoiceLine_ID()); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + invoiceDate = rs.getTimestamp(1); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + } + // + sql = "SELECT io.DateAcct " + + "FROM M_InOutLine iol" + + " INNER JOIN M_InOut io ON (io.M_InOut_ID=iol.M_InOut_ID) " + + "WHERE iol.M_InOutLine_ID=?"; + if (getM_InOutLine_ID() != 0) + { + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getM_InOutLine_ID()); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + shipDate = rs.getTimestamp(1); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + } + // + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + // Assuming that order date is always earlier + if (invoiceDate == null) + return shipDate; + if (shipDate == null) + return invoiceDate; + if (invoiceDate.after(shipDate)) + return invoiceDate; + return shipDate; + } // getNewerDateAcct + + + /** + * Before Delete + * @return true if acct was deleted + */ + protected boolean beforeDelete () + { + if (isPosted()) + { + if (!MPeriod.isOpen(getCtx(), getDateTrx(), MDocType.DOCBASETYPE_MatchPO)) + return false; + setPosted(false); + return MFactAcct.delete (Table_ID, get_ID(), get_TrxName()) >= 0; + } + return true; + } // beforeDelete + + + /** + * After Delete. + * Set Order Qty Delivered/Invoiced + * @param success success + * @return success + */ + protected boolean afterDelete (boolean success) + { + // Order Delivered/Invoiced + // (Reserved in VMatch and MInOut.completeIt) + if (success && getC_OrderLine_ID() != 0) + { + MOrderLine orderLine = new MOrderLine (getCtx(), getC_OrderLine_ID(), get_TrxName()); + if (getM_InOutLine_ID() != 0) + orderLine.setQtyDelivered(orderLine.getQtyDelivered().subtract(getQty())); + if (getC_InvoiceLine_ID() != 0) + orderLine.setQtyInvoiced(orderLine.getQtyInvoiced().subtract(getQty())); + return orderLine.save(get_TrxName()); + } + return success; + } // afterDelete + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MMatchPO["); + sb.append (get_ID()) + .append (",Qty=").append (getQty()) + .append (",C_OrderLine_ID=").append (getC_OrderLine_ID()) + .append (",M_InOutLine_ID=").append (getM_InOutLine_ID()) + .append (",C_InvoiceLine_ID=").append (getC_InvoiceLine_ID()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Consolidate MPO entries. + * (data conversion issue) + * @param ctx context + */ + public static void consolidate(Properties ctx) + { + String sql = "SELECT * FROM M_MatchPO po " + + "WHERE EXISTS (SELECT * FROM M_MatchPO x " + + "WHERE po.C_OrderLine_ID=x.C_OrderLine_ID AND po.Qty=x.Qty " + + "GROUP BY C_OrderLine_ID, Qty " + + "HAVING COUNT(*) = 2) " + + " AND AD_Client_ID=?" + + "ORDER BY C_OrderLine_ID, M_InOutLine_ID"; + PreparedStatement pstmt = null; + int success = 0; + int errors = 0; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt(1, Env.getAD_Client_ID(ctx)); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MMatchPO po1 = new MMatchPO (ctx, rs, null); + if (rs.next()) + { + MMatchPO po2 = new MMatchPO (ctx, rs, null); + if (po1.getM_InOutLine_ID() != 0 && po1.getC_InvoiceLine_ID() == 0 + && po2.getM_InOutLine_ID() == 0 && po2.getC_InvoiceLine_ID() != 0) + { + String s1 = "UPDATE M_MatchPO SET C_InvoiceLine_ID=" + + po2.getC_InvoiceLine_ID() + + " WHERE M_MatchPO_ID=" + po1.getM_MatchPO_ID(); + int no1 = DB.executeUpdate(s1, null); + if (no1 != 1) + { + errors++; + s_log.warning("Not updated M_MatchPO_ID=" + po1.getM_MatchPO_ID()); + continue; + } + // + String s2 = "DELETE FROM Fact_Acct WHERE AD_Table_ID=473 AND Record_ID=?"; + int no2 = DB.executeUpdate(s2, po2.getM_MatchPO_ID(), null); + String s3 = "DELETE FROM M_MatchPO WHERE M_MatchPO_ID=?"; + int no3 = DB.executeUpdate(s3, po2.getM_MatchPO_ID(), null); + if (no2 == 0 && no3 == 1) + success++; + else + { + s_log.warning("M_MatchPO_ID=" + po2.getM_MatchPO_ID() + + " - Deleted=" + no2 + ", Acct=" + no3); + errors++; + } + } + } + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (errors == 0 && success == 0) + ; + else + s_log.info("Success #" + success + " - Error #" + errors); + } // consolidate + +} // MMatchPO diff --git a/base/src/org/compiere/model/MMeasure.java b/base/src/org/compiere/model/MMeasure.java new file mode 100644 index 0000000000..0d94d19a83 --- /dev/null +++ b/base/src/org/compiere/model/MMeasure.java @@ -0,0 +1,455 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Performance Measure + * + * @author Jorg Janke + * @version $Id: MMeasure.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MMeasure extends X_PA_Measure +{ + /** + * Get MMeasure from Cache + * @param ctx context + * @param PA_Measure_ID id + * @return MMeasure + */ + public static MMeasure get (Properties ctx, int PA_Measure_ID) + { + Integer key = new Integer (PA_Measure_ID); + MMeasure retValue = (MMeasure)s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MMeasure (ctx, PA_Measure_ID, null); + if (retValue.get_ID() != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache + = new CCache ("PA_Measure", 10); + + /** + * Standard Constructor + * @param ctx context + * @param PA_Measure_ID id + * @param trxName trx + */ + public MMeasure (Properties ctx, int PA_Measure_ID, String trxName) + { + super (ctx, PA_Measure_ID, trxName); + } // MMeasure + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MMeasure (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MMeasure + + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MMeasure["); + sb.append (get_ID()).append ("-").append (getName()).append ("]"); + return sb.toString (); + } // toString + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (MEASURETYPE_Calculated.equals(getMeasureType()) + && getPA_MeasureCalc_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "PA_MeasureCalc_ID")); + return false; + } + else if (MEASURETYPE_Ratio.equals(getMeasureType()) + && getPA_Ratio_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "PA_Ratio_ID")); + return false; + } + else if (MEASURETYPE_UserDefined.equals(getMeasureType()) + && (getCalculationClass() == null || getCalculationClass().length()==0)) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "CalculationClass")); + return false; + } + else if (MEASURETYPE_Request.equals(getMeasureType()) + && getR_RequestType_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "R_RequestType_ID")); + return false; + } + else if (MEASURETYPE_Project.equals(getMeasureType()) + && getC_ProjectType_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "C_ProjectType_ID")); + return false; + } + return true; + } // beforeSave + + /** + * After Save + * @param newRecord new + * @param success success + * @return succes + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + // Update Goals with Manual Measure + if (success && MEASURETYPE_Manual.equals(getMeasureType())) + updateManualGoals(); + + return success; + } // afterSave + + /** + * Update/save Goals + * @return true if updated + */ + public boolean updateGoals() + { + String mt = getMeasureType(); + try + { + if (MEASURETYPE_Manual.equals(mt)) + return updateManualGoals(); + else if (MEASURETYPE_Achievements.equals(mt)) + return updateAchievementGoals(); + else if (MEASURETYPE_Calculated.equals(mt)) + return updateCalculatedGoals(); + else if (MEASURETYPE_Ratio.equals(mt)) + return updateRatios(); + else if (MEASURETYPE_Request.equals(mt)) + return updateRequests(); + else if (MEASURETYPE_Project.equals(mt)) + return updateProjects(); + // Projects + } + catch (Exception e) + { + log.log(Level.SEVERE, "MeasureType=" + mt, e); + } + return false; + } // updateGoals + + /** + * Update/save Manual Goals + * @return true if updated + */ + private boolean updateManualGoals() + { + if (!MEASURETYPE_Manual.equals(getMeasureType())) + return false; + MGoal[] goals = MGoal.getMeasureGoals (getCtx(), getPA_Measure_ID()); + for (int i = 0; i < goals.length; i++) + { + MGoal goal = goals[i]; + goal.setMeasureActual(getManualActual()); + goal.save(); + } + return true; + } // updateManualGoals + + /** + * Update/save Goals with Achievement + * @return true if updated + */ + private boolean updateAchievementGoals() + { + if (!MEASURETYPE_Achievements.equals(getMeasureType())) + return false; + Timestamp today = new Timestamp(System.currentTimeMillis()); + MGoal[] goals = MGoal.getMeasureGoals (getCtx(), getPA_Measure_ID()); + for (int i = 0; i < goals.length; i++) + { + MGoal goal = goals[i]; + String MeasureScope = goal.getMeasureScope(); + String trunc = TimeUtil.TRUNC_DAY; + if (MGoal.MEASUREDISPLAY_Year.equals(MeasureScope)) + trunc = TimeUtil.TRUNC_YEAR; + else if (MGoal.MEASUREDISPLAY_Quarter.equals(MeasureScope)) + trunc = TimeUtil.TRUNC_QUARTER; + else if (MGoal.MEASUREDISPLAY_Month.equals(MeasureScope)) + trunc = TimeUtil.TRUNC_MONTH; + else if (MGoal.MEASUREDISPLAY_Week.equals(MeasureScope)) + trunc = TimeUtil.TRUNC_WEEK; + Timestamp compare = TimeUtil.trunc(today, trunc); + // + MAchievement[] achievements = MAchievement.getOfMeasure(getCtx(), getPA_Measure_ID()); + BigDecimal ManualActual = Env.ZERO; + for (int j = 0; j < achievements.length; j++) + { + MAchievement achievement = achievements[j]; + if (achievement.isAchieved() && achievement.getDateDoc() != null) + { + Timestamp ach = TimeUtil.trunc(achievement.getDateDoc(), trunc); + if (compare.equals(ach)) + ManualActual = ManualActual.add(achievement.getManualActual()); + } + } + goal.setMeasureActual(ManualActual); + goal.save(); + } + return true; + } // updateAchievementGoals + + /** + * Update/save Goals with Calculation + * @return true if updated + */ + private boolean updateCalculatedGoals() + { + if (!MEASURETYPE_Calculated.equals(getMeasureType())) + return false; + MGoal[] goals = MGoal.getMeasureGoals (getCtx(), getPA_Measure_ID()); + for (int i = 0; i < goals.length; i++) + { + MGoal goal = goals[i]; + // Find Role + MRole role = null; + if (goal.getAD_Role_ID() != 0) + role = MRole.get(getCtx(), goal.getAD_Role_ID()); + else if (goal.getAD_User_ID() != 0) + { + MUser user = MUser.get(getCtx(), goal.getAD_User_ID()); + MRole[] roles = user.getRoles(goal.getAD_Org_ID()); + if (roles.length > 0) + role = roles[0]; + } + if (role == null) + role = MRole.getDefault(getCtx(), false); // could result in wrong data + // + MMeasureCalc mc = MMeasureCalc.get(getCtx(), getPA_MeasureCalc_ID()); + if (mc == null || mc.get_ID() == 0 || mc.get_ID() != getPA_MeasureCalc_ID()) + { + log.log(Level.SEVERE, "Not found PA_MeasureCalc_ID=" + getPA_MeasureCalc_ID()); + return false; + } + BigDecimal ManualActual = null; + String sql = mc.getSqlPI(goal.getRestrictions(false), + goal.getMeasureScope(), getMeasureDataType(), null, role); + PreparedStatement pstmt = null; + try // SQL statement could be wrong + { + pstmt = DB.prepareStatement (sql, null); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + ManualActual = rs.getBigDecimal(1); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // SQL may return no rows or null + if (ManualActual == null) + { + ManualActual = Env.ZERO; + log.fine("No Value = " + sql); + } + goal.setMeasureActual(ManualActual); + goal.save(); + } + return true; + } // updateCalculatedGoals + + /** + * Update/save Goals with Ratios + * @return true if updated + */ + private boolean updateRatios() + { + if (!MEASURETYPE_Ratio.equals(getMeasureType())) + return false; + return false; + } // updateRatios + + /** + * Update/save Goals with Requests + * @return true if updated + */ + private boolean updateRequests() + { + if (!MEASURETYPE_Request.equals(getMeasureType()) + || getR_RequestType_ID() == 0) + return false; + MGoal[] goals = MGoal.getMeasureGoals (getCtx(), getPA_Measure_ID()); + for (int i = 0; i < goals.length; i++) + { + MGoal goal = goals[i]; + // Find Role + MRole role = null; + if (goal.getAD_Role_ID() != 0) + role = MRole.get(getCtx(), goal.getAD_Role_ID()); + else if (goal.getAD_User_ID() != 0) + { + MUser user = MUser.get(getCtx(), goal.getAD_User_ID()); + MRole[] roles = user.getRoles(goal.getAD_Org_ID()); + if (roles.length > 0) + role = roles[0]; + } + if (role == null) + role = MRole.getDefault(getCtx(), false); // could result in wrong data + // + BigDecimal ManualActual = null; + MRequestType rt = MRequestType.get(getCtx(), getR_RequestType_ID()); + String sql = rt.getSqlPI(goal.getRestrictions(false), + goal.getMeasureScope(), getMeasureDataType(), null, role); + PreparedStatement pstmt = null; + try // SQL statement could be wrong + { + pstmt = DB.prepareStatement (sql, null); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + ManualActual = rs.getBigDecimal(1); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // SQL may return no rows or null + if (ManualActual == null) + { + ManualActual = Env.ZERO; + log.fine("No Value = " + sql); + } + goal.setMeasureActual(ManualActual); + goal.save(); + } + return true; + } // updateRequests + + /** + * Update/save Goals with Projects + * @return true if updated + */ + private boolean updateProjects() + { + if (!MEASURETYPE_Project.equals(getMeasureType()) + || getC_ProjectType_ID() == 0) + return false; + MGoal[] goals = MGoal.getMeasureGoals (getCtx(), getPA_Measure_ID()); + for (int i = 0; i < goals.length; i++) + { + MGoal goal = goals[i]; + // Find Role + MRole role = null; + if (goal.getAD_Role_ID() != 0) + role = MRole.get(getCtx(), goal.getAD_Role_ID()); + else if (goal.getAD_User_ID() != 0) + { + MUser user = MUser.get(getCtx(), goal.getAD_User_ID()); + MRole[] roles = user.getRoles(goal.getAD_Org_ID()); + if (roles.length > 0) + role = roles[0]; + } + if (role == null) + role = MRole.getDefault(getCtx(), false); // could result in wrong data + // + BigDecimal ManualActual = null; + MProjectType pt = MProjectType.get(getCtx(), getC_ProjectType_ID()); + String sql = pt.getSqlPI(goal.getRestrictions(false), + goal.getMeasureScope(), getMeasureDataType(), null, role); + PreparedStatement pstmt = null; + try // SQL statement could be wrong + { + pstmt = DB.prepareStatement (sql, null); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + ManualActual = rs.getBigDecimal(1); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // SQL may return no rows or null + if (ManualActual == null) + { + ManualActual = Env.ZERO; + log.fine("No Value = " + sql); + } + goal.setMeasureActual(ManualActual); + goal.save(); + } + return true; + } // updateProjects + +} // MMeasure diff --git a/base/src/org/compiere/model/MMeasureCalc.java b/base/src/org/compiere/model/MMeasureCalc.java new file mode 100644 index 0000000000..c5c7626470 --- /dev/null +++ b/base/src/org/compiere/model/MMeasureCalc.java @@ -0,0 +1,457 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Performance Measure Calculation + * + * @author Jorg Janke + * @version $Id: MMeasureCalc.java,v 1.4 2006/09/25 00:59:41 jjanke Exp $ + */ +public class MMeasureCalc extends X_PA_MeasureCalc +{ + /** + * Get MMeasureCalc from Cache + * @param ctx context + * @param PA_MeasureCalc_ID id + * @return MMeasureCalc + */ + public static MMeasureCalc get (Properties ctx, int PA_MeasureCalc_ID) + { + Integer key = new Integer (PA_MeasureCalc_ID); + MMeasureCalc retValue = (MMeasureCalc)s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MMeasureCalc (ctx, PA_MeasureCalc_ID, null); + if (retValue.get_ID() != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache + = new CCache ("PA_MeasureCalc", 10); + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param PA_MeasureCalc_ID id + * @param trxName trx + */ + public MMeasureCalc (Properties ctx, int PA_MeasureCalc_ID, String trxName) + { + super (ctx, PA_MeasureCalc_ID, trxName); + } // MMeasureCalc + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MMeasureCalc (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MMeasureCalc + + + /** + * Get Sql to return single value for the Performance Indicator + * @param restrictions array of goal restrictions + * @param MeasureScope scope of this value + * @param MeasureDataType data type + * @param reportDate optional report date + * @param role role + * @return sql for performance indicator + */ + public String getSqlPI (MGoalRestriction[] restrictions, + String MeasureScope, String MeasureDataType, Timestamp reportDate, MRole role) + { + StringBuffer sb = new StringBuffer(getSelectClause()) + .append(" ") + .append(getWhereClause()); + // Date Restriction + if (getDateColumn() != null + && MMeasure.MEASUREDATATYPE_QtyAmountInTime.equals(MeasureDataType) + && !MGoal.MEASUREDISPLAY_Total.equals(MeasureScope)) + { + if (reportDate == null) + reportDate = new Timestamp(System.currentTimeMillis()); + String dateString = DB.TO_DATE(reportDate); + // http://download-west.oracle.com/docs/cd/B14117_01/server.101/b10759/functions207.htm#i1002084 + String trunc = "DD"; + if (MGoal.MEASUREDISPLAY_Year.equals(MeasureScope)) + trunc = "Y"; + else if (MGoal.MEASUREDISPLAY_Quarter.equals(MeasureScope)) + trunc = "Q"; + else if (MGoal.MEASUREDISPLAY_Month.equals(MeasureScope)) + trunc = "MM"; + else if (MGoal.MEASUREDISPLAY_Week.equals(MeasureScope)) + trunc = "D"; + // else if (MGoal.MEASUREDISPLAY_Day.equals(MeasureDisplay)) + // ; + sb.append(" AND TRUNC(") + .append(getDateColumn()).append(",'").append(trunc).append("')=TRUNC(") + .append(DB.TO_DATE(reportDate)).append(",'").append(trunc).append("')"); + } // date + String sql = addRestrictions(sb.toString(), restrictions, role); + + log.fine(sql); + return sql; + } // getSql + + /** + * Get Sql to value for the bar chart + * @param restrictions array of goal restrictions + * @param MeasureDisplay scope of this value + * @param startDate optional report start date + * @param role role + * @return sql for Bar Chart + */ + public String getSqlBarChart (MGoalRestriction[] restrictions, + String MeasureDisplay, Timestamp startDate, MRole role) + { + StringBuffer sb = new StringBuffer(); + String dateCol = null; + String groupBy = null; + if (getDateColumn() != null + && !MGoal.MEASUREDISPLAY_Total.equals(MeasureDisplay)) + { + String trunc = "D"; + if (MGoal.MEASUREDISPLAY_Year.equals(MeasureDisplay)) + trunc = "Y"; + else if (MGoal.MEASUREDISPLAY_Quarter.equals(MeasureDisplay)) + trunc = "Q"; + else if (MGoal.MEASUREDISPLAY_Month.equals(MeasureDisplay)) + trunc = "MM"; + else if (MGoal.MEASUREDISPLAY_Week.equals(MeasureDisplay)) + trunc = "W"; + // else if (MGoal.MEASUREDISPLAY_Day.equals(MeasureDisplay)) + // ; + dateCol = "TRUNC(" + getDateColumn() + ",'" + trunc + "') "; + groupBy = dateCol; + } + else + dateCol = "MAX(" + getDateColumn() + ") "; + // + String selectFrom = getSelectClause(); + int index = selectFrom.indexOf("FROM "); + if (index == -1) + index = selectFrom.toUpperCase().indexOf("FROM "); + if (index == -1) + throw new IllegalArgumentException("Cannot find FROM in sql - " + selectFrom); + sb.append(selectFrom.substring(0, index)) + .append(",").append(dateCol) + .append(selectFrom.substring(index)); + + // ** WHERE + sb.append(" ") + .append(getWhereClause()); + // Date Restriction + if (getDateColumn() != null + && startDate != null + && !MGoal.MEASUREDISPLAY_Total.equals(MeasureDisplay)) + { + String dateString = DB.TO_DATE(startDate); + sb.append(" AND ").append(getDateColumn()) + .append(">=").append(dateString); + } // date + String sql = addRestrictions(sb.toString(), restrictions, role); + if (groupBy != null) + sql += " GROUP BY " + groupBy; + // + log.fine(sql); + return sql; + } // getSqlBarChart + + /** + * Get Zoom Query + * @param restrictions restrictions + * @param MeasureDisplay display + * @param date date + * @param role role + * @return query + */ + public MQuery getQuery(MGoalRestriction[] restrictions, + String MeasureDisplay, Timestamp date, MRole role) + { + MQuery query = new MQuery(getAD_Table_ID()); + // + StringBuffer sql = new StringBuffer("SELECT ").append(getKeyColumn()).append(" "); + String from = getSelectClause(); + int index = from.indexOf("FROM "); + if (index == -1) + throw new IllegalArgumentException("Cannot find FROM " + from); + sql.append(from.substring(index)).append(" ") + .append(getWhereClause()); + // Date Range + if (getDateColumn() != null + && !MGoal.MEASUREDISPLAY_Total.equals(MeasureDisplay)) + { + String trunc = "D"; + if (MGoal.MEASUREDISPLAY_Year.equals(MeasureDisplay)) + trunc = "Y"; + else if (MGoal.MEASUREDISPLAY_Quarter.equals(MeasureDisplay)) + trunc = "Q"; + else if (MGoal.MEASUREDISPLAY_Month.equals(MeasureDisplay)) + trunc = "MM"; + else if (MGoal.MEASUREDISPLAY_Week.equals(MeasureDisplay)) + trunc = "W"; + // else if (MGoal.MEASUREDISPLAY_Day.equals(MeasureDisplay)) + // trunc = "D"; + sql.append(" AND TRUNC(").append(getDateColumn()).append(",'").append(trunc) + .append("')=TRUNC(").append(DB.TO_DATE(date)).append(",'").append(trunc).append("')"); + } + String finalSQL = addRestrictions(sql.toString(), restrictions, role); + // Execute + StringBuffer where = new StringBuffer(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (finalSQL, null); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + int id = rs.getInt(1); + if (where.length() > 0) + where.append(","); + where.append(id); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, finalSQL, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (where.length() == 0) + return MQuery.getNoRecordQuery(query.getTableName(), false); + // + StringBuffer whereClause = new StringBuffer (getKeyColumn()) + .append(" IN (").append(where).append(")"); + query.addRestriction(whereClause.toString()); + query.setRecordCount(1); + return query; + } // getQuery + + /** + * Add Restrictions + * @param sql existing sql + * @param restrictions restrictions + * @param role role + * @return updated sql + */ + private String addRestrictions(String sql, + MGoalRestriction[] restrictions, MRole role) + { + return addRestrictions(sql, false, restrictions, role, + getTableName(), getOrgColumn(), getBPartnerColumn(), getProductColumn()); + } // addRestrictions + + + /** + * Add Restrictions to SQL + * @param sql orig sql + * @param queryOnly incomplete sql for query restriction + * @param restrictions restrictions + * @param role role + * @param tableName table name + * @param orgColumn org column + * @param bpColumn bpartner column + * @param pColumn product column + * @return updated sql + */ + public static String addRestrictions(String sql, boolean queryOnly, + MGoalRestriction[] restrictions, MRole role, + String tableName, String orgColumn, String bpColumn, String pColumn) + { + StringBuffer sb = new StringBuffer(sql); + // Org Restrictions + if (orgColumn != null) + { + ArrayList list = new ArrayList(); + for (int i = 0; i < restrictions.length; i++) + { + if (MGoalRestriction.GOALRESTRICTIONTYPE_Organization.equals(restrictions[i].getGoalRestrictionType())) + list.add(restrictions[i].getOrg_ID()); + // Hierarchy comes here + } + if (list.size() == 1) + sb.append(" AND ").append(orgColumn) + .append("=").append(list.get(0)); + else if (list.size() > 1) + { + sb.append(" AND ").append(orgColumn).append(" IN ("); + for (int i = 0; i < list.size(); i++) + { + if (i > 0) + sb.append(","); + sb.append(list.get(i)); + } + sb.append(")"); + } + } // org + + // BPartner Restrictions + if (bpColumn != null) + { + ArrayList listBP = new ArrayList(); + ArrayList listBPG = new ArrayList(); + for (int i = 0; i < restrictions.length; i++) + { + if (MGoalRestriction.GOALRESTRICTIONTYPE_BusinessPartner.equals(restrictions[i].getGoalRestrictionType())) + listBP.add(restrictions[i].getC_BPartner_ID()); + // Hierarchy comes here + if (MGoalRestriction.GOALRESTRICTIONTYPE_BusPartnerGroup.equals(restrictions[i].getGoalRestrictionType())) + listBPG.add(restrictions[i].getC_BP_Group_ID()); + } + // BP + if (listBP.size() == 1) + sb.append(" AND ").append(bpColumn) + .append("=").append(listBP.get(0)); + else if (listBP.size() > 1) + { + sb.append(" AND ").append(bpColumn).append(" IN ("); + for (int i = 0; i < listBP.size(); i++) + { + if (i > 0) + sb.append(","); + sb.append(listBP.get(i)); + } + sb.append(")"); + } + // BPG + if (bpColumn.indexOf(".") == -1) + bpColumn = tableName + "." + bpColumn; + if (listBPG.size() == 1) + sb.append(" AND EXISTS (SELECT * FROM C_BPartner bpx WHERE ") + .append(bpColumn) + .append("=bpx.C_BPartner_ID AND bpx.C_BP_GROUP_ID=") + .append(listBPG.get(0)).append(")"); + else if (listBPG.size() > 1) + { + sb.append(" AND EXISTS (SELECT * FROM C_BPartner bpx WHERE ") + .append(bpColumn) + .append("=bpx.C_BPartner_ID AND bpx.C_BP_GROUP_ID IN ("); + for (int i = 0; i < listBPG.size(); i++) + { + if (i > 0) + sb.append(","); + sb.append(listBPG.get(i)); + } + sb.append("))"); + } + } // bp + + // Product Restrictions + if (pColumn != null) + { + ArrayList listP = new ArrayList(); + ArrayList listPC = new ArrayList(); + for (int i = 0; i < restrictions.length; i++) + { + if (MGoalRestriction.GOALRESTRICTIONTYPE_Product.equals(restrictions[i].getGoalRestrictionType())) + listP.add(restrictions[i].getM_Product_ID()); + // Hierarchy comes here + if (MGoalRestriction.GOALRESTRICTIONTYPE_ProductCategory.equals(restrictions[i].getGoalRestrictionType())) + listPC.add(restrictions[i].getM_Product_Category_ID()); + } + // Product + if (listP.size() == 1) + sb.append(" AND ").append(pColumn) + .append("=").append(listP.get(0)); + else if (listP.size() > 1) + { + sb.append(" AND ").append(pColumn).append(" IN ("); + for (int i = 0; i < listP.size(); i++) + { + if (i > 0) + sb.append(","); + sb.append(listP.get(i)); + } + sb.append(")"); + } + // Category + if (pColumn.indexOf(".") == -1) + pColumn = tableName + "." + pColumn; + if (listPC.size() == 1) + sb.append(" AND EXISTS (SELECT * FROM M_Product px WHERE ") + .append(pColumn) + .append("=px.M_Product_ID AND px.M_Product_Category_ID=") + .append(listPC.get(0)).append(")"); + else if (listPC.size() > 1) + { + sb.append(" AND EXISTS (SELECT * FROM M_Product px WHERE ") + .append(pColumn) + .append("=px.M_Product_ID AND px.M_Product_Category_ID IN ("); + for (int i = 0; i < listPC.size(); i++) + { + if (i > 0) + sb.append(","); + sb.append(listPC.get(i)); + } + sb.append("))"); + } + } // product + String finalSQL = sb.toString(); + if (queryOnly) + return finalSQL; + if (role == null) + role = MRole.getDefault(); + String retValue = role.addAccessSQL(finalSQL, tableName, true, false); + return retValue; + } // addRestrictions + + /** + * Get Table Name + * @return Table Name + */ + public String getTableName() + { + return MTable.getTableName (Env.getCtx(), getAD_Table_ID()); + } // getTavleName + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MMeasureCalc["); + sb.append (get_ID()).append ("-").append (getName()).append ("]"); + return sb.toString (); + } // toString + + +} // MMeasureCalc diff --git a/base/src/org/compiere/model/MMedia.java b/base/src/org/compiere/model/MMedia.java new file mode 100644 index 0000000000..4006f3061d --- /dev/null +++ b/base/src/org/compiere/model/MMedia.java @@ -0,0 +1,295 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Web Media Model + * + * @author Jorg Janke + * @version $Id: MMedia.java,v 1.7 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MMedia extends X_CM_Media +{ + /** + * Get Media + * @param project + * @return server list + */ + public static MMedia[] getMedia (MWebProject project) + { + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + String sql = "SELECT * FROM CM_Media WHERE CM_WebProject_ID=? ORDER BY CM_Media_ID"; + try + { + pstmt = DB.prepareStatement (sql, project.get_TrxName()); + pstmt.setInt (1, project.getCM_WebProject_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + list.add (new MMedia (project.getCtx(), rs, project.get_TrxName())); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MMedia[] retValue = new MMedia[list.size ()]; + list.toArray (retValue); + return retValue; + } // getMedia + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MMedia.class); + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param CM_Media_ID id + * @param trxName transaction + */ + public MMedia (Properties ctx, int CM_Media_ID, String trxName) + { + super (ctx, CM_Media_ID, trxName); + } // MMedia + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MMedia (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MMedia + + /** Web Project */ + private MWebProject m_project = null; + + /** + * Get Web Project + * @return web project + */ + public MWebProject getWebProject() + { + if (m_project == null) + m_project = MWebProject.get(getCtx(), getCM_WebProject_ID()); + return m_project; + } // getWebProject + + /** + * Get AD_Tree_ID + * @return tree + */ + public int getAD_Tree_ID() + { + return getWebProject().getAD_TreeCMM_ID(); + } // getAD_Tree_ID; + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (isSummary()) + { + setMediaType(null); + setAD_Image_ID(0); + } + + return true; + } // beforeSave + + /** + * After Save. + * Insert + * - create tree + * @param newRecord insert + * @param success save success + * @return true if saved + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + if (newRecord) + { + StringBuffer sb = new StringBuffer ("INSERT INTO AD_TreeNodeCMM " + + "(AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, " + + "AD_Tree_ID, Node_ID, Parent_ID, SeqNo) " + + "VALUES (") + .append(getAD_Client_ID()).append(",0, 'Y', SysDate, 0, SysDate, 0,") + .append(getAD_Tree_ID()).append(",").append(get_ID()) + .append(", 0, 999)"); + int no = DB.executeUpdate(sb.toString(), get_TrxName()); + if (no > 0) + log.fine("#" + no + " - TreeType=CMM"); + else + log.warning("#" + no + " - TreeType=CMM"); + return no > 0; + } + return success; + } // afterSave + + /** + * After Delete + * @param success + * @return deleted + */ + protected boolean afterDelete (boolean success) + { + if (!success) + return success; + // + StringBuffer sb = new StringBuffer ("DELETE FROM AD_TreeNodeCMM ") + .append(" WHERE Node_ID=").append(get_IDOld()) + .append(" AND AD_Tree_ID=").append(getAD_Tree_ID()); + int no = DB.executeUpdate(sb.toString(), get_TrxName()); + if (no > 0) + log.fine("#" + no + " - TreeType=CMM"); + else + log.warning("#" + no + " - TreeType=CMM"); + return no > 0; + } // afterDelete + + /** + * Get File Name + * @return file name return ID + */ + public String getFileName() + { + return get_ID() + getExtension(); + } // getFileName + + /** + * Get Extension with . + * @return extension + */ + public String getExtension() + { + String mt = getMediaType(); + if (MEDIATYPE_ApplicationPdf.equals(mt)) + return ".pdf"; + if (MEDIATYPE_ImageGif.equals(mt)) + return ".gif"; + if (MEDIATYPE_ImageJpeg.equals(mt)) + return ".jpg"; + if (MEDIATYPE_ImagePng.equals(mt)) + return ".png"; + if (MEDIATYPE_TextCss.equals(mt)) + return ".css"; + // Unknown + return ".dat"; + } // getExtension + + /** + * Get Image + * @return image or null + */ + public MImage getImage() + { + if (getAD_Image_ID() != 0) + return MImage.get(getCtx(), getAD_Image_ID()); + return null; + } // getImage + + /** + * Get Data as byte array + * @return data or null + */ + public byte[] getData() + { + MImage image = getImage(); + if (image != null) + { + byte[] data = image.getData(); + if (data == null || data.length == 0) + log.config("No Image Data"); + } + + // Attachment + MAttachment att = getAttachment(); + if (att == null || att.getEntryCount() == 0) + { + log.config("No Attachment"); + return null; + } + if (att.getEntryCount() > 1) + log.warning(getName() + " - more then one attachment - " + att.getEntryCount()); + // + MAttachmentEntry entry = att.getEntry(0); + if (entry == null) + { + log.config("No Attachment Entry"); + return null; + } + byte[] buffer = entry.getData(); + if (buffer == null || buffer.length == 0) + { + log.config("No Attachment Entry Data"); + return null; + } + return buffer; + } // getData + + /** + * Get Input Stream + * @return imput stream or null + */ + public InputStream getInputStream() + { + byte[] buffer = getData(); + ByteArrayInputStream is = new ByteArrayInputStream(buffer); + return is; + } // getInputStream + + /** + * Get Updated timestamp of Attachment + * @return updated or null if no attchment + */ + public Timestamp getAttachmentUpdated() + { + MAttachment att = getAttachment(); + if (att == null) + return null; + return att.getUpdated(); + } // getAttachmentUpdated + +} // MMedia diff --git a/base/src/org/compiere/model/MMediaDeploy.java b/base/src/org/compiere/model/MMediaDeploy.java new file mode 100644 index 0000000000..a9643f7782 --- /dev/null +++ b/base/src/org/compiere/model/MMediaDeploy.java @@ -0,0 +1,68 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Media Deployment Model + * + * @author Jorg Janke + * @version $Id: MMediaDeploy.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MMediaDeploy extends X_CM_MediaDeploy +{ + /** + * Standard Constructor + * @param ctx context + * @param CM_MediaDeploy_ID id + * @param trxName transaction + */ + public MMediaDeploy (Properties ctx, int CM_MediaDeploy_ID, String trxName) + { + super (ctx, CM_MediaDeploy_ID, trxName); + } // MMediaDeploy + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName tansaction + */ + public MMediaDeploy (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MMediaDeploy + + /** + * Deployment Parent Constructor + * @param server server + * @param media media + */ + public MMediaDeploy (MMediaServer server, MMedia media) + { + this (server.getCtx(), 0, server.get_TrxName()); + setCM_Media_Server_ID(server.getCM_Media_Server_ID()); + setCM_Media_ID(media.getCM_Media_ID()); + setClientOrg(server); + // + setIsDeployed(true); + setLastSynchronized(new Timestamp(System.currentTimeMillis())); + } // MMediaDeploy + +} // MMediaDeploy diff --git a/base/src/org/compiere/model/MMediaServer.java b/base/src/org/compiere/model/MMediaServer.java new file mode 100644 index 0000000000..52a17464a6 --- /dev/null +++ b/base/src/org/compiere/model/MMediaServer.java @@ -0,0 +1,196 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.sql.*; +import java.text.*; +import java.util.*; +import java.util.logging.*; + +import org.apache.commons.net.ftp.*; +import org.compiere.util.*; +import com.sun.org.apache.bcel.internal.generic.*; + +/** + * Media Server Model + * + * @author Jorg Janke + * @version $Id: MMediaServer.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MMediaServer extends X_CM_Media_Server +{ + /** + * Get Media Server + * @param project + * @return server list + */ + public static MMediaServer[] getMediaServer (MWebProject project) + { + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + String sql = "SELECT * FROM CM_Media_Server WHERE CM_WebProject_ID=? ORDER BY CM_Media_Server_ID"; + try + { + pstmt = DB.prepareStatement (sql, project.get_TrxName()); + pstmt.setInt (1, project.getCM_WebProject_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + list.add (new MMediaServer (project.getCtx(), rs, project.get_TrxName())); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MMediaServer[] retValue = new MMediaServer[list.size ()]; + list.toArray (retValue); + return retValue; + } // getMediaServer + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MMediaServer.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param CM_Media_Server_ID id + * @param trxName transaction + */ + public MMediaServer (Properties ctx, int CM_Media_Server_ID, String trxName) + { + super (ctx, CM_Media_Server_ID, trxName); + } // MMediaServer + + /** + * Load Constructor + * @param ctx context + * @param rs request + * @param trxName transaction + */ + public MMediaServer (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MMediaServer + + /** + * (Re-)Deploy all media + * @param media array of media to deploy + * @return true if deployed + */ + public boolean deploy (MMedia[] media) + { + // Check whether the host is our example localhost, we will not deploy locally, but this is no error + if (this.getIP_Address().equals("127.0.0.1") || this.getName().equals("localhost")) { + log.warning("You have not defined your own server, we will not really deploy to localhost!"); + return true; + } + + FTPClient ftp = new FTPClient(); + try + { + ftp.connect (getIP_Address()); + if (ftp.login (getUserName(), getPassword())) + log.info("Connected to " + getIP_Address() + " as " + getUserName()); + else + { + log.warning("Could NOT connect to " + getIP_Address() + " as " + getUserName()); + return false; + } + } + catch (Exception e) + { + log.log(Level.WARNING, "Could NOT connect to " + getIP_Address() + + " as " + getUserName(), e); + return false; + } + + boolean success = true; + String cmd = null; + // List the files in the directory + try + { + cmd = "cwd"; + ftp.changeWorkingDirectory (getFolder()); + // + cmd = "list"; + String[] fileNames = ftp.listNames(); + log.log(Level.FINE, "Number of files in " + getFolder() + ": " + fileNames.length); + + /* + FTPFile[] files = ftp.listFiles(); + log.config("Number of files in " + getFolder() + ": " + files.length); + for (int i = 0; i < files.length; i++) + log.fine(files[i].getTimestamp() + " \t" + files[i].getName());*/ + // + cmd = "bin"; + ftp.setFileType(FTPClient.BINARY_FILE_TYPE); + // + for (int i = 0; i < media.length; i++) + { + if (!media[i].isSummary()) { + log.log(Level.INFO, " Deploying Media Item:" + media[i].get_ID() + media[i].getExtension()); + MImage thisImage = media[i].getImage(); + + // Open the file and output streams + byte[] buffer = thisImage.getData(); + ByteArrayInputStream is = new ByteArrayInputStream(buffer); + + String fileName = media[i].get_ID() + media[i].getExtension(); + cmd = "put " + fileName; + ftp.storeFile(fileName, is); + is.close(); + } + } + } + catch (Exception e) + { + log.log(Level.WARNING, cmd, e); + success = false; + } + // Logout from the FTP Server and disconnect + try + { + cmd = "logout"; + ftp.logout(); + cmd = "disconnect"; + ftp.disconnect(); + } + catch (Exception e) + { + log.log(Level.WARNING, cmd, e); + } + ftp = null; + return success; + } // deploy + +} // MMediaServer diff --git a/base/src/org/compiere/model/MMovement.java b/base/src/org/compiere/model/MMovement.java new file mode 100644 index 0000000000..1fc72bf803 --- /dev/null +++ b/base/src/org/compiere/model/MMovement.java @@ -0,0 +1,825 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Inventory Movement Model + * + * @author Jorg Janke + * @version $Id: MMovement.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MMovement extends X_M_Movement implements DocAction +{ + /** + * Standard Constructor + * @param ctx context + * @param M_Movement_ID id + * @param trxName transaction + */ + public MMovement (Properties ctx, int M_Movement_ID, String trxName) + { + super (ctx, M_Movement_ID, trxName); + if (M_Movement_ID == 0) + { + // setC_DocType_ID (0); + setDocAction (DOCACTION_Complete); // CO + setDocStatus (DOCSTATUS_Drafted); // DR + setIsApproved (false); + setIsInTransit (false); + setMovementDate (new Timestamp(System.currentTimeMillis())); // @#Date@ + setPosted (false); + super.setProcessed (false); + } + } // MMovement + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MMovement (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MMovement + + /** Lines */ + private MMovementLine[] m_lines = null; + /** Confirmations */ + private MMovementConfirm[] m_confirms = null; + + /** + * Get Lines + * @param requery requery + * @return array of lines + */ + public MMovementLine[] getLines (boolean requery) + { + if (m_lines != null && !requery) + return m_lines; + // + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_MovementLine WHERE M_Movement_ID=? ORDER BY Line"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getM_Movement_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + list.add (new MMovementLine (getCtx(), rs, get_TrxName())); + } + rs.close (); + pstmt.close (); + pstmt = null; + } catch (Exception e) + { + log.log(Level.SEVERE, "getLines", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } catch (Exception e) + { + pstmt = null; + } + + m_lines = new MMovementLine[list.size ()]; + list.toArray (m_lines); + return m_lines; + } // getLines + + /** + * Get Confirmations + * @param requery requery + * @return array of Confirmations + */ + public MMovementConfirm[] getConfirmations(boolean requery) + { + if (m_confirms != null && !requery) + return m_confirms; + + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_MovementConfirm WHERE M_Movement_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getM_Movement_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MMovementConfirm(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getConfirmations", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + m_confirms = new MMovementConfirm[list.size ()]; + list.toArray (m_confirms); + return m_confirms; + } // getConfirmations + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * Get Document Info + * @return document info (untranslated) + */ + public String getDocumentInfo() + { + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + return dt.getName() + " " + getDocumentNo(); + } // getDocumentInfo + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + // ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.INVOICE, getC_Invoice_ID()); + // if (re == null) + return null; + // return re.getPDF(file); + } // createPDF + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getC_DocType_ID() == 0) + { + MDocType types[] = MDocType.getOfDocBaseType(getCtx(), MDocType.DOCBASETYPE_MaterialMovement); + if (types.length > 0) // get first + setC_DocType_ID(types[0].getC_DocType_ID()); + else + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@NotFound@ @C_DocType_ID@")); + return false; + } + } + return true; + } // beforeSave + + /** + * Set Processed. + * Propergate to Lines/Taxes + * @param processed processed + */ + public void setProcessed (boolean processed) + { + super.setProcessed (processed); + if (get_ID() == 0) + return; + String sql = "UPDATE M_MovementLine SET Processed='" + + (processed ? "Y" : "N") + + "' WHERE M_Movement_ID=" + getM_Movement_ID(); + int noLine = DB.executeUpdate(sql, get_TrxName()); + m_lines = null; + log.fine("Processed=" + processed + " - Lines=" + noLine); + } // setProcessed + + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // processIt + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info(toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info(toString()); + setDocAction(DOCACTION_Prepare); + return true; + } // invalidateIt + + /** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + + // Std Period open? + if (!MPeriod.isOpen(getCtx(), getMovementDate(), dt.getDocBaseType())) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + MMovementLine[] lines = getLines(false); + if (lines.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + // Add up Amounts + + + checkMaterialPolicy(); + + // Confirmation + if (dt.isInTransit()) + createConfirmation(); + + m_justPrepared = true; + if (!DOCACTION_Complete.equals(getDocAction())) + setDocAction(DOCACTION_Complete); + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Create Movement Confirmation + */ + private void createConfirmation() + { + MMovementConfirm[] confirmations = getConfirmations(false); + if (confirmations.length > 0) + return; + + // Create Confirmation + MMovementConfirm.create (this, false); + } // createConfirmation + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info(toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info(toString()); + setIsApproved(false); + return true; + } // rejectIt + + /** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + + // Outstanding (not processed) Incoming Confirmations ? + MMovementConfirm[] confirmations = getConfirmations(true); + for (int i = 0; i < confirmations.length; i++) + { + MMovementConfirm confirm = confirmations[i]; + if (!confirm.isProcessed()) + { + m_processMsg = "Open: @M_MovementConfirm_ID@ - " + + confirm.getDocumentNo(); + return DocAction.STATUS_InProgress; + } + } + + // Implicit Approval + if (!isApproved()) + approveIt(); + log.info(toString()); + + // + MMovementLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MMovementLine line = lines[i]; + MTransaction trxFrom = null; + if (line.getM_AttributeSetInstance_ID() == 0) + { + MMovementLineMA mas[] = MMovementLineMA.get(getCtx(), + line.getM_MovementLine_ID(), get_TrxName()); + for (int j = 0; j < mas.length; j++) + { + MMovementLineMA ma = mas[j]; + // + MStorage storageFrom = MStorage.get(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); + if (storageFrom == null) + storageFrom = MStorage.getCreate(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); + // + MStorage storageTo = MStorage.get(getCtx(), line.getM_LocatorTo_ID(), + line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); + if (storageTo == null) + storageTo = MStorage.getCreate(getCtx(), line.getM_LocatorTo_ID(), + line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); + // + storageFrom.setQtyOnHand(storageFrom.getQtyOnHand().subtract(ma.getMovementQty())); + if (!storageFrom.save(get_TrxName())) + { + m_processMsg = "Storage From not updated (MA)"; + return DocAction.STATUS_Invalid; + } + // + storageTo.setQtyOnHand(storageTo.getQtyOnHand().add(ma.getMovementQty())); + if (!storageTo.save(get_TrxName())) + { + m_processMsg = "Storage To not updated (MA)"; + return DocAction.STATUS_Invalid; + } + + // + trxFrom = new MTransaction (getCtx(), line.getAD_Org_ID(), + MTransaction.MOVEMENTTYPE_MovementFrom, + line.getM_Locator_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), + ma.getMovementQty().negate(), getMovementDate(), get_TrxName()); + trxFrom.setM_MovementLine_ID(line.getM_MovementLine_ID()); + if (!trxFrom.save()) + { + m_processMsg = "Transaction From not inserted (MA)"; + return DocAction.STATUS_Invalid; + } + // + MTransaction trxTo = new MTransaction (getCtx(), line.getAD_Org_ID(), + MTransaction.MOVEMENTTYPE_MovementTo, + line.getM_LocatorTo_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), + ma.getMovementQty(), getMovementDate(), get_TrxName()); + trxTo.setM_MovementLine_ID(line.getM_MovementLine_ID()); + if (!trxTo.save()) + { + m_processMsg = "Transaction To not inserted (MA)"; + return DocAction.STATUS_Invalid; + } + } + } + // Fallback - We have ASI + if (trxFrom == null) + { + MStorage storageFrom = MStorage.get(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), get_TrxName()); + if (storageFrom == null) + storageFrom = MStorage.getCreate(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), get_TrxName()); + // + MStorage storageTo = MStorage.get(getCtx(), line.getM_LocatorTo_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(), get_TrxName()); + if (storageTo == null) + storageTo = MStorage.getCreate(getCtx(), line.getM_LocatorTo_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(), get_TrxName()); + // + storageFrom.setQtyOnHand(storageFrom.getQtyOnHand().subtract(line.getMovementQty())); + if (!storageFrom.save(get_TrxName())) + { + m_processMsg = "Storage From not updated"; + return DocAction.STATUS_Invalid; + } + // + storageTo.setQtyOnHand(storageTo.getQtyOnHand().add(line.getMovementQty())); + if (!storageTo.save(get_TrxName())) + { + m_processMsg = "Storage To not updated"; + return DocAction.STATUS_Invalid; + } + + // + trxFrom = new MTransaction (getCtx(), line.getAD_Org_ID(), + MTransaction.MOVEMENTTYPE_MovementFrom, + line.getM_Locator_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), + line.getMovementQty().negate(), getMovementDate(), get_TrxName()); + trxFrom.setM_MovementLine_ID(line.getM_MovementLine_ID()); + if (!trxFrom.save()) + { + m_processMsg = "Transaction From not inserted"; + return DocAction.STATUS_Invalid; + } + // + MTransaction trxTo = new MTransaction (getCtx(), line.getAD_Org_ID(), + MTransaction.MOVEMENTTYPE_MovementTo, + line.getM_LocatorTo_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(), + line.getMovementQty(), getMovementDate(), get_TrxName()); + trxTo.setM_MovementLine_ID(line.getM_MovementLine_ID()); + if (!trxTo.save()) + { + m_processMsg = "Transaction To not inserted"; + return DocAction.STATUS_Invalid; + } + } // Fallback + } // for all lines + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + m_processMsg = valid; + return DocAction.STATUS_Invalid; + } + + // + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + + /** + * Check Material Policy + * Sets line ASI + */ + private void checkMaterialPolicy() + { + int no = MMovementLineMA.deleteMovementMA(getM_Movement_ID(), get_TrxName()); + if (no > 0) + log.config("Delete old #" + no); + MMovementLine[] lines = getLines(false); + + MClient client = MClient.get(getCtx()); + + // Check Lines + for (int i = 0; i < lines.length; i++) + { + MMovementLine line = lines[i]; + boolean needSave = false; + + // Attribute Set Instance + if (line.getM_AttributeSetInstance_ID() == 0) + { + MProduct product = MProduct.get(getCtx(), line.getM_Product_ID()); + MProductCategory pc = MProductCategory.get(getCtx(), product.getM_Product_Category_ID()); + String MMPolicy = pc.getMMPolicy(); + if (MMPolicy == null || MMPolicy.length() == 0) + MMPolicy = client.getMMPolicy(); + // + MStorage[] storages = MStorage.getAllWithASI(getCtx(), + line.getM_Product_ID(), line.getM_Locator_ID(), + MClient.MMPOLICY_FiFo.equals(MMPolicy), get_TrxName()); + BigDecimal qtyToDeliver = line.getMovementQty(); + for (int ii = 0; ii < storages.length; ii++) + { + MStorage storage = storages[ii]; + if (ii == 0) + { + if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) + { + line.setM_AttributeSetInstance_ID(storage.getM_AttributeSetInstance_ID()); + needSave = true; + log.config("Direct - " + line); + qtyToDeliver = Env.ZERO; + } + else + { + log.config("Split - " + line); + MMovementLineMA ma = new MMovementLineMA (line, + storage.getM_AttributeSetInstance_ID(), + storage.getQtyOnHand()); + if (!ma.save()) + ; + qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); + log.fine("#" + ii + ": " + ma + ", QtyToDeliver=" + qtyToDeliver); + } + } + else // create addl material allocation + { + MMovementLineMA ma = new MMovementLineMA (line, + storage.getM_AttributeSetInstance_ID(), + qtyToDeliver); + if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) + qtyToDeliver = Env.ZERO; + else + { + ma.setMovementQty(storage.getQtyOnHand()); + qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); + } + if (!ma.save()) + ; + log.fine("#" + ii + ": " + ma + ", QtyToDeliver=" + qtyToDeliver); + } + if (qtyToDeliver.signum() == 0) + break; + } // for all storages + + // No AttributeSetInstance found for remainder + if (qtyToDeliver.signum() != 0) + { + MMovementLineMA ma = new MMovementLineMA (line, + 0, qtyToDeliver); + if (!ma.save()) + ; + log.fine("##: " + ma); + } + } // attributeSetInstance + + if (needSave && !line.save()) + log.severe("NOT saved " + line); + } // for all lines + + } // checkMaterialPolicy + + /** + * Void Document. + * @return true if success + */ + public boolean voidIt() + { + log.info(toString()); + if (DOCSTATUS_Closed.equals(getDocStatus()) + || DOCSTATUS_Reversed.equals(getDocStatus()) + || DOCSTATUS_Voided.equals(getDocStatus())) + { + m_processMsg = "Document Closed: " + getDocStatus(); + return false; + } + + // Not Processed + if (DOCSTATUS_Drafted.equals(getDocStatus()) + || DOCSTATUS_Invalid.equals(getDocStatus()) + || DOCSTATUS_InProgress.equals(getDocStatus()) + || DOCSTATUS_Approved.equals(getDocStatus()) + || DOCSTATUS_NotApproved.equals(getDocStatus()) ) + { + // Set lines to 0 + MMovementLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MMovementLine line = lines[i]; + BigDecimal old = line.getMovementQty(); + if (old.compareTo(Env.ZERO) != 0) + { + line.setMovementQty(Env.ZERO); + line.addDescription("Void (" + old + ")"); + line.save(get_TrxName()); + } + } + } + else + { + return reverseCorrectIt(); + } + + setProcessed(true); + setDocAction(DOCACTION_None); + return true; + } // voidIt + + /** + * Close Document. + * @return true if success + */ + public boolean closeIt() + { + log.info(toString()); + + // Close Not delivered Qty + setDocAction(DOCACTION_None); + return true; + } // closeIt + + /** + * Reverse Correction + * @return false + */ + public boolean reverseCorrectIt() + { + log.info(toString()); + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + if (!MPeriod.isOpen(getCtx(), getMovementDate(), dt.getDocBaseType())) + { + m_processMsg = "@PeriodClosed@"; + return false; + } + + // Deep Copy + MMovement reversal = new MMovement(getCtx(), 0, get_TrxName()); + copyValues(this, reversal, getAD_Client_ID(), getAD_Org_ID()); + reversal.setDocStatus(DOCSTATUS_Drafted); + reversal.setDocAction(DOCACTION_Complete); + reversal.setIsApproved (false); + reversal.setIsInTransit (false); + reversal.setPosted(false); + reversal.setProcessed(false); + reversal.addDescription("{->" + getDocumentNo() + ")"); + if (!reversal.save()) + { + m_processMsg = "Could not create Movement Reversal"; + return false; + } + + // Reverse Line Qty + MMovementLine[] oLines = getLines(true); + for (int i = 0; i < oLines.length; i++) + { + MMovementLine oLine = oLines[i]; + MMovementLine rLine = new MMovementLine(getCtx(), 0, get_TrxName()); + copyValues(oLine, rLine, oLine.getAD_Client_ID(), oLine.getAD_Org_ID()); + rLine.setM_Movement_ID(reversal.getM_Movement_ID()); + // + rLine.setMovementQty(rLine.getMovementQty().negate()); + rLine.setTargetQty(Env.ZERO); + rLine.setScrappedQty(Env.ZERO); + rLine.setConfirmedQty(Env.ZERO); + rLine.setProcessed(false); + if (!rLine.save()) + { + m_processMsg = "Could not create Movement Reversal Line"; + return false; + } + } + // + if (!reversal.processIt(DocAction.ACTION_Complete)) + { + m_processMsg = "Reversal ERROR: " + reversal.getProcessMsg(); + return false; + } + reversal.closeIt(); + reversal.setDocStatus(DOCSTATUS_Reversed); + reversal.setDocAction(DOCACTION_None); + reversal.save(); + m_processMsg = reversal.getDocumentNo(); + + // Update Reversed (this) + addDescription("(" + reversal.getDocumentNo() + "<-)"); + setProcessed(true); + setDocStatus(DOCSTATUS_Reversed); // may come from void + setDocAction(DOCACTION_None); + + return true; + } // reverseCorrectionIt + + /** + * Reverse Accrual - none + * @return false + */ + public boolean reverseAccrualIt() + { + log.info(toString()); + return false; + } // reverseAccrualIt + + /** + * Re-activate + * @return false + */ + public boolean reActivateIt() + { + log.info(toString()); + return false; + } // reActivateIt + + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getDocumentNo()); + // : Total Lines = 123.00 (#1) + sb.append(": ") + .append(Msg.translate(getCtx(),"ApprovalAmt")).append("=").append(getApprovalAmt()) + .append(" (#").append(getLines(false).length).append(")"); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner (Responsible) + * @return AD_User_ID + */ + public int getDoc_User_ID() + { + return getCreatedBy(); + } // getDoc_User_ID + + /** + * Get Document Currency + * @return C_Currency_ID + */ + public int getC_Currency_ID() + { + // MPriceList pl = MPriceList.get(getCtx(), getM_PriceList_ID()); + // return pl.getC_Currency_ID(); + return 0; + } // getC_Currency_ID + +} // MMovement + diff --git a/base/src/org/compiere/model/MMovementConfirm.java b/base/src/org/compiere/model/MMovementConfirm.java new file mode 100644 index 0000000000..5de557fef0 --- /dev/null +++ b/base/src/org/compiere/model/MMovementConfirm.java @@ -0,0 +1,610 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.process.*; +import org.compiere.util.*; + + +/** + * Inventory Movement Confirmation + * + * @author Jorg Janke + * @version $Id: MMovementConfirm.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MMovementConfirm extends X_M_MovementConfirm implements DocAction +{ + /** + * Create Confirmation or return existing one + * @param move movement + * @param checkExisting if false, new confirmation is created + * @return Confirmation + */ + public static MMovementConfirm create (MMovement move, boolean checkExisting) + { + if (checkExisting) + { + MMovementConfirm[] confirmations = move.getConfirmations(false); + for (int i = 0; i < confirmations.length; i++) + { + MMovementConfirm confirm = confirmations[i]; + return confirm; + } + } + + MMovementConfirm confirm = new MMovementConfirm (move); + confirm.save(move.get_TrxName()); + MMovementLine[] moveLines = move.getLines(false); + for (int i = 0; i < moveLines.length; i++) + { + MMovementLine mLine = moveLines[i]; + MMovementLineConfirm cLine = new MMovementLineConfirm (confirm); + cLine.setMovementLine(mLine); + cLine.save(move.get_TrxName()); + } + return confirm; + } // MInOutConfirm + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_MovementConfirm_ID id + * @param trxName transaction + */ + public MMovementConfirm (Properties ctx, int M_MovementConfirm_ID, String trxName) + { + super (ctx, M_MovementConfirm_ID, trxName); + if (M_MovementConfirm_ID == 0) + { + // setM_Movement_ID (0); + setDocAction (DOCACTION_Complete); + setDocStatus (DOCSTATUS_Drafted); + setIsApproved (false); // N + setProcessed (false); + } + } // MMovementConfirm + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MMovementConfirm (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MMovementConfirm + + /** + * Parent Constructor + * @param move movement + */ + public MMovementConfirm (MMovement move) + { + this (move.getCtx(), 0, move.get_TrxName()); + setClientOrg(move); + setM_Movement_ID(move.getM_Movement_ID()); + } // MInOutConfirm + + /** Confirm Lines */ + private MMovementLineConfirm[] m_lines = null; + + /** Physical Inventory From */ + private MInventory m_inventoryFrom = null; + /** Physical Inventory To */ + private MInventory m_inventoryTo = null; + /** Physical Inventory Info */ + private String m_inventoryInfo = null; + + /** + * Get Lines + * @param requery requery + * @return array of lines + */ + public MMovementLineConfirm[] getLines (boolean requery) + { + if (m_lines != null && !requery) + return m_lines; + String sql = "SELECT * FROM M_MovementLineConfirm " + + "WHERE M_MovementConfirm_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getM_MovementConfirm_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MMovementLineConfirm(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_lines = new MMovementLineConfirm[list.size ()]; + list.toArray (m_lines); + return m_lines; + } // getLines + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + + /** + * Set Approved + * @param IsApproved approval + */ + public void setIsApproved (boolean IsApproved) + { + if (IsApproved && !isApproved()) + { + int AD_User_ID = Env.getAD_User_ID(getCtx()); + MUser user = MUser.get(getCtx(), AD_User_ID); + String info = user.getName() + + ": " + + Msg.translate(getCtx(), "IsApproved") + + " - " + new Timestamp(System.currentTimeMillis()); + addDescription(info); + } + super.setIsApproved (IsApproved); + } // setIsApproved + + + /** + * Get Document Info + * @return document info (untranslated) + */ + public String getDocumentInfo() + { + return Msg.getElement(getCtx(), "M_MovementConfirm_ID") + " " + getDocumentNo(); + } // getDocumentInfo + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + // ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.INVOICE, getC_Invoice_ID()); + // if (re == null) + return null; + // return re.getPDF(file); + } // createPDF + + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // processIt + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info("unlockIt - " + toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info("invalidateIt - " + toString()); + setDocAction(DOCACTION_Prepare); + return true; + } // invalidateIt + + /** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + + // Std Period open? + if (!MPeriod.isOpen(getCtx(), getUpdated(), MDocType.DOCBASETYPE_MaterialMovement)) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + + MMovementLineConfirm[] lines = getLines(true); + if (lines.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + boolean difference = false; + for (int i = 0; i < lines.length; i++) + { + if (!lines[i].isFullyConfirmed()) + { + difference = true; + break; + } + } + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + m_processMsg = valid; + return DocAction.STATUS_Invalid; + } + + // + m_justPrepared = true; + if (!DOCACTION_Complete.equals(getDocAction())) + setDocAction(DOCACTION_Complete); + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info("approveIt - " + toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info("rejectIt - " + toString()); + setIsApproved(false); + return true; + } // rejectIt + + /** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + // Implicit Approval + if (!isApproved()) + approveIt(); + log.info("completeIt - " + toString()); + // + MMovement move = new MMovement (getCtx(), getM_Movement_ID(), get_TrxName()); + MMovementLineConfirm[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MMovementLineConfirm confirm = lines[i]; + confirm.set_TrxName(get_TrxName()); + if (!confirm.processLine ()) + { + m_processMsg = "ShipLine not saved - " + confirm; + return DocAction.STATUS_Invalid; + } + if (confirm.isFullyConfirmed()) + { + confirm.setProcessed(true); + confirm.save(get_TrxName()); + } + else + { + if (createDifferenceDoc (move, confirm)) + { + confirm.setProcessed(true); + confirm.save(get_TrxName()); + } + else + { + log.log(Level.SEVERE, "completeIt - Scrapped=" + confirm.getScrappedQty() + + " - Difference=" + confirm.getDifferenceQty()); + + m_processMsg = "Differnce Doc not created"; + return DocAction.STATUS_Invalid; + } + } + } // for all lines + + if (m_inventoryInfo != null) + { + m_processMsg = " @M_Inventory_ID@: " + m_inventoryInfo; + addDescription(Msg.translate(getCtx(), "M_Inventory_ID") + + ": " + m_inventoryInfo); + } + + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + /** + * Create Difference Document. + * Creates one or two inventory lines + * @param move movement + * @param confirm confirm line + * @return true if created + */ + private boolean createDifferenceDoc (MMovement move, MMovementLineConfirm confirm) + { + MMovementLine mLine = confirm.getLine(); + + // Difference - Create Inventory Difference for Source Location + if (Env.ZERO.compareTo(confirm.getDifferenceQty()) != 0) + { + // Get Warehouse for Source + MLocator loc = MLocator.get(getCtx(), mLine.getM_Locator_ID()); + if (m_inventoryFrom != null + && m_inventoryFrom.getM_Warehouse_ID() != loc.getM_Warehouse_ID()) + m_inventoryFrom = null; + + if (m_inventoryFrom == null) + { + MWarehouse wh = MWarehouse.get(getCtx(), loc.getM_Warehouse_ID()); + m_inventoryFrom = new MInventory (wh); + m_inventoryFrom.setDescription(Msg.translate(getCtx(), "M_MovementConfirm_ID") + " " + getDocumentNo()); + if (!m_inventoryFrom.save(get_TrxName())) + { + m_processMsg += "Inventory not created"; + return false; + } + // First Inventory + if (getM_Inventory_ID() == 0) + { + setM_Inventory_ID(m_inventoryFrom.getM_Inventory_ID()); + m_inventoryInfo = m_inventoryFrom.getDocumentNo(); + } + else + m_inventoryInfo += "," + m_inventoryFrom.getDocumentNo(); + } + + log.info("createDifferenceDoc - Difference=" + confirm.getDifferenceQty()); + MInventoryLine line = new MInventoryLine (m_inventoryFrom, + mLine.getM_Locator_ID(), mLine.getM_Product_ID(), mLine.getM_AttributeSetInstance_ID(), + confirm.getDifferenceQty(), Env.ZERO); + line.setDescription(Msg.translate(getCtx(), "DifferenceQty")); + if (!line.save(get_TrxName())) + { + m_processMsg += "Inventory Line not created"; + return false; + } + confirm.setM_InventoryLine_ID(line.getM_InventoryLine_ID()); + } // Difference + + // Scrapped - Create Inventory Difference for Target Location + if (Env.ZERO.compareTo(confirm.getScrappedQty()) != 0) + { + // Get Warehouse for Target + MLocator loc = MLocator.get(getCtx(), mLine.getM_LocatorTo_ID()); + if (m_inventoryTo != null + && m_inventoryTo.getM_Warehouse_ID() != loc.getM_Warehouse_ID()) + m_inventoryTo = null; + + if (m_inventoryTo == null) + { + MWarehouse wh = MWarehouse.get(getCtx(), loc.getM_Warehouse_ID()); + m_inventoryTo = new MInventory (wh); + m_inventoryTo.setDescription(Msg.translate(getCtx(), "M_MovementConfirm_ID") + " " + getDocumentNo()); + if (!m_inventoryTo.save(get_TrxName())) + { + m_processMsg += "Inventory not created"; + return false; + } + // First Inventory + if (getM_Inventory_ID() == 0) + { + setM_Inventory_ID(m_inventoryTo.getM_Inventory_ID()); + m_inventoryInfo = m_inventoryTo.getDocumentNo(); + } + else + m_inventoryInfo += "," + m_inventoryTo.getDocumentNo(); + } + + log.info("createDifferenceDoc - Scrapped=" + confirm.getScrappedQty()); + MInventoryLine line = new MInventoryLine (m_inventoryTo, + mLine.getM_LocatorTo_ID(), mLine.getM_Product_ID(), mLine.getM_AttributeSetInstance_ID(), + confirm.getScrappedQty(), Env.ZERO); + line.setDescription(Msg.translate(getCtx(), "ScrappedQty")); + if (!line.save(get_TrxName())) + { + m_processMsg += "Inventory Line not created"; + return false; + } + confirm.setM_InventoryLine_ID(line.getM_InventoryLine_ID()); + } // Scrapped + + return true; + } // createDifferenceDoc + + /** + * Void Document. + * @return false + */ + public boolean voidIt() + { + log.info("voidIt - " + toString()); + return false; + } // voidIt + + /** + * Close Document. + * Cancel not delivered Qunatities + * @return true if success + */ + public boolean closeIt() + { + log.info("closeIt - " + toString()); + + // Close Not delivered Qty + setDocAction(DOCACTION_None); + return true; + } // closeIt + + /** + * Reverse Correction + * @return false + */ + public boolean reverseCorrectIt() + { + log.info("reverseCorrectIt - " + toString()); + return false; + } // reverseCorrectionIt + + /** + * Reverse Accrual - none + * @return false + */ + public boolean reverseAccrualIt() + { + log.info("reverseAccrualIt - " + toString()); + return false; + } // reverseAccrualIt + + /** + * Re-activate + * @return false + */ + public boolean reActivateIt() + { + log.info("reActivateIt - " + toString()); + return false; + } // reActivateIt + + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getDocumentNo()); + // : Total Lines = 123.00 (#1) + sb.append(": ") + .append(Msg.translate(getCtx(),"ApprovalAmt")).append("=").append(getApprovalAmt()) + .append(" (#").append(getLines(false).length).append(")"); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner (Responsible) + * @return AD_User_ID + */ + public int getDoc_User_ID() + { + return getUpdatedBy(); + } // getDoc_User_ID + + /** + * Get Document Currency + * @return C_Currency_ID + */ + public int getC_Currency_ID() + { + // MPriceList pl = MPriceList.get(getCtx(), getM_PriceList_ID()); + // return pl.getC_Currency_ID(); + return 0; + } // getC_Currency_ID + + +} // MMovementConfirm diff --git a/base/src/org/compiere/model/MMovementLine.java b/base/src/org/compiere/model/MMovementLine.java new file mode 100644 index 0000000000..49348723f0 --- /dev/null +++ b/base/src/org/compiere/model/MMovementLine.java @@ -0,0 +1,169 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Inventory Move Line Model + * + * @author Jorg Janke + * @version $Id: MMovementLine.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MMovementLine extends X_M_MovementLine +{ + /** + * Standard Cosntructor + * @param ctx context + * @param M_MovementLine_ID id + * @param trxName transaction + */ + public MMovementLine (Properties ctx, int M_MovementLine_ID, String trxName) + { + super (ctx, M_MovementLine_ID, trxName); + if (M_MovementLine_ID == 0) + { + // setM_LocatorTo_ID (0); // @M_LocatorTo_ID@ + // setM_Locator_ID (0); // @M_Locator_ID@ + // setM_MovementLine_ID (0); + // setLine (0); + // setM_Product_ID (0); + setM_AttributeSetInstance_ID(0); // ID + setMovementQty (Env.ZERO); // 1 + setTargetQty (Env.ZERO); // 0 + setScrappedQty(Env.ZERO); + setConfirmedQty(Env.ZERO); + setProcessed (false); + } + } // MMovementLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MMovementLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MMovementLine + + /** + * Parent constructor + * @param parent parent + */ + public MMovementLine (MMovement parent) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setM_Movement_ID(parent.getM_Movement_ID()); + } // MMovementLine + + /** + * Get AttributeSetInstance To + * @return ASI + */ + public int getM_AttributeSetInstanceTo_ID () + { + int M_AttributeSetInstanceTo_ID = super.getM_AttributeSetInstanceTo_ID(); + if (M_AttributeSetInstanceTo_ID == 0) + M_AttributeSetInstanceTo_ID = super.getM_AttributeSetInstance_ID(); + return M_AttributeSetInstanceTo_ID; + } // getM_AttributeSetInstanceTo_ID + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * Get Product + * @return product or null if not defined + */ + public MProduct getProduct() + { + if (getM_Product_ID() != 0) + return MProduct.get(getCtx(), getM_Product_ID()); + return null; + } // getProduct + + /** + * Set Movement Qty - enforce UOM + * @param MovementQty qty + */ + public void setMovementQty (BigDecimal MovementQty) + { + if (MovementQty != null) + { + MProduct product = getProduct(); + if (product != null) + { + int precision = product.getUOMPrecision(); + MovementQty = MovementQty.setScale(precision, BigDecimal.ROUND_HALF_UP); + } + } + super.setMovementQty(MovementQty); + } // setMovementQty + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Set Line No + if (getLine() == 0) + { + String sql = "SELECT COALESCE(MAX(Line),0)+10 AS DefaultValue FROM C_M_MovementLine WHERE M_Movement_ID=?"; + int ii = DB.getSQLValue (get_TrxName(), sql, getM_Movement_ID()); + setLine (ii); + } + + if (getM_Locator_ID() == getM_LocatorTo_ID()) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@M_Locator_ID@ == @M_LocatorTo_ID@")); + return false; + } + + if (getMovementQty().signum() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "MovementQty")); + return false; + } + + // Qty Precision + if (newRecord || is_ValueChanged("QtyEntered")) + setMovementQty(getMovementQty()); + + return true; + } // beforeSave + + +} // MMovementLine diff --git a/base/src/org/compiere/model/MMovementLineConfirm.java b/base/src/org/compiere/model/MMovementLineConfirm.java new file mode 100644 index 0000000000..b538c83434 --- /dev/null +++ b/base/src/org/compiere/model/MMovementLineConfirm.java @@ -0,0 +1,155 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Inventory Movement Confirmation Line + * + * @author Jorg Janke + * @version $Id: MMovementLineConfirm.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MMovementLineConfirm extends X_M_MovementLineConfirm +{ + + /** + * Standard Constructor + * @param ctx ctx + * @param M_MovementLineConfirm_ID id + * @param trxName transaction + */ + public MMovementLineConfirm (Properties ctx, int M_MovementLineConfirm_ID, String trxName) + { + super (ctx, M_MovementLineConfirm_ID, trxName); + if (M_MovementLineConfirm_ID == 0) + { + // setM_MovementConfirm_ID (0); Parent + // setM_MovementLine_ID (0); + setConfirmedQty (Env.ZERO); + setDifferenceQty (Env.ZERO); + setScrappedQty (Env.ZERO); + setTargetQty (Env.ZERO); + setProcessed (false); + } } // M_MovementLineConfirm + + /** + * M_MovementLineConfirm + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MMovementLineConfirm (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // M_MovementLineConfirm + + /** + * Parent Constructor + * @param parent parent + */ + public MMovementLineConfirm (MMovementConfirm parent) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setM_MovementConfirm_ID(parent.getM_MovementConfirm_ID()); + } // MMovementLineConfirm + + /** Movement Line */ + private MMovementLine m_line = null; + + /** + * Set Movement Line + * @param line line + */ + public void setMovementLine (MMovementLine line) + { + setM_MovementLine_ID(line.getM_MovementLine_ID()); + setTargetQty(line.getMovementQty()); + setConfirmedQty(getTargetQty()); // suggestion + m_line = line; + } // setMovementLine + + /** + * Get Movement Line + * @return line + */ + public MMovementLine getLine() + { + if (m_line == null) + m_line = new MMovementLine (getCtx(), getM_MovementLine_ID(), get_TrxName()); + return m_line; + } // getLine + + + /** + * Process Confirmation Line. + * - Update Movement Line + * @return success + */ + public boolean processLine () + { + MMovementLine line = getLine(); + + line.setTargetQty(getTargetQty()); + line.setMovementQty(getConfirmedQty()); + line.setConfirmedQty(getConfirmedQty()); + line.setScrappedQty(getScrappedQty()); + + return line.save(get_TrxName()); + } // processConfirmation + + /** + * Is Fully Confirmed + * @return true if Target = Confirmed qty + */ + public boolean isFullyConfirmed() + { + return getTargetQty().compareTo(getConfirmedQty()) == 0; + } // isFullyConfirmed + + + /** + * Before Delete - do not delete + * @return false + */ + protected boolean beforeDelete () + { + return false; + } // beforeDelete + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Calculate Difference = Target - Confirmed - Scrapped + BigDecimal difference = getTargetQty(); + difference = difference.subtract(getConfirmedQty()); + difference = difference.subtract(getScrappedQty()); + setDifferenceQty(difference); + // + return true; + } // beforeSave + + +} // M_MovementLineConfirm diff --git a/base/src/org/compiere/model/MMovementLineMA.java b/base/src/org/compiere/model/MMovementLineMA.java new file mode 100644 index 0000000000..be20737651 --- /dev/null +++ b/base/src/org/compiere/model/MMovementLineMA.java @@ -0,0 +1,152 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Movement Material Allocation + * + * @author Jorg Janke + * @version $Id: MMovementLineMA.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MMovementLineMA extends X_M_MovementLineMA +{ + /** + * Get Material Allocations for Line + * @param ctx context + * @param M_MovementLine_ID line + * @param trxName trx + * @return allocations + */ + public static MMovementLineMA[] get (Properties ctx, int M_MovementLine_ID, String trxName) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_MovementLineMA WHERE M_MovementLine_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_MovementLine_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + list.add (new MMovementLineMA (ctx, rs, trxName)); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + MMovementLineMA[] retValue = new MMovementLineMA[list.size ()]; + list.toArray (retValue); + return retValue; + } // get + + /** + * Delete all Material Allocation for Movement + * @param M_Movement_ID movement + * @param trxName transaction + * @return number of rows deleted or -1 for error + */ + public static int deleteMovementMA (int M_Movement_ID, String trxName) + { + String sql = "DELETE FROM M_MovementLineMA ma WHERE EXISTS " + + "(SELECT * FROM M_MovementLine l WHERE l.M_MovementLine_ID=ma.M_MovementLine_ID" + + " AND M_Movement_ID=" + M_Movement_ID + ")"; + return DB.executeUpdate(sql, trxName); + } // deleteInOutMA + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MMovementLineMA.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_MovementLineMA_ID ignored + * @param trxName trx + */ + public MMovementLineMA (Properties ctx, int M_MovementLineMA_ID, + String trxName) + { + super (ctx, M_MovementLineMA_ID, trxName); + if (M_MovementLineMA_ID != 0) + throw new IllegalArgumentException("Multi-Key"); + } // MMovementLineMA + + /** + * Load Constructor + * @param ctx context + * @param rs result ser + * @param trxName trx + */ + public MMovementLineMA (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MMovementLineMA + + /** + * Parent Constructor + * @param parent parent + * @param M_AttributeSetInstance_ID asi + * @param MovementQty qty + */ + public MMovementLineMA (MMovementLine parent, int M_AttributeSetInstance_ID, BigDecimal MovementQty) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setM_MovementLine_ID(parent.getM_MovementLine_ID()); + // + setM_AttributeSetInstance_ID(M_AttributeSetInstance_ID); + setMovementQty(MovementQty); + } // MMovementLineMA + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MMovementLineMA["); + sb.append("M_MovementLine_ID=").append(getM_MovementLine_ID()) + .append(",M_AttributeSetInstance_ID=").append(getM_AttributeSetInstance_ID()) + .append(", Qty=").append(getMovementQty()) + .append ("]"); + return sb.toString (); + } // toString + +} // MMovementLineMA diff --git a/base/src/org/compiere/model/MNewsChannel.java b/base/src/org/compiere/model/MNewsChannel.java new file mode 100644 index 0000000000..28948f8083 --- /dev/null +++ b/base/src/org/compiere/model/MNewsChannel.java @@ -0,0 +1,165 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * News Channel Model + * + * @author Yves Sandfort + * @version $Id$ + */ +public class MNewsChannel extends X_CM_NewsChannel +{ + /** + * Standard Constructor + * + * @param ctx context + * @param CM_NewsChannel_ID id + * @param trxName transaction + */ + public MNewsChannel (Properties ctx, int CM_NewsChannel_ID, String trxName) + { + super (ctx, CM_NewsChannel_ID, trxName); + } // MNewsChannel + + /** + * Load Constructor + * + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MNewsChannel (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MNewsChannel + + /** + * Get News Items + * @param where where clause + * @return array of news items + */ + public MNewsItem[] getNewsItems(String where) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM CM_NewsItem WHERE CM_NewsChannel_ID=? AND IsActive='Y'"; + if (where != null && where.length() > 0) + sql += " AND " + where; + sql += " ORDER BY pubDate DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, this.get_TrxName()); + pstmt.setInt (1, this.get_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MNewsItem(this.getCtx(), rs, this.get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MNewsItem[] retValue = new MNewsItem[list.size ()]; + list.toArray (retValue); + return retValue; + } // getNewsItems + + + + /** + * Get rss2 Channel Code + * @param xmlCode xml + * @param showFutureItems future + * @return channel code + */ + public StringBuffer get_rss2ChannelCode(StringBuffer xmlCode, boolean showFutureItems) + { + if (this != null) // never null ?? + { + xmlCode.append (""); + xmlCode.append (" <![CDATA[" + this.getName () + + "]]>"); + xmlCode.append (" " + this.getLink () + + ""); + xmlCode.append (" "); + xmlCode.append (" " + + this.getAD_Language () + ""); + xmlCode.append (" " + "" + ""); + xmlCode.append (" " + + this.getCreated () + ""); + xmlCode.append (" "); + xmlCode.append (" " + "" + ""); + xmlCode.append (" <![CDATA[" + "" + "]]>"); + xmlCode.append (" " + "" + ""); + xmlCode.append (" "); + + String whereClause = ""; + if (!showFutureItems) whereClause = "sysdate>pubdate"; + MNewsItem[] theseItems = getNewsItems(whereClause); + + for(int i=0;i"); + } + return xmlCode; + } + + + /** + * After Save. + * Insert + * - create / update index + * @param newRecord insert + * @param success save success + * @return true if saved + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + reIndex(newRecord); + return success; + } // afterSave + + + public void reIndex(boolean newRecord) + { + String [] toBeIndexed = new String[2]; + toBeIndexed[0] = this.getName(); + toBeIndexed[1] = this.getDescription(); + MIndex.reIndex (newRecord, toBeIndexed, getCtx(), getAD_Client_ID(), get_Table_ID(), get_ID(), getCM_WebProject_ID(), this.getUpdated()); + } +} // diff --git a/base/src/org/compiere/model/MNewsItem.java b/base/src/org/compiere/model/MNewsItem.java new file mode 100644 index 0000000000..8f7ea0e6d1 --- /dev/null +++ b/base/src/org/compiere/model/MNewsItem.java @@ -0,0 +1,137 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * News ItemModel + * + * @author Yves Sandfort + * @version $Id$ + */ +public class MNewsItem extends X_CM_NewsItem +{ + /*** + * Standard Constructor + * + * @param ctx context + * @param CM_NewsItem_ID id + * @param trxName transaction + */ + public MNewsItem (Properties ctx, int CM_NewsItem_ID, String trxName) + { + super (ctx, CM_NewsItem_ID, trxName); + } // MNewsItem + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MNewsItem (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MNewsItem + + /** + * getNewsChannel + * @return NewsChannel + */ + public MNewsChannel getNewsChannel() + { + int[] thisNewsChannel = MNewsChannel.getAllIDs("CM_NewsChannel","CM_NewsChannel_ID=" + this.getCM_NewsChannel_ID(), get_TrxName()); + if (thisNewsChannel!=null) + { + if (thisNewsChannel.length==1) + return new MNewsChannel(getCtx(), thisNewsChannel[0], get_TrxName()); + } + return null; + } // getNewsChannel + + /** + * Get rss2 Item Code + * @param xmlCode xml + * @param thisChannel channel + * @return rss item code + */ + public StringBuffer get_rss2ItemCode(StringBuffer xmlCode, MNewsChannel thisChannel) + { + if (this != null) // never null ?? + { + xmlCode.append (""); + xmlCode.append (""+ this.get_ID() + ""); + xmlCode.append (" <![CDATA[" + + this.getTitle () + "]]>"); + xmlCode.append (" "); + xmlCode.append (" "); + xmlCode.append (" " + + thisChannel.getLink () + + "?CM_NewsItem_ID=" + this.get_ID() + ""); + xmlCode.append (" "); + xmlCode.append (" " + + this.getPubDate () + ""); + xmlCode.append (""); + } + return xmlCode; + } + + /** + * After Save. + * Insert + * - create / update index + * @param newRecord insert + * @param success save success + * @return true if saved + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + if (!newRecord) + { + MIndex.cleanUp(get_TrxName(), getAD_Client_ID(), get_Table_ID(), get_ID()); + } + reIndex(newRecord); + return success; + } // afterSave + + /** + * reIndex + * @param newRecord + * @throws SQLException + */ + public void reIndex(boolean newRecord) + { + int CMWebProjectID = 0; + if (getNewsChannel()!=null) + CMWebProjectID = getNewsChannel().getCM_WebProject_ID(); + String [] toBeIndexed = new String[4]; + toBeIndexed[0] = this.getAuthor(); + toBeIndexed[1] = this.getDescription(); + toBeIndexed[2] = this.getTitle(); + toBeIndexed[3] = this.getContentHTML(); + MIndex.reIndex (newRecord, toBeIndexed, getCtx(), getAD_Client_ID(), get_Table_ID(), get_ID(), CMWebProjectID, this.getUpdated()); + } // reIndex +} diff --git a/base/src/org/compiere/model/MOrder.java b/base/src/org/compiere/model/MOrder.java new file mode 100644 index 0000000000..713fc84fb2 --- /dev/null +++ b/base/src/org/compiere/model/MOrder.java @@ -0,0 +1,2203 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.print.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Order Model. + * Please do not set DocStatus and C_DocType_ID directly. + * They are set in the process() method. + * Use DocAction and C_DocTypeTarget_ID instead. + * + * @author Jorg Janke + * @version $Id: MOrder.java,v 1.5 2006/10/06 00:42:24 jjanke Exp $ + */ +public class MOrder extends X_C_Order implements DocAction +{ + /** + * Create new Order by copying + * @param from order + * @param dateDoc date of the document date + * @param C_DocTypeTarget_ID target document type + * @param isSOTrx sales order + * @param counter create counter links + * @param copyASI copy line attributes Attribute Set Instance, Resaouce Assignment + * @param trxName trx + * @return Order + */ + public static MOrder copyFrom (MOrder from, Timestamp dateDoc, + int C_DocTypeTarget_ID, boolean isSOTrx, boolean counter, boolean copyASI, + String trxName) + { + MOrder to = new MOrder (from.getCtx(), 0, trxName); + to.set_TrxName(trxName); + PO.copyValues(from, to, from.getAD_Client_ID(), from.getAD_Org_ID()); + to.set_ValueNoCheck ("C_Order_ID", I_ZERO); + to.set_ValueNoCheck ("DocumentNo", null); + // + to.setDocStatus (DOCSTATUS_Drafted); // Draft + to.setDocAction(DOCACTION_Complete); + // + to.setC_DocType_ID(0); + to.setC_DocTypeTarget_ID (C_DocTypeTarget_ID); + to.setIsSOTrx(isSOTrx); + // + to.setIsSelected (false); + to.setDateOrdered (dateDoc); + to.setDateAcct (dateDoc); + to.setDatePromised (dateDoc); // assumption + to.setDatePrinted(null); + to.setIsPrinted (false); + // + to.setIsApproved (false); + to.setIsCreditApproved(false); + to.setC_Payment_ID(0); + to.setC_CashLine_ID(0); + // Amounts are updated when adding lines + to.setGrandTotal(Env.ZERO); + to.setTotalLines(Env.ZERO); + // + to.setIsDelivered(false); + to.setIsInvoiced(false); + to.setIsSelfService(false); + to.setIsTransferred (false); + to.setPosted (false); + to.setProcessed (false); + if (counter) + to.setRef_Order_ID(from.getC_Order_ID()); + else + to.setRef_Order_ID(0); + // + if (!to.save(trxName)) + throw new IllegalStateException("Could not create Order"); + if (counter) + from.setRef_Order_ID(to.getC_Order_ID()); + + if (to.copyLinesFrom(from, counter, copyASI) == 0) + throw new IllegalStateException("Could not create Order Lines"); + + return to; + } // copyFrom + + + /************************************************************************** + * Default Constructor + * @param ctx context + * @param C_Order_ID order to load, (0 create new order) + * @param trxName trx name + */ + public MOrder(Properties ctx, int C_Order_ID, String trxName) + { + super (ctx, C_Order_ID, trxName); + // New + if (C_Order_ID == 0) + { + setDocStatus(DOCSTATUS_Drafted); + setDocAction (DOCACTION_Prepare); + // + setDeliveryRule (DELIVERYRULE_Availability); + setFreightCostRule (FREIGHTCOSTRULE_FreightIncluded); + setInvoiceRule (INVOICERULE_Immediate); + setPaymentRule(PAYMENTRULE_OnCredit); + setPriorityRule (PRIORITYRULE_Medium); + setDeliveryViaRule (DELIVERYVIARULE_Pickup); + // + setIsDiscountPrinted (false); + setIsSelected (false); + setIsTaxIncluded (false); + setIsSOTrx (true); + setIsDropShip(false); + setSendEMail (false); + // + setIsApproved(false); + setIsPrinted(false); + setIsCreditApproved(false); + setIsDelivered(false); + setIsInvoiced(false); + setIsTransferred(false); + setIsSelfService(false); + // + super.setProcessed(false); + setProcessing(false); + setPosted(false); + + setDateAcct (new Timestamp(System.currentTimeMillis())); + setDatePromised (new Timestamp(System.currentTimeMillis())); + setDateOrdered (new Timestamp(System.currentTimeMillis())); + + setFreightAmt (Env.ZERO); + setChargeAmt (Env.ZERO); + setTotalLines (Env.ZERO); + setGrandTotal (Env.ZERO); + } + } // MOrder + + /************************************************************************** + * Project Constructor + * @param project Project to create Order from + * @param IsSOTrx sales order + * @param DocSubTypeSO if SO DocType Target (default DocSubTypeSO_OnCredit) + */ + public MOrder (MProject project, boolean IsSOTrx, String DocSubTypeSO) + { + this (project.getCtx(), 0, project.get_TrxName()); + setAD_Client_ID(project.getAD_Client_ID()); + setAD_Org_ID(project.getAD_Org_ID()); + setC_Campaign_ID(project.getC_Campaign_ID()); + setSalesRep_ID(project.getSalesRep_ID()); + // + setC_Project_ID(project.getC_Project_ID()); + setDescription(project.getName()); + Timestamp ts = project.getDateContract(); + if (ts != null) + setDateOrdered (ts); + ts = project.getDateFinish(); + if (ts != null) + setDatePromised (ts); + // + setC_BPartner_ID(project.getC_BPartner_ID()); + setC_BPartner_Location_ID(project.getC_BPartner_Location_ID()); + setAD_User_ID(project.getAD_User_ID()); + // + setM_Warehouse_ID(project.getM_Warehouse_ID()); + setM_PriceList_ID(project.getM_PriceList_ID()); + setC_PaymentTerm_ID(project.getC_PaymentTerm_ID()); + // + setIsSOTrx(IsSOTrx); + if (IsSOTrx) + { + if (DocSubTypeSO == null || DocSubTypeSO.length() == 0) + setC_DocTypeTarget_ID(DocSubTypeSO_OnCredit); + else + setC_DocTypeTarget_ID(DocSubTypeSO); + } + else + setC_DocTypeTarget_ID(); + } // MOrder + + /** + * Load Constructor + * @param ctx context + * @param rs result set record + * @param trxName transaction + */ + public MOrder (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MOrder + + /** Order Lines */ + private MOrderLine[] m_lines = null; + /** Tax Lines */ + private MOrderTax[] m_taxes = null; + /** Force Creation of order */ + private boolean m_forceCreation = false; + + /** + * Overwrite Client/Org if required + * @param AD_Client_ID client + * @param AD_Org_ID org + */ + public void setClientOrg (int AD_Client_ID, int AD_Org_ID) + { + super.setClientOrg(AD_Client_ID, AD_Org_ID); + } // setClientOrg + + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * Set Business Partner (Ship+Bill) + * @param C_BPartner_ID bpartner + */ + public void setC_BPartner_ID (int C_BPartner_ID) + { + super.setC_BPartner_ID (C_BPartner_ID); + super.setBill_BPartner_ID (C_BPartner_ID); + } // setC_BPartner_ID + + /** + * Set Business Partner Location (Ship+Bill) + * @param C_BPartner_Location_ID bp location + */ + public void setC_BPartner_Location_ID (int C_BPartner_Location_ID) + { + super.setC_BPartner_Location_ID (C_BPartner_Location_ID); + super.setBill_Location_ID(C_BPartner_Location_ID); + } // setC_BPartner_Location_ID + + /** + * Set Business Partner Contact (Ship+Bill) + * @param AD_User_ID user + */ + public void setAD_User_ID (int AD_User_ID) + { + super.setAD_User_ID (AD_User_ID); + super.setBill_User_ID (AD_User_ID); + } // setAD_User_ID + + /** + * Set Ship Business Partner + * @param C_BPartner_ID bpartner + */ + public void setShip_BPartner_ID (int C_BPartner_ID) + { + super.setC_BPartner_ID (C_BPartner_ID); + } // setShip_BPartner_ID + + /** + * Set Ship Business Partner Location + * @param C_BPartner_Location_ID bp location + */ + public void setShip_Location_ID (int C_BPartner_Location_ID) + { + super.setC_BPartner_Location_ID (C_BPartner_Location_ID); + } // setShip_Location_ID + + /** + * Set Ship Business Partner Contact + * @param AD_User_ID user + */ + public void setShip_User_ID (int AD_User_ID) + { + super.setAD_User_ID (AD_User_ID); + } // setShip_User_ID + + + /** + * Set Warehouse + * @param M_Warehouse_ID warehouse + */ + public void setM_Warehouse_ID (int M_Warehouse_ID) + { + super.setM_Warehouse_ID (M_Warehouse_ID); + } // setM_Warehouse_ID + + /** + * Set Drop Ship + * @param IsDropShip drop ship + */ + public void setIsDropShip (boolean IsDropShip) + { + super.setIsDropShip (IsDropShip); + } // setIsDropShip + + /*************************************************************************/ + + /** Sales Order Sub Type - SO */ + public static final String DocSubTypeSO_Standard = "SO"; + /** Sales Order Sub Type - OB */ + public static final String DocSubTypeSO_Quotation = "OB"; + /** Sales Order Sub Type - ON */ + public static final String DocSubTypeSO_Proposal = "ON"; + /** Sales Order Sub Type - PR */ + public static final String DocSubTypeSO_Prepay = "PR"; + /** Sales Order Sub Type - WR */ + public static final String DocSubTypeSO_POS = "WR"; + /** Sales Order Sub Type - WP */ + public static final String DocSubTypeSO_Warehouse = "WP"; + /** Sales Order Sub Type - WI */ + public static final String DocSubTypeSO_OnCredit = "WI"; + /** Sales Order Sub Type - RM */ + public static final String DocSubTypeSO_RMA = "RM"; + + /** + * Set Target Sales Document Type + * @param DocSubTypeSO_x SO sub type - see DocSubTypeSO_* + */ + public void setC_DocTypeTarget_ID (String DocSubTypeSO_x) + { + String sql = "SELECT C_DocType_ID FROM C_DocType " + + "WHERE AD_Client_ID=? AND AD_Org_ID IN (0," + getAD_Org_ID() + + ") AND DocSubTypeSO=? " + + "ORDER BY AD_Org_ID DESC, IsDefault DESC"; + int C_DocType_ID = DB.getSQLValue(null, sql, getAD_Client_ID(), DocSubTypeSO_x); + if (C_DocType_ID <= 0) + log.severe ("Not found for AD_Client_ID=" + getAD_Client_ID () + ", SubType=" + DocSubTypeSO_x); + else + { + log.fine("(SO) - " + DocSubTypeSO_x); + setC_DocTypeTarget_ID (C_DocType_ID); + setIsSOTrx(true); + } + } // setC_DocTypeTarget_ID + + /** + * Set Target Document Type. + * Standard Order or PO + */ + public void setC_DocTypeTarget_ID () + { + if (isSOTrx()) // SO = Std Order + { + setC_DocTypeTarget_ID(DocSubTypeSO_Standard); + return; + } + // PO + String sql = "SELECT C_DocType_ID FROM C_DocType " + + "WHERE AD_Client_ID=? AND AD_Org_ID IN (0," + getAD_Org_ID() + + ") AND DocBaseType='POO' " + + "ORDER BY AD_Org_ID DESC, IsDefault DESC"; + int C_DocType_ID = DB.getSQLValue(null, sql, getAD_Client_ID()); + if (C_DocType_ID <= 0) + log.severe ("No POO found for AD_Client_ID=" + getAD_Client_ID ()); + else + { + log.fine("(PO) - " + C_DocType_ID); + setC_DocTypeTarget_ID (C_DocType_ID); + } + } // setC_DocTypeTarget_ID + + + /** + * Set Business Partner Defaults & Details. + * SOTrx should be set. + * @param bp business partner + */ + public void setBPartner (MBPartner bp) + { + if (bp == null) + return; + + setC_BPartner_ID(bp.getC_BPartner_ID()); + // Defaults Payment Term + int ii = 0; + if (isSOTrx()) + ii = bp.getC_PaymentTerm_ID(); + else + ii = bp.getPO_PaymentTerm_ID(); + if (ii != 0) + setC_PaymentTerm_ID(ii); + // Default Price List + if (isSOTrx()) + ii = bp.getM_PriceList_ID(); + else + ii = bp.getPO_PriceList_ID(); + if (ii != 0) + setM_PriceList_ID(ii); + // Default Delivery/Via Rule + String ss = bp.getDeliveryRule(); + if (ss != null) + setDeliveryRule(ss); + ss = bp.getDeliveryViaRule(); + if (ss != null) + setDeliveryViaRule(ss); + // Default Invoice/Payment Rule + ss = bp.getInvoiceRule(); + if (ss != null) + setInvoiceRule(ss); + ss = bp.getPaymentRule(); + if (ss != null) + setPaymentRule(ss); + // Sales Rep + ii = bp.getSalesRep_ID(); + if (ii != 0) + setSalesRep_ID(ii); + + + // Set Locations + MBPartnerLocation[] locs = bp.getLocations(false); + if (locs != null) + { + for (int i = 0; i < locs.length; i++) + { + if (locs[i].isShipTo()) + super.setC_BPartner_Location_ID(locs[i].getC_BPartner_Location_ID()); + if (locs[i].isBillTo()) + setBill_Location_ID(locs[i].getC_BPartner_Location_ID()); + } + // set to first + if (getC_BPartner_Location_ID() == 0 && locs.length > 0) + super.setC_BPartner_Location_ID(locs[0].getC_BPartner_Location_ID()); + if (getBill_Location_ID() == 0 && locs.length > 0) + setBill_Location_ID(locs[0].getC_BPartner_Location_ID()); + } + if (getC_BPartner_Location_ID() == 0) + log.log(Level.SEVERE, "MOrder.setBPartner - Has no Ship To Address: " + bp); + if (getBill_Location_ID() == 0) + log.log(Level.SEVERE, "MOrder.setBPartner - Has no Bill To Address: " + bp); + + // Set Contact + MUser[] contacts = bp.getContacts(false); + if (contacts != null && contacts.length == 1) + setAD_User_ID(contacts[0].getAD_User_ID()); + } // setBPartner + + + /** + * Copy Lines From other Order + * @param otherOrder order + * @param counter set counter info + * @param copyASI copy line attributes Attribute Set Instance, Resaouce Assignment + * @return number of lines copied + */ + public int copyLinesFrom (MOrder otherOrder, boolean counter, boolean copyASI) + { + if (isProcessed() || isPosted() || otherOrder == null) + return 0; + MOrderLine[] fromLines = otherOrder.getLines(false, null); + int count = 0; + for (int i = 0; i < fromLines.length; i++) + { + MOrderLine line = new MOrderLine (this); + PO.copyValues(fromLines[i], line, getAD_Client_ID(), getAD_Org_ID()); + line.setC_Order_ID(getC_Order_ID()); + line.setOrder(this); + line.set_ValueNoCheck ("C_OrderLine_ID", I_ZERO); // new + // References + if (!copyASI) + { + line.setM_AttributeSetInstance_ID(0); + line.setS_ResourceAssignment_ID(0); + } + if (counter) + line.setRef_OrderLine_ID(fromLines[i].getC_OrderLine_ID()); + else + line.setRef_OrderLine_ID(0); + // + line.setQtyDelivered(Env.ZERO); + line.setQtyInvoiced(Env.ZERO); + line.setQtyReserved(Env.ZERO); + line.setDateDelivered(null); + line.setDateInvoiced(null); + // Tax + if (getC_BPartner_ID() != otherOrder.getC_BPartner_ID()) + line.setTax(); // recalculate + // + // + line.setProcessed(false); + if (line.save(get_TrxName())) + count++; + // Cross Link + if (counter) + { + fromLines[i].setRef_OrderLine_ID(line.getC_OrderLine_ID()); + fromLines[i].save(get_TrxName()); + } + } + if (fromLines.length != count) + log.log(Level.SEVERE, "Line difference - From=" + fromLines.length + " <> Saved=" + count); + return count; + } // copyLinesFrom + + + /************************************************************************** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MOrder[") + .append(get_ID()).append("-").append(getDocumentNo()) + .append(",IsSOTrx=").append(isSOTrx()) + .append(",C_DocType_ID=").append(getC_DocType_ID()) + .append(", GrandTotal=").append(getGrandTotal()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Get Document Info + * @return document info (untranslated) + */ + public String getDocumentInfo() + { + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + return dt.getName() + " " + getDocumentNo(); + } // getDocumentInfo + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.ORDER, getC_Invoice_ID()); + if (re == null) + return null; + return re.getPDF(file); + } // createPDF + + /** + * Set Price List (and Currency, TaxIncluded) when valid + * @param M_PriceList_ID price list + */ + public void setM_PriceList_ID (int M_PriceList_ID) + { + MPriceList pl = MPriceList.get(getCtx(), M_PriceList_ID, null); + if (pl.get_ID() == M_PriceList_ID) + { + super.setM_PriceList_ID(M_PriceList_ID); + setC_Currency_ID(pl.getC_Currency_ID()); + setIsTaxIncluded(pl.isTaxIncluded()); + } + } // setM_PriceList_ID + + + /************************************************************************** + * Get Lines of Order + * @param whereClause where clause or null (starting with AND) + * @param orderClause order clause + * @return lines + */ + public MOrderLine[] getLines (String whereClause, String orderClause) + { + ArrayList list = new ArrayList (); + StringBuffer sql = new StringBuffer("SELECT * FROM C_OrderLine WHERE C_Order_ID=? "); + if (whereClause != null) + sql.append(whereClause); + if (orderClause != null) + sql.append(" ").append(orderClause); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql.toString(), get_TrxName()); + pstmt.setInt(1, getC_Order_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + MOrderLine ol = new MOrderLine(getCtx(), rs, get_TrxName()); + ol.setHeaderInfo (this); + list.add(ol); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + // + MOrderLine[] lines = new MOrderLine[list.size ()]; + list.toArray (lines); + return lines; + } // getLines + + /** + * Get Lines of Order + * @param requery requery + * @param orderBy optional order by column + * @return lines + */ + public MOrderLine[] getLines (boolean requery, String orderBy) + { + if (m_lines != null && !requery) + return m_lines; + // + String orderClause = "ORDER BY "; + if (orderBy != null && orderBy.length() > 0) + orderClause += orderBy; + else + orderClause += "Line"; + m_lines = getLines(null, orderClause); + return m_lines; + } // getLines + + /** + * Get Lines of Order. + * (useb by web store) + * @return lines + */ + public MOrderLine[] getLines() + { + return getLines(false, null); + } // getLines + + /** + * Renumber Lines + * @param step start and step + */ + public void renumberLines (int step) + { + int number = step; + MOrderLine[] lines = getLines(true, null); // Line is default + for (int i = 0; i < lines.length; i++) + { + MOrderLine line = lines[i]; + line.setLine(number); + line.save(get_TrxName()); + number += step; + } + m_lines = null; + } // renumberLines + + /** + * Does the Order Line belong to this Order + * @param C_OrderLine_ID line + * @return true if part of the order + */ + public boolean isOrderLine(int C_OrderLine_ID) + { + if (m_lines == null) + getLines(); + for (int i = 0; i < m_lines.length; i++) + if (m_lines[i].getC_OrderLine_ID() == C_OrderLine_ID) + return true; + return false; + } // isOrderLine + + /** + * Get Taxes of Order + * @param requery requery + * @return array of taxes + */ + public MOrderTax[] getTaxes(boolean requery) + { + if (m_taxes != null && !requery) + return m_taxes; + // + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_OrderTax WHERE C_Order_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_Order_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MOrderTax(getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getTaxes", e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + // + m_taxes = new MOrderTax[list.size ()]; + list.toArray (m_taxes); + return m_taxes; + } // getTaxes + + + /** + * Get Invoices of Order + * @return invoices + */ + public MInvoice[] getInvoices() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_Invoice WHERE C_Order_ID=? ORDER BY Created DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_Order_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MInvoice(getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + // + MInvoice[] retValue = new MInvoice[list.size()]; + list.toArray(retValue); + return retValue; + } // getInvoices + + /** + * Get latest Invoice of Order + * @return invoice id or 0 + */ + public int getC_Invoice_ID() + { + int C_Invoice_ID = 0; + ArrayList list = new ArrayList(); + String sql = "SELECT C_Invoice_ID FROM C_Invoice " + + "WHERE C_Order_ID=? AND DocStatus IN ('CO','CL') " + + "ORDER BY Created DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_Order_ID()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + C_Invoice_ID = rs.getInt(1); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getC_Invoice_ID", e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + return C_Invoice_ID; + } // getC_Invoice_ID + + + /** + * Get Shipments of Order + * @return shipments + */ + public MInOut[] getShipments() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_InOut WHERE C_Order_ID=? ORDER BY Created DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_Order_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MInOut(getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + // + MInOut[] retValue = new MInOut[list.size()]; + list.toArray(retValue); + return retValue; + } // getShipments + + /** + * Get ISO Code of Currency + * @return Currency ISO + */ + public String getCurrencyISO() + { + return MCurrency.getISO_Code (getCtx(), getC_Currency_ID()); + } // getCurrencyISO + + /** + * Get Currency Precision + * @return precision + */ + public int getPrecision() + { + return MCurrency.getStdPrecision(getCtx(), getC_Currency_ID()); + } // getPrecision + + /** + * Get Document Status + * @return Document Status Clear Text + */ + public String getDocStatusName() + { + return MRefList.getListName(getCtx(), 131, getDocStatus()); + } // getDocStatusName + + /** + * Set DocAction + * @param DocAction doc action + */ + public void setDocAction (String DocAction) + { + setDocAction (DocAction, false); + } // setDocAction + + /** + * Set DocAction + * @param DocAction doc oction + * @param forceCreation force creation + */ + public void setDocAction (String DocAction, boolean forceCreation) + { + super.setDocAction (DocAction); + m_forceCreation = forceCreation; + } // setDocAction + + /** + * Set Processed. + * Propergate to Lines/Taxes + * @param processed processed + */ + public void setProcessed (boolean processed) + { + super.setProcessed (processed); + if (get_ID() == 0) + return; + String set = "SET Processed='" + + (processed ? "Y" : "N") + + "' WHERE C_Order_ID=" + getC_Order_ID(); + int noLine = DB.executeUpdate("UPDATE C_OrderLine " + set, get_TrxName()); + int noTax = DB.executeUpdate("UPDATE C_OrderTax " + set, get_TrxName()); + m_lines = null; + m_taxes = null; + log.fine("setProcessed - " + processed + " - Lines=" + noLine + ", Tax=" + noTax); + } // setProcessed + + + + /************************************************************************** + * Before Save + * @param newRecord new + * @return save + */ + protected boolean beforeSave (boolean newRecord) + { + // Client/Org Check + if (getAD_Org_ID() == 0) + { + int context_AD_Org_ID = Env.getAD_Org_ID(getCtx()); + if (context_AD_Org_ID != 0) + { + setAD_Org_ID(context_AD_Org_ID); + log.warning("Changed Org to Context=" + context_AD_Org_ID); + } + } + if (getAD_Client_ID() == 0) + { + m_processMsg = "AD_Client_ID = 0"; + return false; + } + + // New Record Doc Type - make sure DocType set to 0 + if (newRecord && getC_DocType_ID() == 0) + setC_DocType_ID (0); + + // Default Warehouse + if (getM_Warehouse_ID() == 0) + { + int ii = Env.getContextAsInt(getCtx(), "#M_Warehouse_ID"); + if (ii != 0) + setM_Warehouse_ID(ii); + else + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "M_Warehouse_ID")); + return false; + } + } + // Warehouse Org + if (newRecord + || is_ValueChanged("AD_Org_ID") || is_ValueChanged("M_Warehouse_ID")) + { + MWarehouse wh = MWarehouse.get(getCtx(), getM_Warehouse_ID()); + if (wh.getAD_Org_ID() != getAD_Org_ID()) + log.saveWarning("WarehouseOrgConflict", ""); + } + // Reservations in Warehouse + if (!newRecord && is_ValueChanged("M_Warehouse_ID")) + { + MOrderLine[] lines = getLines(false,null); + for (int i = 0; i < lines.length; i++) + { + if (!lines[i].canChangeWarehouse()) + return false; + } + } + + // No Partner Info - set Template + if (getC_BPartner_ID() == 0) + setBPartner(MBPartner.getTemplate(getCtx(), getAD_Client_ID())); + if (getC_BPartner_Location_ID() == 0) + setBPartner(new MBPartner(getCtx(), getC_BPartner_ID(), null)); + // No Bill - get from Ship + if (getBill_BPartner_ID() == 0) + { + setBill_BPartner_ID(getC_BPartner_ID()); + setBill_Location_ID(getC_BPartner_Location_ID()); + } + if (getBill_Location_ID() == 0) + setBill_Location_ID(getC_BPartner_Location_ID()); + + // Default Price List + if (getM_PriceList_ID() == 0) + { + int ii = DB.getSQLValue(null, + "SELECT M_PriceList_ID FROM M_PriceList " + + "WHERE AD_Client_ID=? AND IsSOPriceList=? " + + "ORDER BY IsDefault DESC", getAD_Client_ID(), isSOTrx() ? "Y" : "N"); + if (ii != 0) + setM_PriceList_ID (ii); + } + // Default Currency + if (getC_Currency_ID() == 0) + { + String sql = "SELECT C_Currency_ID FROM M_PriceList WHERE M_PriceList_ID=?"; + int ii = DB.getSQLValue (null, sql, getM_PriceList_ID()); + if (ii != 0) + setC_Currency_ID (ii); + else + setC_Currency_ID(Env.getContextAsInt(getCtx(), "#C_Currency_ID")); + } + + // Default Sales Rep + if (getSalesRep_ID() == 0) + { + int ii = Env.getContextAsInt(getCtx(), "#SalesRep_ID"); + if (ii != 0) + setSalesRep_ID (ii); + } + + // Default Document Type + if (getC_DocTypeTarget_ID() == 0) + setC_DocTypeTarget_ID(DocSubTypeSO_Standard); + + // Default Payment Term + if (getC_PaymentTerm_ID() == 0) + { + int ii = Env.getContextAsInt(getCtx(), "#C_PaymentTerm_ID"); + if (ii != 0) + setC_PaymentTerm_ID(ii); + else + { + String sql = "SELECT C_PaymentTerm_ID FROM C_PaymentTerm WHERE AD_Client_ID=? AND IsDefault='Y'"; + ii = DB.getSQLValue(null, sql, getAD_Client_ID()); + if (ii != 0) + setC_PaymentTerm_ID (ii); + } + } + + return true; + } // beforeSave + + + /** + * After Save + * @param newRecord new + * @param success success + * @return true if can be saved + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success || newRecord) + return success; + + // Propagate Description changes + if (is_ValueChanged("Description") || is_ValueChanged("POReference")) + { + String sql = "UPDATE C_Invoice i" + + " SET (Description,POReference)=" + + "(SELECT Description,POReference " + + "FROM C_Order o WHERE i.C_Order_ID=o.C_Order_ID) " + + "WHERE DocStatus NOT IN ('RE','CL') AND C_Order_ID=" + getC_Order_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + log.fine("Description -> #" + no); + } + + // Propagate Changes of Payment Info to existing (not reversed/closed) invoices + if (is_ValueChanged("PaymentRule") || is_ValueChanged("C_PaymentTerm_ID") + || is_ValueChanged("DateAcct") || is_ValueChanged("C_Payment_ID") + || is_ValueChanged("C_CashLine_ID")) + { + String sql = "UPDATE C_Invoice i " + + "SET (PaymentRule,C_PaymentTerm_ID,DateAcct,C_Payment_ID,C_CashLine_ID)=" + + "(SELECT PaymentRule,C_PaymentTerm_ID,DateAcct,C_Payment_ID,C_CashLine_ID " + + "FROM C_Order o WHERE i.C_Order_ID=o.C_Order_ID)" + + "WHERE DocStatus NOT IN ('RE','CL') AND C_Order_ID=" + getC_Order_ID(); + // Don't touch Closed/Reversed entries + int no = DB.executeUpdate(sql, get_TrxName()); + log.fine("Payment -> #" + no); + } + + // Sync Lines + afterSaveSync("AD_Org_ID"); + afterSaveSync("C_BPartner_ID"); + afterSaveSync("C_BPartner_Location_ID"); + afterSaveSync("DateOrdered"); + afterSaveSync("DatePromised"); + afterSaveSync("M_Warehouse_ID"); + afterSaveSync("M_Shipper_ID"); + afterSaveSync("C_Currency_ID"); + // + return true; + } // afterSave + + private void afterSaveSync (String columnName) + { + if (is_ValueChanged(columnName)) + { + String sql = "UPDATE C_OrderLine ol" + + " SET " + columnName + " =" + + "(SELECT " + columnName + + " FROM C_Order o WHERE ol.C_Order_ID=o.C_Order_ID) " + + "WHERE C_Order_ID=" + getC_Order_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + log.fine(columnName + " Lines -> #" + no); + } + } // afterSaveSync + + /** + * Before Delete + * @return true of it can be deleted + */ + protected boolean beforeDelete () + { + if (isProcessed()) + return false; + + getLines(); + for (int i = 0; i < m_lines.length; i++) + { + if (!m_lines[i].beforeDelete()) + return false; + } + return true; + } // beforeDelete + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // processIt + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info("unlockIt - " + toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info(toString()); + setDocAction(DOCACTION_Prepare); + return true; + } // invalidateIt + + + /************************************************************************** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + MDocType dt = MDocType.get(getCtx(), getC_DocTypeTarget_ID()); + + // Std Period open? + if (!MPeriod.isOpen(getCtx(), getDateAcct(), dt.getDocBaseType())) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + + // Lines + MOrderLine[] lines = getLines(true, "M_Product_ID"); + if (lines.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + + // Bug 1564431 + if (getDeliveryRule() != null && getDeliveryRule().equals(MOrder.DELIVERYRULE_CompleteOrder)) + { + for (int i = 0; i < lines.length; i++) + { + MOrderLine line = lines[i]; + MProduct product = line.getProduct(); + if (product != null && product.isExcludeAutoDelivery()) + { + m_processMsg = "@M_Product_ID@ "+product.getValue()+" @IsExcludeAutoDelivery@"; + return DocAction.STATUS_Invalid; + } + } + } + + // Convert DocType to Target + if (getC_DocType_ID() != getC_DocTypeTarget_ID() ) + { + // Cannot change Std to anything else if different warehouses + if (getC_DocType_ID() != 0) + { + MDocType dtOld = MDocType.get(getCtx(), getC_DocType_ID()); + if (MDocType.DOCSUBTYPESO_StandardOrder.equals(dtOld.getDocSubTypeSO()) // From SO + && !MDocType.DOCSUBTYPESO_StandardOrder.equals(dt.getDocSubTypeSO())) // To !SO + { + for (int i = 0; i < lines.length; i++) + { + if (lines[i].getM_Warehouse_ID() != getM_Warehouse_ID()) + { + log.warning("different Warehouse " + lines[i]); + m_processMsg = "@CannotChangeDocType@"; + return DocAction.STATUS_Invalid; + } + } + } + } + + // New or in Progress/Invalid + if (DOCSTATUS_Drafted.equals(getDocStatus()) + || DOCSTATUS_InProgress.equals(getDocStatus()) + || DOCSTATUS_Invalid.equals(getDocStatus()) + || getC_DocType_ID() == 0) + { + setC_DocType_ID(getC_DocTypeTarget_ID()); + } + else // convert only if offer + { + if (dt.isOffer()) + setC_DocType_ID(getC_DocTypeTarget_ID()); + else + { + m_processMsg = "@CannotChangeDocType@"; + return DocAction.STATUS_Invalid; + } + } + } // convert DocType + + // Mandatory Product Attribute Set Instance + String mandatoryType = "='Y'"; // IN ('Y','S') + String sql = "SELECT COUNT(*) " + + "FROM C_OrderLine ol" + + " INNER JOIN M_Product p ON (ol.M_Product_ID=p.M_Product_ID)" + + " INNER JOIN M_AttributeSet pas ON (p.M_AttributeSet_ID=pas.M_AttributeSet_ID) " + + "WHERE pas.MandatoryType" + mandatoryType + + " AND ol.M_AttributeSetInstance_ID IS NULL" + + " AND ol.C_Order_ID=?"; + int no = DB.getSQLValue(get_TrxName(), sql, getC_Order_ID()); + if (no != 0) + { + m_processMsg = "@LinesWithoutProductAttribute@ (" + no + ")"; + return DocAction.STATUS_Invalid; + } + + // Lines + if (explodeBOM()) + lines = getLines(true, "M_Product_ID"); + if (!reserveStock(dt, lines)) + { + m_processMsg = "Cannot reserve Stock"; + return DocAction.STATUS_Invalid; + } + if (!calculateTaxTotal()) + { + m_processMsg = "Error calculating tax"; + return DocAction.STATUS_Invalid; + } + + // Credit Check + if (isSOTrx()) + { + MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), null); + if (MBPartner.SOCREDITSTATUS_CreditStop.equals(bp.getSOCreditStatus())) + { + m_processMsg = "@BPartnerCreditStop@ - @TotalOpenBalance@=" + + bp.getTotalOpenBalance() + + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); + return DocAction.STATUS_Invalid; + } + if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus())) + { + m_processMsg = "@BPartnerCreditHold@ - @TotalOpenBalance@=" + + bp.getTotalOpenBalance() + + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); + return DocAction.STATUS_Invalid; + } + BigDecimal grandTotal = MConversionRate.convertBase(getCtx(), + getGrandTotal(), getC_Currency_ID(), getDateOrdered(), + getC_ConversionType_ID(), getAD_Client_ID(), getAD_Org_ID()); + if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus(grandTotal))) + { + m_processMsg = "@BPartnerOverOCreditHold@ - @TotalOpenBalance@=" + + bp.getTotalOpenBalance() + ", @GrandTotal@=" + grandTotal + + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); + return DocAction.STATUS_Invalid; + } + } + + m_justPrepared = true; + // if (!DOCACTION_Complete.equals(getDocAction())) don't set for just prepare + // setDocAction(DOCACTION_Complete); + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Explode non stocked BOM. + * @return true if bom exploded + */ + private boolean explodeBOM() + { + boolean retValue = false; + String where = "AND IsActive='Y' AND EXISTS " + + "(SELECT * FROM M_Product p WHERE C_OrderLine.M_Product_ID=p.M_Product_ID" + + " AND p.IsBOM='Y' AND p.IsVerified='Y' AND p.IsStocked='N')"; + // + String sql = "SELECT COUNT(*) FROM C_OrderLine " + + "WHERE C_Order_ID=? " + where; + int count = DB.getSQLValue(get_TrxName(), sql, getC_Order_ID()); + while (count != 0) + { + retValue = true; + renumberLines (1000); // max 999 bom items + + // Order Lines with non-stocked BOMs + MOrderLine[] lines = getLines (where, "ORDER BY Line"); + for (int i = 0; i < lines.length; i++) + { + MOrderLine line = lines[i]; + MProduct product = MProduct.get (getCtx(), line.getM_Product_ID()); + log.fine(product.getName()); + // New Lines + int lineNo = line.getLine (); + MProductBOM[] boms = MProductBOM.getBOMLines (product); + for (int j = 0; j < boms.length; j++) + { + MProductBOM bom = boms[j]; + MOrderLine newLine = new MOrderLine (this); + newLine.setLine (++lineNo); + newLine.setM_Product_ID (bom.getProduct () + .getM_Product_ID ()); + newLine.setC_UOM_ID (bom.getProduct ().getC_UOM_ID ()); + newLine.setQty (line.getQtyOrdered ().multiply ( + bom.getBOMQty ())); + if (bom.getDescription () != null) + newLine.setDescription (bom.getDescription ()); + // + newLine.setPrice (); + newLine.save (get_TrxName()); + } + // Convert into Comment Line + line.setM_Product_ID (0); + line.setM_AttributeSetInstance_ID (0); + line.setPrice (Env.ZERO); + line.setPriceLimit (Env.ZERO); + line.setPriceList (Env.ZERO); + line.setLineNetAmt (Env.ZERO); + line.setFreightAmt (Env.ZERO); + // + String description = product.getName (); + if (product.getDescription () != null) + description += " " + product.getDescription (); + if (line.getDescription () != null) + description += " " + line.getDescription (); + line.setDescription (description); + line.save (get_TrxName()); + } // for all lines with BOM + + m_lines = null; // force requery + count = DB.getSQLValue (get_TrxName(), sql, getC_Invoice_ID ()); + renumberLines (10); + } // while count != 0 + return retValue; + } // explodeBOM + + + /** + * Reserve Inventory. + * Counterpart: MInOut.completeIt() + * @param dt document type or null + * @param lines order lines (ordered by M_Product_ID for deadlock prevention) + * @return true if (un) reserved + */ + private boolean reserveStock (MDocType dt, MOrderLine[] lines) + { + if (dt == null) + dt = MDocType.get(getCtx(), getC_DocType_ID()); + + // Binding + boolean binding = !dt.isProposal(); + // Not binding - i.e. Target=0 + if (DOCACTION_Void.equals(getDocAction()) + // Closing Binding Quotation + || (MDocType.DOCSUBTYPESO_Quotation.equals(dt.getDocSubTypeSO()) + && DOCACTION_Close.equals(getDocAction())) + || isDropShip() ) + binding = false; + boolean isSOTrx = isSOTrx(); + log.fine("Binding=" + binding + " - IsSOTrx=" + isSOTrx); + // Force same WH for all but SO/PO + int header_M_Warehouse_ID = getM_Warehouse_ID(); + if (MDocType.DOCSUBTYPESO_StandardOrder.equals(dt.getDocSubTypeSO()) + || MDocType.DOCBASETYPE_PurchaseOrder.equals(dt.getDocBaseType())) + header_M_Warehouse_ID = 0; // don't enforce + + BigDecimal Volume = Env.ZERO; + BigDecimal Weight = Env.ZERO; + + // Always check and (un) Reserve Inventory + for (int i = 0; i < lines.length; i++) + { + MOrderLine line = lines[i]; + // Check/set WH/Org + if (header_M_Warehouse_ID != 0) // enforce WH + { + if (header_M_Warehouse_ID != line.getM_Warehouse_ID()) + line.setM_Warehouse_ID(header_M_Warehouse_ID); + if (getAD_Org_ID() != line.getAD_Org_ID()) + line.setAD_Org_ID(getAD_Org_ID()); + } + // Binding + BigDecimal target = binding ? line.getQtyOrdered() : Env.ZERO; + BigDecimal difference = target + .subtract(line.getQtyReserved()) + .subtract(line.getQtyDelivered()); + if (difference.signum() == 0) + { + MProduct product = line.getProduct(); + if (product != null) + { + Volume = Volume.add(product.getVolume().multiply(line.getQtyOrdered())); + Weight = Weight.add(product.getWeight().multiply(line.getQtyOrdered())); + } + continue; + } + + log.fine("Line=" + line.getLine() + + " - Target=" + target + ",Difference=" + difference + + " - Ordered=" + line.getQtyOrdered() + + ",Reserved=" + line.getQtyReserved() + ",Delivered=" + line.getQtyDelivered()); + + // Check Product - Stocked and Item + MProduct product = line.getProduct(); + if (product != null) + { + if (product.isStocked()) + { + BigDecimal ordered = isSOTrx ? Env.ZERO : difference; + BigDecimal reserved = isSOTrx ? difference : Env.ZERO; + int M_Locator_ID = 0; + // Get Locator to reserve + if (line.getM_AttributeSetInstance_ID() != 0) // Get existing Location + M_Locator_ID = MStorage.getM_Locator_ID (line.getM_Warehouse_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), + ordered, get_TrxName()); + // Get default Location + if (M_Locator_ID == 0) + { + MWarehouse wh = MWarehouse.get(getCtx(), line.getM_Warehouse_ID()); + M_Locator_ID = wh.getDefaultLocator().getM_Locator_ID(); + } + // Update Storage + if (!MStorage.add(getCtx(), line.getM_Warehouse_ID(), M_Locator_ID, + line.getM_Product_ID(), + line.getM_AttributeSetInstance_ID(), line.getM_AttributeSetInstance_ID(), + Env.ZERO, reserved, ordered, get_TrxName())) + return false; + } // stockec + // update line + line.setQtyReserved(line.getQtyReserved().add(difference)); + if (!line.save(get_TrxName())) + return false; + // + Volume = Volume.add(product.getVolume().multiply(line.getQtyOrdered())); + Weight = Weight.add(product.getWeight().multiply(line.getQtyOrdered())); + } // product + } // reverse inventory + + setVolume(Volume); + setWeight(Weight); + return true; + } // reserveStock + + /** + * Calculate Tax and Total + * @return true if tax total calculated + */ + private boolean calculateTaxTotal() + { + log.fine(""); + // Delete Taxes + DB.executeUpdate("DELETE C_OrderTax WHERE C_Order_ID=" + getC_Order_ID(), get_TrxName()); + m_taxes = null; + + // Lines + BigDecimal totalLines = Env.ZERO; + ArrayList taxList = new ArrayList(); + MOrderLine[] lines = getLines(); + for (int i = 0; i < lines.length; i++) + { + MOrderLine line = lines[i]; + Integer taxID = new Integer(line.getC_Tax_ID()); + if (!taxList.contains(taxID)) + { + MOrderTax oTax = MOrderTax.get (line, getPrecision(), + false, get_TrxName()); // current Tax + oTax.setIsTaxIncluded(isTaxIncluded()); + if (!oTax.calculateTaxFromLines()) + return false; + if (!oTax.save(get_TrxName())) + return false; + taxList.add(taxID); + } + totalLines = totalLines.add(line.getLineNetAmt()); + } + + // Taxes + BigDecimal grandTotal = totalLines; + MOrderTax[] taxes = getTaxes(true); + for (int i = 0; i < taxes.length; i++) + { + MOrderTax oTax = taxes[i]; + MTax tax = oTax.getTax(); + if (tax.isSummary()) + { + MTax[] cTaxes = tax.getChildTaxes(false); + for (int j = 0; j < cTaxes.length; j++) + { + MTax cTax = cTaxes[j]; + BigDecimal taxAmt = cTax.calculateTax(oTax.getTaxBaseAmt(), isTaxIncluded(), getPrecision()); + // + MOrderTax newOTax = new MOrderTax(getCtx(), 0, get_TrxName()); + newOTax.setClientOrg(this); + newOTax.setC_Order_ID(getC_Order_ID()); + newOTax.setC_Tax_ID(cTax.getC_Tax_ID()); + newOTax.setPrecision(getPrecision()); + newOTax.setIsTaxIncluded(isTaxIncluded()); + newOTax.setTaxBaseAmt(oTax.getTaxBaseAmt()); + newOTax.setTaxAmt(taxAmt); + if (!newOTax.save(get_TrxName())) + return false; + // + if (!isTaxIncluded()) + grandTotal = grandTotal.add(taxAmt); + } + if (!oTax.delete(true, get_TrxName())) + return false; + } + else + { + if (!isTaxIncluded()) + grandTotal = grandTotal.add(oTax.getTaxAmt()); + } + } + // + setTotalLines(totalLines); + setGrandTotal(grandTotal); + return true; + } // calculateTaxTotal + + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info("approveIt - " + toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info("rejectIt - " + toString()); + setIsApproved(false); + return true; + } // rejectIt + + + /************************************************************************** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + String DocSubTypeSO = dt.getDocSubTypeSO(); + + // Just prepare + if (DOCACTION_Prepare.equals(getDocAction())) + { + setProcessed(false); + return DocAction.STATUS_InProgress; + } + // Offers + if (MDocType.DOCSUBTYPESO_Proposal.equals(DocSubTypeSO) + || MDocType.DOCSUBTYPESO_Quotation.equals(DocSubTypeSO)) + { + // Binding + if (MDocType.DOCSUBTYPESO_Quotation.equals(DocSubTypeSO)) + reserveStock(dt, getLines(true, "M_Product_ID")); + setProcessed(true); + return DocAction.STATUS_Completed; + } + // Waiting Payment - until we have a payment + if (!m_forceCreation + && MDocType.DOCSUBTYPESO_PrepayOrder.equals(DocSubTypeSO) + && getC_Payment_ID() == 0 && getC_CashLine_ID() == 0) + { + setProcessed(true); + return DocAction.STATUS_WaitingPayment; + } + + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + // Implicit Approval + if (!isApproved()) + approveIt(); + getLines(true,null); + log.info(toString()); + StringBuffer info = new StringBuffer(); + + boolean realTimePOS = false; + + // Create SO Shipment - Force Shipment + MInOut shipment = null; + if (MDocType.DOCSUBTYPESO_OnCreditOrder.equals(DocSubTypeSO) // (W)illCall(I)nvoice + || MDocType.DOCSUBTYPESO_WarehouseOrder.equals(DocSubTypeSO) // (W)illCall(P)ickup + || MDocType.DOCSUBTYPESO_POSOrder.equals(DocSubTypeSO) // (W)alkIn(R)eceipt + || MDocType.DOCSUBTYPESO_PrepayOrder.equals(DocSubTypeSO)) + { + if (!DELIVERYRULE_Force.equals(getDeliveryRule())) + setDeliveryRule(DELIVERYRULE_Force); + // + shipment = createShipment (dt, realTimePOS ? null : getDateOrdered()); + if (shipment == null) + return DocAction.STATUS_Invalid; + info.append("@M_InOut_ID@: ").append(shipment.getDocumentNo()); + String msg = shipment.getProcessMsg(); + if (msg != null && msg.length() > 0) + info.append(" (").append(msg).append(")"); + } // Shipment + + + // Create SO Invoice - Always invoice complete Order + if ( MDocType.DOCSUBTYPESO_POSOrder.equals(DocSubTypeSO) + || MDocType.DOCSUBTYPESO_OnCreditOrder.equals(DocSubTypeSO) + || MDocType.DOCSUBTYPESO_PrepayOrder.equals(DocSubTypeSO)) + { + MInvoice invoice = createInvoice (dt, shipment, realTimePOS ? null : getDateOrdered()); + if (invoice == null) + return DocAction.STATUS_Invalid; + info.append(" - @C_Invoice_ID@: ").append(invoice.getDocumentNo()); + String msg = invoice.getProcessMsg(); + if (msg != null && msg.length() > 0) + info.append(" (").append(msg).append(")"); + } // Invoice + + // Counter Documents + MOrder counter = createCounterDoc(); + if (counter != null) + info.append(" - @CounterDoc@: @Order@=").append(counter.getDocumentNo()); + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + if (info.length() > 0) + info.append(" - "); + info.append(valid); + m_processMsg = info.toString(); + return DocAction.STATUS_Invalid; + } + + setProcessed(true); + m_processMsg = info.toString(); + // + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + /** + * Create Shipment + * @param dt order document type + * @param movementDate optional movement date (default today) + * @return shipment or null + */ + private MInOut createShipment(MDocType dt, Timestamp movementDate) + { + log.info("For " + dt); + MInOut shipment = new MInOut (this, dt.getC_DocTypeShipment_ID(), movementDate); + // shipment.setDateAcct(getDateAcct()); + if (!shipment.save(get_TrxName())) + { + m_processMsg = "Could not create Shipment"; + return null; + } + // + MOrderLine[] oLines = getLines(true, null); + for (int i = 0; i < oLines.length; i++) + { + MOrderLine oLine = oLines[i]; + // + MInOutLine ioLine = new MInOutLine(shipment); + // Qty = Ordered - Delivered + BigDecimal MovementQty = oLine.getQtyOrdered().subtract(oLine.getQtyDelivered()); + // Location + int M_Locator_ID = MStorage.getM_Locator_ID (oLine.getM_Warehouse_ID(), + oLine.getM_Product_ID(), oLine.getM_AttributeSetInstance_ID(), + MovementQty, get_TrxName()); + if (M_Locator_ID == 0) // Get default Location + { + MWarehouse wh = MWarehouse.get(getCtx(), oLine.getM_Warehouse_ID()); + M_Locator_ID = wh.getDefaultLocator().getM_Locator_ID(); + } + // + ioLine.setOrderLine(oLine, M_Locator_ID, MovementQty); + ioLine.setQty(MovementQty); + if (oLine.getQtyEntered().compareTo(oLine.getQtyOrdered()) != 0) + ioLine.setQtyEntered(MovementQty + .multiply(oLine.getQtyEntered()) + .divide(oLine.getQtyOrdered(), 6, BigDecimal.ROUND_HALF_UP)); + if (!ioLine.save(get_TrxName())) + { + m_processMsg = "Could not create Shipment Line"; + return null; + } + } + // Manually Process Shipment + String status = shipment.completeIt(); + shipment.setDocStatus(status); + shipment.save(get_TrxName()); + if (!DOCSTATUS_Completed.equals(status)) + { + m_processMsg = "@M_InOut_ID@: " + shipment.getProcessMsg(); + return null; + } + return shipment; + } // createShipment + + /** + * Create Invoice + * @param dt order document type + * @param shipment optional shipment + * @param invoiceDate invoice date + * @return invoice or null + */ + private MInvoice createInvoice (MDocType dt, MInOut shipment, Timestamp invoiceDate) + { + log.info(dt.toString()); + MInvoice invoice = new MInvoice (this, dt.getC_DocTypeInvoice_ID(), invoiceDate); + if (!invoice.save(get_TrxName())) + { + m_processMsg = "Could not create Invoice"; + return null; + } + + // If we have a Shipment - use that as a base + if (shipment != null) + { + if (!INVOICERULE_AfterDelivery.equals(getInvoiceRule())) + setInvoiceRule(INVOICERULE_AfterDelivery); + // + MInOutLine[] sLines = shipment.getLines(false); + for (int i = 0; i < sLines.length; i++) + { + MInOutLine sLine = sLines[i]; + // + MInvoiceLine iLine = new MInvoiceLine(invoice); + iLine.setShipLine(sLine); + // Qty = Delivered + iLine.setQtyEntered(sLine.getQtyEntered()); + iLine.setQtyInvoiced(sLine.getMovementQty()); + if (!iLine.save(get_TrxName())) + { + m_processMsg = "Could not create Invoice Line from Shipment Line"; + return null; + } + // + sLine.setIsInvoiced(true); + if (!sLine.save(get_TrxName())) + { + log.warning("Could not update Shipment line: " + sLine); + } + } + } + else // Create Invoice from Order + { + if (!INVOICERULE_Immediate.equals(getInvoiceRule())) + setInvoiceRule(INVOICERULE_Immediate); + // + MOrderLine[] oLines = getLines(); + for (int i = 0; i < oLines.length; i++) + { + MOrderLine oLine = oLines[i]; + // + MInvoiceLine iLine = new MInvoiceLine(invoice); + iLine.setOrderLine(oLine); + // Qty = Ordered - Invoiced + iLine.setQtyInvoiced(oLine.getQtyOrdered().subtract(oLine.getQtyInvoiced())); + if (oLine.getQtyOrdered().compareTo(oLine.getQtyEntered()) == 0) + iLine.setQtyEntered(iLine.getQtyInvoiced()); + else + iLine.setQtyEntered(iLine.getQtyInvoiced().multiply(oLine.getQtyEntered()) + .divide(oLine.getQtyOrdered(), 12, BigDecimal.ROUND_HALF_UP)); + if (!iLine.save(get_TrxName())) + { + m_processMsg = "Could not create Invoice Line from Order Line"; + return null; + } + } + } + // Manually Process Invoice + String status = invoice.completeIt(); + invoice.setDocStatus(status); + invoice.save(get_TrxName()); + setC_CashLine_ID(invoice.getC_CashLine_ID()); + if (!DOCSTATUS_Completed.equals(status)) + { + m_processMsg = "@C_Invoice_ID@: " + invoice.getProcessMsg(); + return null; + } + return invoice; + } // createInvoice + + /** + * Create Counter Document + * @return counter order + */ + private MOrder createCounterDoc() + { + // Is this itself a counter doc ? + if (getRef_Order_ID() != 0) + return null; + + // Org Must be linked to BPartner + MOrg org = MOrg.get(getCtx(), getAD_Org_ID()); + int counterC_BPartner_ID = org.getLinkedC_BPartner_ID(); + if (counterC_BPartner_ID == 0) + return null; + // Business Partner needs to be linked to Org + MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), null); + int counterAD_Org_ID = bp.getAD_OrgBP_ID_Int(); + if (counterAD_Org_ID == 0) + return null; + + MBPartner counterBP = new MBPartner (getCtx(), counterC_BPartner_ID, null); + MOrgInfo counterOrgInfo = MOrgInfo.get(getCtx(), counterAD_Org_ID); + log.info("Counter BP=" + counterBP.getName()); + + // Document Type + int C_DocTypeTarget_ID = 0; + MDocTypeCounter counterDT = MDocTypeCounter.getCounterDocType(getCtx(), getC_DocType_ID()); + if (counterDT != null) + { + log.fine(counterDT.toString()); + if (!counterDT.isCreateCounter() || !counterDT.isValid()) + return null; + C_DocTypeTarget_ID = counterDT.getCounter_C_DocType_ID(); + } + else // indirect + { + C_DocTypeTarget_ID = MDocTypeCounter.getCounterDocType_ID(getCtx(), getC_DocType_ID()); + log.fine("Indirect C_DocTypeTarget_ID=" + C_DocTypeTarget_ID); + if (C_DocTypeTarget_ID <= 0) + return null; + } + // Deep Copy + MOrder counter = copyFrom (this, getDateOrdered(), + C_DocTypeTarget_ID, !isSOTrx(), true, false, get_TrxName()); + // + counter.setAD_Org_ID(counterAD_Org_ID); + counter.setM_Warehouse_ID(counterOrgInfo.getM_Warehouse_ID()); + // + counter.setBPartner(counterBP); + counter.setDatePromised(getDatePromised()); // default is date ordered + // Refernces (Should not be required + counter.setSalesRep_ID(getSalesRep_ID()); + counter.save(get_TrxName()); + + // Update copied lines + MOrderLine[] counterLines = counter.getLines(true, null); + for (int i = 0; i < counterLines.length; i++) + { + MOrderLine counterLine = counterLines[i]; + counterLine.setOrder(counter); // copies header values (BP, etc.) + counterLine.setPrice(); + counterLine.setTax(); + counterLine.save(get_TrxName()); + } + log.fine(counter.toString()); + + // Document Action + if (counterDT != null) + { + if (counterDT.getDocAction() != null) + { + counter.setDocAction(counterDT.getDocAction()); + counter.processIt(counterDT.getDocAction()); + counter.save(get_TrxName()); + } + } + return counter; + } // createCounterDoc + + /** + * Void Document. + * Set Qtys to 0 - Sales: reverse all documents + * @return true if success + */ + public boolean voidIt() + { + MOrderLine[] lines = getLines(true, "M_Product_ID"); + log.info(toString()); + for (int i = 0; i < lines.length; i++) + { + MOrderLine line = lines[i]; + BigDecimal old = line.getQtyOrdered(); + if (old.signum() != 0) + { + line.addDescription(Msg.getMsg(getCtx(), "Voided") + " (" + old + ")"); + line.setQty(Env.ZERO); + line.setLineNetAmt(Env.ZERO); + line.save(get_TrxName()); + } + } + addDescription(Msg.getMsg(getCtx(), "Voided")); + // Clear Reservations + if (!reserveStock(null, lines)) + { + m_processMsg = "Cannot unreserve Stock (void)"; + return false; + } + + if (!createReversals()) + return false; + + setProcessed(true); + setDocAction(DOCACTION_None); + return true; + } // voidIt + + /** + * Create Shipment/Invoice Reversals + * @return true if success + */ + private boolean createReversals() + { + // Cancel only Sales + if (!isSOTrx()) + return true; + + log.info("createReversals"); + StringBuffer info = new StringBuffer(); + + // Reverse All *Shipments* + info.append("@M_InOut_ID@:"); + MInOut[] shipments = getShipments(); + for (int i = 0; i < shipments.length; i++) + { + MInOut ship = shipments[i]; + // if closed - ignore + if (MInOut.DOCSTATUS_Closed.equals(ship.getDocStatus()) + || MInOut.DOCSTATUS_Reversed.equals(ship.getDocStatus()) + || MInOut.DOCSTATUS_Voided.equals(ship.getDocStatus()) ) + continue; + ship.set_TrxName(get_TrxName()); + + // If not completed - void - otherwise reverse it + if (!MInOut.DOCSTATUS_Completed.equals(ship.getDocStatus())) + { + if (ship.voidIt()) + ship.setDocStatus(MInOut.DOCSTATUS_Voided); + } + else if (ship.reverseCorrectIt()) // completed shipment + { + ship.setDocStatus(MInOut.DOCSTATUS_Reversed); + info.append(" ").append(ship.getDocumentNo()); + } + else + { + m_processMsg = "Could not reverse Shipment " + ship; + return false; + } + ship.setDocAction(MInOut.DOCACTION_None); + ship.save(get_TrxName()); + } // for all shipments + + // Reverse All *Invoices* + info.append(" - @C_Invoice_ID@:"); + MInvoice[] invoices = getInvoices(); + for (int i = 0; i < invoices.length; i++) + { + MInvoice invoice = invoices[i]; + // if closed - ignore + if (MInvoice.DOCSTATUS_Closed.equals(invoice.getDocStatus()) + || MInvoice.DOCSTATUS_Reversed.equals(invoice.getDocStatus()) + || MInvoice.DOCSTATUS_Voided.equals(invoice.getDocStatus()) ) + continue; + invoice.set_TrxName(get_TrxName()); + + // If not compleded - void - otherwise reverse it + if (!MInvoice.DOCSTATUS_Completed.equals(invoice.getDocStatus())) + { + if (invoice.voidIt()) + invoice.setDocStatus(MInvoice.DOCSTATUS_Voided); + } + else if (invoice.reverseCorrectIt()) // completed invoice + { + invoice.setDocStatus(MInvoice.DOCSTATUS_Reversed); + info.append(" ").append(invoice.getDocumentNo()); + } + else + { + m_processMsg = "Could not reverse Invoice " + invoice; + return false; + } + invoice.setDocAction(MInvoice.DOCACTION_None); + invoice.save(get_TrxName()); + } // for all shipments + + m_processMsg = info.toString(); + return true; + } // createReversals + + + /** + * Close Document. + * Cancel not delivered Qunatities + * @return true if success + */ + public boolean closeIt() + { + log.info(toString()); + + // Close Not delivered Qty - SO/PO + MOrderLine[] lines = getLines(true, "M_Product_ID"); + for (int i = 0; i < lines.length; i++) + { + MOrderLine line = lines[i]; + BigDecimal old = line.getQtyOrdered(); + if (old.compareTo(line.getQtyDelivered()) != 0) + { + line.setQtyLostSales(line.getQtyOrdered().subtract(line.getQtyDelivered())); + line.setQtyOrdered(line.getQtyDelivered()); + // QtyEntered unchanged + line.addDescription("Close (" + old + ")"); + line.save(get_TrxName()); + } + } + // Clear Reservations + if (!reserveStock(null, lines)) + { + m_processMsg = "Cannot unreserve Stock (close)"; + return false; + } + setProcessed(true); + setDocAction(DOCACTION_None); + return true; + } // closeIt + + /** + * Reverse Correction - same void + * @return true if success + */ + public boolean reverseCorrectIt() + { + log.info(toString()); + return voidIt(); + } // reverseCorrectionIt + + /** + * Reverse Accrual - none + * @return false + */ + public boolean reverseAccrualIt() + { + log.info(toString()); + return false; + } // reverseAccrualIt + + /** + * Re-activate. + * @return true if success + */ + public boolean reActivateIt() + { + log.info(toString()); + + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + String DocSubTypeSO = dt.getDocSubTypeSO(); + + // PO - just re-open + if (!isSOTrx()) + log.info("Existing documents not modified - " + dt); + // Reverse Direct Documents + else if (MDocType.DOCSUBTYPESO_OnCreditOrder.equals(DocSubTypeSO) // (W)illCall(I)nvoice + || MDocType.DOCSUBTYPESO_WarehouseOrder.equals(DocSubTypeSO) // (W)illCall(P)ickup + || MDocType.DOCSUBTYPESO_POSOrder.equals(DocSubTypeSO)) // (W)alkIn(R)eceipt + { + if (!createReversals()) + return false; + } + else + { + log.info("Existing documents not modified - SubType=" + DocSubTypeSO); + } + + setDocAction(DOCACTION_Complete); + setProcessed(false); + return true; + } // reActivateIt + + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getDocumentNo()); + // : Grand Total = 123.00 (#1) + sb.append(": "). + append(Msg.translate(getCtx(),"GrandTotal")).append("=").append(getGrandTotal()); + if (m_lines != null) + sb.append(" (#").append(m_lines.length).append(")"); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner (Responsible) + * @return AD_User_ID + */ + public int getDoc_User_ID() + { + return getSalesRep_ID(); + } // getDoc_User_ID + + /** + * Get Document Approval Amount + * @return amount + */ + public BigDecimal getApprovalAmt() + { + return getGrandTotal(); + } // getApprovalAmt + +} // MOrder diff --git a/base/src/org/compiere/model/MOrderLine.java b/base/src/org/compiere/model/MOrderLine.java new file mode 100644 index 0000000000..b4d65b7239 --- /dev/null +++ b/base/src/org/compiere/model/MOrderLine.java @@ -0,0 +1,936 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Order Line Model. + * + * MOrderLine ol = new MOrderLine(m_order); + ol.setM_Product_ID(wbl.getM_Product_ID()); + ol.setQtyOrdered(wbl.getQuantity()); + ol.setPrice(); + ol.setPriceActual(wbl.getPrice()); + ol.setTax(); + ol.save(); + + * + * @author Jorg Janke + * @version $Id: MOrderLine.java,v 1.6 2006/10/02 05:18:39 jjanke Exp $ + */ +public class MOrderLine extends X_C_OrderLine +{ + + /** + * Get Order Unreserved Qty + * @param ctx context + * @param M_Warehouse_ID wh + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID asi + * @param excludeC_OrderLine_ID exclude C_OrderLine_ID + * @return Unreserved Qty + */ + public static BigDecimal getNotReserved (Properties ctx, int M_Warehouse_ID, + int M_Product_ID, int M_AttributeSetInstance_ID, int excludeC_OrderLine_ID) + { + BigDecimal retValue = Env.ZERO; + String sql = "SELECT SUM(QtyOrdered-QtyDelivered-QtyReserved) " + + "FROM C_OrderLine ol" + + " INNER JOIN C_Order o ON (ol.C_Order_ID=o.C_Order_ID) " + + "WHERE ol.M_Warehouse_ID=?" // #1 + + " AND M_Product_ID=?" // #2 + + " AND o.IsSOTrx='Y' AND o.DocStatus='DR'" + + " AND QtyOrdered-QtyDelivered-QtyReserved<>0" + + " AND ol.C_OrderLine_ID<>?"; + if (M_AttributeSetInstance_ID != 0) + sql += " AND M_AttributeSetInstance_ID=?"; + + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, M_Warehouse_ID); + pstmt.setInt (2, M_Product_ID); + pstmt.setInt (3, excludeC_OrderLine_ID); + if (M_AttributeSetInstance_ID != 0) + pstmt.setInt (4, M_AttributeSetInstance_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = rs.getBigDecimal(1); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (retValue == null) + s_log.fine("-"); + else + s_log.fine(retValue.toString()); + return retValue; + } // getNotReserved + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MOrderLine.class); + + /************************************************************************** + * Default Constructor + * @param ctx context + * @param C_OrderLine_ID order line to load + * @param trxName trx name + */ + public MOrderLine (Properties ctx, int C_OrderLine_ID, String trxName) + { + super (ctx, C_OrderLine_ID, trxName); + if (C_OrderLine_ID == 0) + { + // setC_Order_ID (0); + // setLine (0); + // setM_Warehouse_ID (0); // @M_Warehouse_ID@ + // setC_BPartner_ID(0); + // setC_BPartner_Location_ID (0); // @C_BPartner_Location_ID@ + // setC_Currency_ID (0); // @C_Currency_ID@ + // setDateOrdered (new Timestamp(System.currentTimeMillis())); // @DateOrdered@ + // + // setC_Tax_ID (0); + // setC_UOM_ID (0); + // + setFreightAmt (Env.ZERO); + setLineNetAmt (Env.ZERO); + // + setPriceEntered(Env.ZERO); + setPriceActual (Env.ZERO); + setPriceLimit (Env.ZERO); + setPriceList (Env.ZERO); + // + setM_AttributeSetInstance_ID(0); + // + setQtyEntered (Env.ZERO); + setQtyOrdered (Env.ZERO); // 1 + setQtyDelivered (Env.ZERO); + setQtyInvoiced (Env.ZERO); + setQtyReserved (Env.ZERO); + // + setIsDescription (false); // N + setProcessed (false); + setLine (0); + } + } // MOrderLine + + /** + * Parent Constructor. + ol.setM_Product_ID(wbl.getM_Product_ID()); + ol.setQtyOrdered(wbl.getQuantity()); + ol.setPrice(); + ol.setPriceActual(wbl.getPrice()); + ol.setTax(); + ol.save(); + * @param order parent order + */ + public MOrderLine (MOrder order) + { + this (order.getCtx(), 0, order.get_TrxName()); + if (order.get_ID() == 0) + throw new IllegalArgumentException("Header not saved"); + setC_Order_ID (order.getC_Order_ID()); // parent + setOrder(order); + } // MOrderLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set record + * @param trxName transaction + */ + public MOrderLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MOrderLine + + private int m_M_PriceList_ID = 0; + // + private boolean m_IsSOTrx = true; + // Product Pricing + private MProductPricing m_productPrice = null; + + /** Cached Currency Precision */ + private Integer m_precision = null; + /** Product */ + private MProduct m_product = null; + /** Parent */ + private MOrder m_parent = null; + + /** + * Set Defaults from Order. + * Does not set Parent !! + * @param order order + */ + public void setOrder (MOrder order) + { + setClientOrg(order); + setC_BPartner_ID(order.getC_BPartner_ID()); + setC_BPartner_Location_ID(order.getC_BPartner_Location_ID()); + setM_Warehouse_ID(order.getM_Warehouse_ID()); + setDateOrdered(order.getDateOrdered()); + setDatePromised(order.getDatePromised()); + setC_Currency_ID(order.getC_Currency_ID()); + // + setHeaderInfo(order); // sets m_order + // Don't set Activity, etc as they are overwrites + } // setOrder + + /** + * Set Header Info + * @param order order + */ + public void setHeaderInfo (MOrder order) + { + m_parent = order; + m_precision = new Integer(order.getPrecision()); + m_M_PriceList_ID = order.getM_PriceList_ID(); + m_IsSOTrx = order.isSOTrx(); + } // setHeaderInfo + + /** + * Get Parent + * @return parent + */ + public MOrder getParent() + { + if (m_parent == null) + m_parent = new MOrder(getCtx(), getC_Order_ID(), get_TrxName()); + return m_parent; + } // getParent + + /** + * Set Price Entered/Actual. + * Use this Method if the Line UOM is the Product UOM + * @param PriceActual price + */ + public void setPrice (BigDecimal PriceActual) + { + setPriceEntered(PriceActual); + setPriceActual (PriceActual); + } // setPrice + + /** + * Set Price Actual. + * (actual price is not updateable) + * @param PriceActual actual price + */ + public void setPriceActual (BigDecimal PriceActual) + { + if (PriceActual == null) + throw new IllegalArgumentException ("PriceActual is mandatory"); + set_ValueNoCheck("PriceActual", PriceActual); + } // setPriceActual + + /** + * Set Price for Product and PriceList. + * Use only if newly created. + * Uses standard price list of not set by order constructor + */ + public void setPrice() + { + if (getM_Product_ID() == 0) + return; + if (m_M_PriceList_ID == 0) + throw new IllegalStateException("PriceList unknown!"); + setPrice (m_M_PriceList_ID); + } // setPrice + + /** + * Set Price for Product and PriceList + * @param M_PriceList_ID price list + */ + public void setPrice (int M_PriceList_ID) + { + if (getM_Product_ID() == 0) + return; + // + log.fine(toString() + " - M_PriceList_ID=" + M_PriceList_ID); + getProductPricing (M_PriceList_ID); + setPriceActual (m_productPrice.getPriceStd()); + setPriceList (m_productPrice.getPriceList()); + setPriceLimit (m_productPrice.getPriceLimit()); + // + if (getQtyEntered().compareTo(getQtyOrdered()) == 0) + setPriceEntered(getPriceActual()); + else + setPriceEntered(getPriceActual().multiply(getQtyOrdered() + .divide(getQtyEntered(), 12, BigDecimal.ROUND_HALF_UP))); // recision + + // Calculate Discount + setDiscount(m_productPrice.getDiscount()); + // Set UOM + setC_UOM_ID(m_productPrice.getC_UOM_ID()); + } // setPrice + + /** + * Get and calculate Product Pricing + * @param M_PriceList_ID id + * @return product pricing + */ + private MProductPricing getProductPricing (int M_PriceList_ID) + { + m_productPrice = new MProductPricing (getM_Product_ID(), + getC_BPartner_ID(), getQtyOrdered(), m_IsSOTrx); + m_productPrice.setM_PriceList_ID(M_PriceList_ID); + m_productPrice.setPriceDate(getDateOrdered()); + // + m_productPrice.calculatePrice(); + return m_productPrice; + } // getProductPrice + + /** + * Set Tax + * @return true if tax is set + */ + public boolean setTax() + { + int ii = Tax.get(getCtx(), getM_Product_ID(), getC_Charge_ID(), getDateOrdered(), getDateOrdered(), + getAD_Org_ID(), getM_Warehouse_ID(), + getC_BPartner_Location_ID(), // should be bill to + getC_BPartner_Location_ID(), m_IsSOTrx); + if (ii == 0) + { + log.log(Level.SEVERE, "No Tax found"); + return false; + } + setC_Tax_ID (ii); + return true; + } // setTax + + /** + * Calculate Extended Amt. + * May or may not include tax + */ + public void setLineNetAmt () + { + BigDecimal bd = getPriceActual().multiply(getQtyOrdered()); + if (bd.scale() > getPrecision()) + bd = bd.setScale(getPrecision(), BigDecimal.ROUND_HALF_UP); + super.setLineNetAmt (bd); + } // setLineNetAmt + + /** + * Get Currency Precision from Currency + * @return precision + */ + public int getPrecision() + { + if (m_precision != null) + return m_precision.intValue(); + // + if (getC_Currency_ID() == 0) + { + setOrder (getParent()); + if (m_precision != null) + return m_precision.intValue(); + } + if (getC_Currency_ID() != 0) + { + MCurrency cur = MCurrency.get(getCtx(), getC_Currency_ID()); + if (cur.get_ID() != 0) + { + m_precision = new Integer (cur.getStdPrecision()); + return m_precision.intValue(); + } + } + // Fallback + String sql = "SELECT c.StdPrecision " + + "FROM C_Currency c INNER JOIN C_Order x ON (x.C_Currency_ID=c.C_Currency_ID) " + + "WHERE x.C_Order_ID=?"; + int i = DB.getSQLValue(get_TrxName(), sql, getC_Order_ID()); + m_precision = new Integer(i); + return m_precision.intValue(); + } // getPrecision + + /** + * Set Product + * @param product product + */ + public void setProduct (MProduct product) + { + m_product = product; + if (m_product != null) + { + setM_Product_ID(m_product.getM_Product_ID()); + setC_UOM_ID (m_product.getC_UOM_ID()); + } + else + { + setM_Product_ID(0); + set_ValueNoCheck ("C_UOM_ID", null); + } + setM_AttributeSetInstance_ID(0); + } // setProduct + + + /** + * Set M_Product_ID + * @param M_Product_ID product + * @param setUOM set also UOM + */ + public void setM_Product_ID (int M_Product_ID, boolean setUOM) + { + if (setUOM) + setProduct(MProduct.get(getCtx(), M_Product_ID)); + else + super.setM_Product_ID (M_Product_ID); + setM_AttributeSetInstance_ID(0); + } // setM_Product_ID + + /** + * Set Product and UOM + * @param M_Product_ID product + * @param C_UOM_ID uom + */ + public void setM_Product_ID (int M_Product_ID, int C_UOM_ID) + { + super.setM_Product_ID (M_Product_ID); + if (C_UOM_ID != 0) + super.setC_UOM_ID(C_UOM_ID); + setM_AttributeSetInstance_ID(0); + } // setM_Product_ID + + + /** + * Get Product + * @return product or null + */ + public MProduct getProduct() + { + if (m_product == null && getM_Product_ID() != 0) + m_product = MProduct.get (getCtx(), getM_Product_ID()); + return m_product; + } // getProduct + + /** + * Set M_AttributeSetInstance_ID + * @param M_AttributeSetInstance_ID id + */ + public void setM_AttributeSetInstance_ID (int M_AttributeSetInstance_ID) + { + if (M_AttributeSetInstance_ID == 0) // 0 is valid ID + set_Value("M_AttributeSetInstance_ID", new Integer(0)); + else + super.setM_AttributeSetInstance_ID (M_AttributeSetInstance_ID); + } // setM_AttributeSetInstance_ID + + /** + * Set Warehouse + * @param M_Warehouse_ID warehouse + */ + public void setM_Warehouse_ID (int M_Warehouse_ID) + { + if (getM_Warehouse_ID() > 0 + && getM_Warehouse_ID() != M_Warehouse_ID + && !canChangeWarehouse()) + log.severe("Ignored - Already Delivered/Invoiced/Reserved"); + else + super.setM_Warehouse_ID (M_Warehouse_ID); + } // setM_Warehouse_ID + + /** + * Can Change Warehouse + * @return true if warehouse can be changed + */ + public boolean canChangeWarehouse() + { + if (getQtyDelivered().signum() != 0) + { + log.saveError("Error", Msg.translate(getCtx(), "QtyDelivered") + "=" + getQtyDelivered()); + return false; + } + if (getQtyInvoiced().signum() != 0) + { + log.saveError("Error", Msg.translate(getCtx(), "QtyInvoiced") + "=" + getQtyInvoiced()); + return false; + } + if (getQtyReserved().signum() != 0) + { + log.saveError("Error", Msg.translate(getCtx(), "QtyReserved") + "=" + getQtyReserved()); + return false; + } + // We can change + return true; + } // canChangeWarehouse + + /** + * Get C_Project_ID + * @return project + */ + public int getC_Project_ID() + { + int ii = super.getC_Project_ID (); + if (ii == 0) + ii = getParent().getC_Project_ID(); + return ii; + } // getC_Project_ID + + /** + * Get C_Activity_ID + * @return Activity + */ + public int getC_Activity_ID() + { + int ii = super.getC_Activity_ID (); + if (ii == 0) + ii = getParent().getC_Activity_ID(); + return ii; + } // getC_Activity_ID + + /** + * Get C_Campaign_ID + * @return Campaign + */ + public int getC_Campaign_ID() + { + int ii = super.getC_Campaign_ID (); + if (ii == 0) + ii = getParent().getC_Campaign_ID(); + return ii; + } // getC_Campaign_ID + + /** + * Get User2_ID + * @return User2 + */ + public int getUser1_ID () + { + int ii = super.getUser1_ID (); + if (ii == 0) + ii = getParent().getUser1_ID(); + return ii; + } // getUser1_ID + + /** + * Get User2_ID + * @return User2 + */ + public int getUser2_ID () + { + int ii = super.getUser2_ID (); + if (ii == 0) + ii = getParent().getUser2_ID(); + return ii; + } // getUser2_ID + + /** + * Get AD_OrgTrx_ID + * @return trx org + */ + public int getAD_OrgTrx_ID() + { + int ii = super.getAD_OrgTrx_ID(); + if (ii == 0) + ii = getParent().getAD_OrgTrx_ID(); + return ii; + } // getAD_OrgTrx_ID + + /************************************************************************** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MOrderLine[") + .append(get_ID()).append(",Line=").append(getLine()) + .append(",Ordered=").append(getQtyOrdered()) + .append(",Delivered=").append(getQtyDelivered()) + .append(",Invoiced=").append(getQtyInvoiced()) + .append(",Reserved=").append(getQtyReserved()) + .append(", LineNet=").append(getLineNetAmt()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * Get Description Text. + * For jsp access (vs. isDescription) + * @return description + */ + public String getDescriptionText() + { + return super.getDescription(); + } // getDescriptionText + + /** + * Get Name + * @return get the name of the line (from Product) + */ + public String getName() + { + getProduct(); + if (m_product != null) + return m_product.getName(); + if (getC_Charge_ID() != 0) + { + MCharge charge = MCharge.get(getCtx(), getC_Charge_ID()); + return charge.getName(); + } + return ""; + } // getName + + /** + * Set C_Charge_ID + * @param C_Charge_ID charge + */ + public void setC_Charge_ID (int C_Charge_ID) + { + super.setC_Charge_ID (C_Charge_ID); + if (C_Charge_ID > 0) + set_ValueNoCheck ("C_UOM_ID", null); + } // setC_Charge_ID + /** + * Set Discount + */ + public void setDiscount() + { + BigDecimal list = getPriceList(); + // No List Price + if (Env.ZERO.compareTo(list) == 0) + return; + BigDecimal discount = list.subtract(getPriceActual()) + .multiply(new BigDecimal(100)) + .divide(list, getPrecision(), BigDecimal.ROUND_HALF_UP); + setDiscount(discount); + } // setDiscount + + /** + * Is Tax Included in Amount + * @return true if tax calculated + */ + public boolean isTaxIncluded() + { + if (m_M_PriceList_ID == 0) + { + m_M_PriceList_ID = DB.getSQLValue(get_TrxName(), + "SELECT M_PriceList_ID FROM C_Order WHERE C_Order_ID=?", + getC_Order_ID()); + } + MPriceList pl = MPriceList.get(getCtx(), m_M_PriceList_ID, get_TrxName()); + return pl.isTaxIncluded(); + } // isTaxIncluded + + + /** + * Set Qty Entered/Ordered. + * Use this Method if the Line UOM is the Product UOM + * @param Qty QtyOrdered/Entered + */ + public void setQty (BigDecimal Qty) + { + super.setQtyEntered (Qty); + super.setQtyOrdered (getQtyEntered()); + } // setQty + + /** + * Set Qty Entered - enforce entered UOM + * @param QtyEntered + */ + public void setQtyEntered (BigDecimal QtyEntered) + { + if (QtyEntered != null && getC_UOM_ID() != 0) + { + int precision = MUOM.getPrecision(getCtx(), getC_UOM_ID()); + QtyEntered = QtyEntered.setScale(precision, BigDecimal.ROUND_HALF_UP); + } + super.setQtyEntered (QtyEntered); + } // setQtyEntered + + /** + * Set Qty Ordered - enforce Product UOM + * @param QtyOrdered + */ + public void setQtyOrdered (BigDecimal QtyOrdered) + { + MProduct product = getProduct(); + if (QtyOrdered != null && product != null) + { + int precision = product.getUOMPrecision(); + QtyOrdered = QtyOrdered.setScale(precision, BigDecimal.ROUND_HALF_UP); + } + super.setQtyOrdered(QtyOrdered); + } // setQtyOrdered + + /************************************************************************** + * Before Save + * @param newRecord + * @return true if it can be sabed + */ + protected boolean beforeSave (boolean newRecord) + { + // Get Defaults from Parent + if (getC_BPartner_ID() == 0 || getC_BPartner_Location_ID() == 0 + || getM_Warehouse_ID() == 0 + || getC_Currency_ID() == 0) + setOrder (getParent()); + if (m_M_PriceList_ID == 0) + setHeaderInfo(getParent()); + + + // R/O Check - Product/Warehouse Change + if (!newRecord + && (is_ValueChanged("M_Product_ID") || is_ValueChanged("M_Warehouse_ID"))) + { + if (!canChangeWarehouse()) + return false; + } // Product Changed + + // Charge + if (getC_Charge_ID() != 0 && getM_Product_ID() != 0) + setM_Product_ID(0); + // No Product + if (getM_Product_ID() == 0) + setM_AttributeSetInstance_ID(0); + // Product + else // Set/check Product Price + { + // Set Price if Actual = 0 + if (m_productPrice == null + && Env.ZERO.compareTo(getPriceActual()) == 0 + && Env.ZERO.compareTo(getPriceList()) == 0) + setPrice(); + // Check if on Price list + if (m_productPrice == null) + getProductPricing(m_M_PriceList_ID); + if (!m_productPrice.isCalculated()) + { + log.saveError("Error", Msg.getMsg(getCtx(), "ProductNotOnPriceList")); + return false; + } + } + + // UOM + if (getC_UOM_ID() == 0 + && (getM_Product_ID() != 0 + || getPriceEntered().compareTo(Env.ZERO) != 0 + || getC_Charge_ID() != 0)) + { + int C_UOM_ID = MUOM.getDefault_UOM_ID(getCtx()); + if (C_UOM_ID > 0) + setC_UOM_ID (C_UOM_ID); + } + // Qty Precision + if (newRecord || is_ValueChanged("QtyEntered")) + setQtyEntered(getQtyEntered()); + if (newRecord || is_ValueChanged("QtyOrdered")) + setQtyOrdered(getQtyOrdered()); + + // Qty on instance ASI for SO + if (m_IsSOTrx + && getM_AttributeSetInstance_ID() != 0 + && (newRecord || is_ValueChanged("M_Product_ID") + || is_ValueChanged("M_AttributeSetInstance_ID") + || is_ValueChanged("M_Warehouse_ID"))) + { + MProduct product = getProduct(); + int M_AttributeSet_ID = product.getM_AttributeSet_ID(); + boolean isInstance = M_AttributeSet_ID != 0; + if (isInstance) + { + MAttributeSet mas = MAttributeSet.get(getCtx(), M_AttributeSet_ID); + isInstance = mas.isInstanceAttribute(); + } + // Max + if (isInstance) + { + MStorage[] storages = MStorage.getWarehouse(getCtx(), + getM_Warehouse_ID(), getM_Product_ID(), getM_AttributeSetInstance_ID(), + M_AttributeSet_ID, false, null, true, get_TrxName()); + BigDecimal qty = Env.ZERO; + for (int i = 0; i < storages.length; i++) + { + if (storages[i].getM_AttributeSetInstance_ID() == getM_AttributeSetInstance_ID()) + qty = qty.add(storages[i].getQtyOnHand()); + } + if (getQtyOrdered().compareTo(qty) > 0) + { + log.warning("Qty - Stock=" + qty + ", Ordered=" + getQtyOrdered()); + log.saveError("QtyInsufficient", "=" + qty); + return false; + } + } + } + + // FreightAmt Not used + if (Env.ZERO.compareTo(getFreightAmt()) != 0) + setFreightAmt(Env.ZERO); + + // Set Tax + if (getC_Tax_ID() == 0) + setTax(); + + // Get Line No + if (getLine() == 0) + { + String sql = "SELECT COALESCE(MAX(Line),0)+10 FROM C_OrderLine WHERE C_Order_ID=?"; + int ii = DB.getSQLValue (get_TrxName(), sql, getC_Order_ID()); + setLine (ii); + } + + // Calculations & Rounding + setLineNetAmt(); // extended Amount with or without tax + setDiscount(); + + return true; + } // beforeSave + + + /** + * Before Delete + * @return true if it can be deleted + */ + protected boolean beforeDelete () + { + // R/O Check - Something delivered. etc. + if (Env.ZERO.compareTo(getQtyDelivered()) != 0) + { + log.saveError("DeleteError", Msg.translate(getCtx(), "QtyDelivered") + "=" + getQtyDelivered()); + return false; + } + if (Env.ZERO.compareTo(getQtyInvoiced()) != 0) + { + log.saveError("DeleteError", Msg.translate(getCtx(), "QtyInvoiced") + "=" + getQtyInvoiced()); + return false; + } + if (Env.ZERO.compareTo(getQtyReserved()) != 0) + { + // For PO should be On Order + log.saveError("DeleteError", Msg.translate(getCtx(), "QtyReserved") + "=" + getQtyReserved()); + return false; + } + + return true; + } // beforeDelete + + /** + * After Save + * @param newRecord new + * @param success success + * @return saved + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + if (!newRecord && is_ValueChanged("C_Tax_ID")) + { + // Recalculate Tax for old Tax + MOrderTax tax = MOrderTax.get (this, getPrecision(), + true, get_TrxName()); // old Tax + if (tax != null) + { + if (!tax.calculateTaxFromLines()) + return false; + if (!tax.save(get_TrxName())) + return false; + } + } + return updateHeaderTax(); + } // afterSave + + /** + * After Delete + * @param success success + * @return deleted + */ + protected boolean afterDelete (boolean success) + { + if (!success) + return success; + if (getS_ResourceAssignment_ID() != 0) + { + MResourceAssignment ra = new MResourceAssignment(getCtx(), getS_ResourceAssignment_ID(), get_TrxName()); + ra.delete(true); + } + + return updateHeaderTax(); + } // afterDelete + + /** + * Update Tax & Header + * @return true if header updated + */ + private boolean updateHeaderTax() + { + // Recalculate Tax for this Tax + MOrderTax tax = MOrderTax.get (this, getPrecision(), + false, get_TrxName()); // current Tax + if (!tax.calculateTaxFromLines()) + return false; + if (!tax.save(get_TrxName())) + return false; + + // Update Order Header + String sql = "UPDATE C_Order i" + + " SET TotalLines=" + + "(SELECT COALESCE(SUM(LineNetAmt),0) FROM C_OrderLine il WHERE i.C_Order_ID=il.C_Order_ID) " + + "WHERE C_Order_ID=" + getC_Order_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + if (no != 1) + log.warning("(1) #" + no); + + if (isTaxIncluded()) + sql = "UPDATE C_Order i " + + " SET GrandTotal=TotalLines " + + "WHERE C_Order_ID=" + getC_Order_ID(); + else + sql = "UPDATE C_Order i " + + " SET GrandTotal=TotalLines+" + + "(SELECT COALESCE(SUM(TaxAmt),0) FROM C_OrderTax it WHERE i.C_Order_ID=it.C_Order_ID) " + + "WHERE C_Order_ID=" + getC_Order_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 1) + log.warning("(2) #" + no); + m_parent = null; + return no == 1; + } // updateHeaderTax + +} // MOrderLine diff --git a/base/src/org/compiere/model/MOrderTax.java b/base/src/org/compiere/model/MOrderTax.java new file mode 100644 index 0000000000..d00fc5df14 --- /dev/null +++ b/base/src/org/compiere/model/MOrderTax.java @@ -0,0 +1,263 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Order Tax Model + * + * @author Jorg Janke + * @version $Id: MOrderTax.java,v 1.4 2006/07/30 00:51:04 jjanke Exp $ + */ +public class MOrderTax extends X_C_OrderTax +{ + /** + * Get Tax Line for Order Line + * @param line Order line + * @param precision currenct precision + * @param oldTax get old tax + * @param trxName transaction + * @return existing or new tax + */ + public static MOrderTax get (MOrderLine line, int precision, + boolean oldTax, String trxName) + { + MOrderTax retValue = null; + if (line == null || line.getC_Order_ID() == 0) + { + s_log.fine("No Order"); + return null; + } + int C_Tax_ID = line.getC_Tax_ID(); + if (oldTax && line.is_ValueChanged("C_Tax_ID")) + { + Object old = line.get_ValueOld("C_Tax_ID"); + if (old == null) + { + s_log.fine("No Old Tax"); + return null; + } + C_Tax_ID = ((Integer)old).intValue(); + } + if (C_Tax_ID == 0) + { + s_log.fine("No Tax"); + return null; + } + + String sql = "SELECT * FROM C_OrderTax WHERE C_Order_ID=? AND C_Tax_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, line.getC_Order_ID()); + pstmt.setInt (2, C_Tax_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = new MOrderTax (line.getCtx(), rs, trxName); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (retValue != null) + { + retValue.setPrecision(precision); + retValue.set_TrxName(trxName); + s_log.fine("(old=" + oldTax + ") " + retValue); + return retValue; + } + + // Create New + retValue = new MOrderTax(line.getCtx(), 0, trxName); + retValue.set_TrxName(trxName); + retValue.setClientOrg(line); + retValue.setC_Order_ID(line.getC_Order_ID()); + retValue.setC_Tax_ID(line.getC_Tax_ID()); + retValue.setPrecision(precision); + retValue.setIsTaxIncluded(line.isTaxIncluded()); + s_log.fine("(new) " + retValue); + return retValue; + } // get + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MOrderTax.class); + + + /************************************************************************** + * Persistency Constructor + * @param ctx context + * @param ignored ignored + * @param trxName transaction + */ + public MOrderTax (Properties ctx, int ignored, String trxName) + { + super(ctx, 0, trxName); + if (ignored != 0) + throw new IllegalArgumentException("Multi-Key"); + setTaxAmt (Env.ZERO); + setTaxBaseAmt (Env.ZERO); + setIsTaxIncluded(false); + } // MOrderTax + + /** + * Load Constructor. + * Set Precision and TaxIncluded for tax calculations! + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MOrderTax (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MOrderTax + + /** Tax */ + private MTax m_tax = null; + /** Cached Precision */ + private Integer m_precision = null; + + /** + * Get Precision + * @return Returns the precision or 2 + */ + private int getPrecision () + { + if (m_precision == null) + return 2; + return m_precision.intValue(); + } // getPrecision + + /** + * Set Precision + * @param precision The precision to set. + */ + protected void setPrecision (int precision) + { + m_precision = new Integer(precision); + } // setPrecision + + /** + * Get Tax + * @return tax + */ + protected MTax getTax() + { + if (m_tax == null) + m_tax = MTax.get(getCtx(), getC_Tax_ID()); + return m_tax; + } // getTax + + + /************************************************************************** + * Calculate/Set Tax Amt from Order Lines + * @return true if aclculated + */ + public boolean calculateTaxFromLines () + { + BigDecimal taxBaseAmt = Env.ZERO; + BigDecimal taxAmt = Env.ZERO; + // + boolean documentLevel = getTax().isDocumentLevel(); + MTax tax = getTax(); + // + String sql = "SELECT LineNetAmt FROM C_OrderLine WHERE C_Order_ID=? AND C_Tax_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_Order_ID()); + pstmt.setInt (2, getC_Tax_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + BigDecimal baseAmt = rs.getBigDecimal(1); + taxBaseAmt = taxBaseAmt.add(baseAmt); + // + if (!documentLevel) // calculate line tax + taxAmt = taxAmt.add(tax.calculateTax(baseAmt, isTaxIncluded(), getPrecision())); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, get_TrxName(), e); + taxBaseAmt = null; + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + if (taxBaseAmt == null) + return false; + + // Calculate Tax + if (documentLevel) // document level + taxAmt = tax.calculateTax(taxBaseAmt, isTaxIncluded(), getPrecision()); + setTaxAmt(taxAmt); + + // Set Base + if (isTaxIncluded()) + setTaxBaseAmt (taxBaseAmt.subtract(taxAmt)); + else + setTaxBaseAmt (taxBaseAmt); + log.fine(toString()); + return true; + } // calculateTaxFromLines + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MOrderTax["); + sb.append("C_Order_ID=").append(getC_Order_ID()) + .append(",C_Tax_ID=").append(getC_Tax_ID()) + .append(", Base=").append(getTaxBaseAmt()).append(",Tax=").append(getTaxAmt()) + .append ("]"); + return sb.toString (); + } // toString + +} // MOrderTax diff --git a/base/src/org/compiere/model/MPOS.java b/base/src/org/compiere/model/MPOS.java new file mode 100644 index 0000000000..d4d9ca797b --- /dev/null +++ b/base/src/org/compiere/model/MPOS.java @@ -0,0 +1,134 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + + +/** + * POS Terminal definition + * + * @author Jorg Janke + * @version $Id: MPOS.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MPOS extends X_C_POS +{ + /** + * Get POS from Cache + * @param ctx context + * @param C_POS_ID id + * @return MPOS + */ + public static MPOS get (Properties ctx, int C_POS_ID) + { + Integer key = new Integer (C_POS_ID); + MPOS retValue = (MPOS) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MPOS (ctx, C_POS_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("C_POS", 20); + + /** + * Standard Constructor + * @param ctx context + * @param C_POS_ID id + * @param trxName transaction + */ + public MPOS (Properties ctx, int C_POS_ID, String trxName) + { + super (ctx, C_POS_ID, trxName); + if (C_POS_ID == 0) + { + // setName (null); + // setSalesRep_ID (0); + // setC_CashBook_ID (0); + // setM_PriceList_ID (0); + setIsModifyPrice (false); // N + // setM_Warehouse_ID (0); + } + } // MPOS + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPOS (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPOS + + /** Cash Business Partner */ + private MBPartner m_template = null; + + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Org Consistency + if (newRecord + || is_ValueChanged("C_CashBook_ID") || is_ValueChanged("M_Warehouse_ID")) + { + MCashBook cb = MCashBook.get(getCtx(), getC_CashBook_ID()); + if (cb.getAD_Org_ID() != getAD_Org_ID()) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@AD_Org_ID@: @C_CashBook_ID@")); + return false; + } + MWarehouse wh = MWarehouse.get(getCtx(), getM_Warehouse_ID()); + if (wh.getAD_Org_ID() != getAD_Org_ID()) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@AD_Org_ID@: @M_Warehouse_ID@")); + return false; + } + } + return true; + } // beforeSave + + + /** + * Get default Cash BPartner + * @return BPartner + */ + public MBPartner getBPartner() + { + if (m_template == null) + { + if (getC_BPartnerCashTrx_ID() == 0) + m_template = MBPartner.getBPartnerCashTrx (getCtx(), getAD_Client_ID()); + else + m_template = new MBPartner(getCtx(), getC_BPartnerCashTrx_ID(), get_TrxName()); + log.fine("getBPartner - " + m_template); + } + return m_template; + } // getBPartner + +} // MPOS diff --git a/base/src/org/compiere/model/MPOSKey.java b/base/src/org/compiere/model/MPOSKey.java new file mode 100644 index 0000000000..a2656b3e2c --- /dev/null +++ b/base/src/org/compiere/model/MPOSKey.java @@ -0,0 +1,54 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * POS Function Key Model + * + * @author Jorg Janke + * @version $Id: MPOSKey.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MPOSKey extends X_C_POSKey +{ + + /** + * Standard Constructor + * @param ctx context + * @param C_POSKey_ID id + * @param trxName transaction + */ + public MPOSKey (Properties ctx, int C_POSKey_ID, String trxName) + { + super (ctx, C_POSKey_ID, trxName); + } // MPOSKey + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPOSKey (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPOSKey + +} // MPOSKey diff --git a/base/src/org/compiere/model/MPOSKeyLayout.java b/base/src/org/compiere/model/MPOSKeyLayout.java new file mode 100644 index 0000000000..5a4a4434b0 --- /dev/null +++ b/base/src/org/compiere/model/MPOSKeyLayout.java @@ -0,0 +1,132 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * POS Function Key Layout + * + * @author Jorg Janke + * @version $Id: MPOSKeyLayout.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MPOSKeyLayout extends X_C_POSKeyLayout +{ + /** + * Get POS Key Layout from Cache + * @param ctx context + * @param C_POSKeyLayout_ID id + * @return MPOSKeyLayout + */ + public static MPOSKeyLayout get (Properties ctx, int C_POSKeyLayout_ID) + { + Integer key = new Integer (C_POSKeyLayout_ID); + MPOSKeyLayout retValue = (MPOSKeyLayout) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MPOSKeyLayout (ctx, C_POSKeyLayout_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("C_POSKeyLayout", 3); + + /** + * Standard Constructor + * @param ctx context + * @param C_POSKeyLayout_ID id + * @param trxName transaction + */ + public MPOSKeyLayout (Properties ctx, int C_POSKeyLayout_ID, String trxName) + { + super (ctx, C_POSKeyLayout_ID, trxName); + } // MPOSKeyLayout + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPOSKeyLayout (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPOSKeyLayout + + /** Keys */ + private MPOSKey[] m_keys = null; + + /** + * Get Keys + * @param requery requery + * @return keys + */ + public MPOSKey[] getKeys (boolean requery) + { + if (m_keys != null && !requery) + return m_keys; + + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_POSKey WHERE C_POSKeyLayout_ID=? ORDER BY SeqNo"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_POSKeyLayout_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MPOSKey(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + m_keys = new MPOSKey[list.size ()]; + list.toArray (m_keys); + return m_keys; + } // getKeys + + /** + * Get Number of Keys + * @return keys + */ + public int getNoOfKeys() + { + return getKeys(false).length; + } // getNoOfKeys + +} // MPOSKeyLayout + diff --git a/base/src/org/compiere/model/MPackage.java b/base/src/org/compiere/model/MPackage.java new file mode 100644 index 0000000000..dc68f83da6 --- /dev/null +++ b/base/src/org/compiere/model/MPackage.java @@ -0,0 +1,100 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Package Model + * + * @author Jorg Janke + * @version $Id: MPackage.java,v 1.3 2006/07/30 00:51:04 jjanke Exp $ + */ +public class MPackage extends X_M_Package +{ + /** + * Create one Package for Shipment + * @param shipment shipment + * @param shipper shipper + * @param shipDate null for today + * @return package + */ + public static MPackage create (MInOut shipment, MShipper shipper, Timestamp shipDate) + { + MPackage retValue = new MPackage (shipment, shipper); + if (shipDate != null) + retValue.setShipDate(shipDate); + retValue.save(); + // Lines + MInOutLine[] lines = shipment.getLines(false); + for (int i = 0; i < lines.length; i++) + { + MInOutLine sLine = lines[i]; + MPackageLine pLine = new MPackageLine (retValue); + pLine.setInOutLine(sLine); + pLine.save(); + } // lines + return retValue; + } // create + + + + /************************************************************************** + * MPackage + * @param ctx context + * @param M_Package_ID id + * @param trxName transaction + */ + public MPackage (Properties ctx, int M_Package_ID, String trxName) + { + super (ctx, M_Package_ID, trxName); + if (M_Package_ID == 0) + { + // setM_Shipper_ID (0); + // setDocumentNo (null); + // setM_InOut_ID (0); + setShipDate (new Timestamp(System.currentTimeMillis())); + } + } // MPackage + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPackage (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPackage + + /** + * Shipment Constructor + * @param shipment shipment + * @param shipper shipper + */ + public MPackage (MInOut shipment, MShipper shipper) + { + this (shipment.getCtx(), 0, shipment.get_TrxName()); + setClientOrg(shipment); + setM_InOut_ID(shipment.getM_InOut_ID()); + setM_Shipper_ID(shipper.getM_Shipper_ID()); + } // MPackage + +} // MPackage diff --git a/base/src/org/compiere/model/MPackageLine.java b/base/src/org/compiere/model/MPackageLine.java new file mode 100644 index 0000000000..e62f4b1662 --- /dev/null +++ b/base/src/org/compiere/model/MPackageLine.java @@ -0,0 +1,80 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Package Line Model + * + * @author Jorg Janke + * @version $Id: MPackageLine.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MPackageLine extends X_M_PackageLine +{ + /** + * Standard Constructor + * @param ctx context + * @param M_PackageLine_ID id + * @param trxName transaction + */ + public MPackageLine (Properties ctx, int M_PackageLine_ID, String trxName) + { + super (ctx, M_PackageLine_ID, trxName); + if (M_PackageLine_ID == 0) + { + // setM_Package_ID (0); + // setM_InOutLine_ID (0); + setQty (Env.ZERO); + } + } // MPackageLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPackageLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPackageLine + + /** + * Parent Constructor + * @param parent header + */ + public MPackageLine (MPackage parent) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setM_Package_ID(parent.getM_Package_ID()); + } // MPackageLine + + /** + * Set Shipment Line + * @param line line + */ + public void setInOutLine (MInOutLine line) + { + setM_InOutLine_ID (line.getM_InOutLine_ID()); + setQty (line.getMovementQty()); + } // setInOutLine + +} // MPackageLine diff --git a/base/src/org/compiere/model/MPaySchedule.java b/base/src/org/compiere/model/MPaySchedule.java new file mode 100644 index 0000000000..f8c1baaf94 --- /dev/null +++ b/base/src/org/compiere/model/MPaySchedule.java @@ -0,0 +1,117 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Payment Term Schedule Model + * + * @author Jorg Janke + * @version $Id: MPaySchedule.java,v 1.3 2006/07/30 00:51:04 jjanke Exp $ + */ +public class MPaySchedule extends X_C_PaySchedule +{ + /** + * Standard Constructor + * @param ctx context + * @param C_PaySchedule_ID id + * @param trxName transaction + */ + public MPaySchedule(Properties ctx, int C_PaySchedule_ID, String trxName) + { + super(ctx, C_PaySchedule_ID, trxName); + if (C_PaySchedule_ID == 0) + { + // setC_PaymentTerm_ID (0); // Parent + setPercentage (Env.ZERO); + setDiscount (Env.ZERO); + setDiscountDays (0); + setGraceDays (0); + setNetDays (0); + setIsValid (false); + } + } // MPaySchedule + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPaySchedule(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPaySchedule + + /** Parent */ + public MPaymentTerm m_parent = null; + + /** + * @return Returns the parent. + */ + public MPaymentTerm getParent () + { + if (m_parent == null) + m_parent = new MPaymentTerm (getCtx(), getC_PaymentTerm_ID(), get_TrxName()); + return m_parent; + } // getParent + + /** + * @param parent The parent to set. + */ + public void setParent (MPaymentTerm parent) + { + m_parent = parent; + } // setParent + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (is_ValueChanged("Percentage")) + { + log.fine("beforeSave"); + setIsValid(false); + } + return true; + } // beforeSave + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (newRecord || is_ValueChanged("Percentage")) + { + log.fine("afterSave"); + getParent(); + m_parent.validate(); + m_parent.save(); + } + return success; + } // afterSave + +} // MPaySchedule diff --git a/base/src/org/compiere/model/MPaySelection.java b/base/src/org/compiere/model/MPaySelection.java new file mode 100644 index 0000000000..1745f4b015 --- /dev/null +++ b/base/src/org/compiere/model/MPaySelection.java @@ -0,0 +1,142 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * AP Payment Selection + * + * @author Jorg Janke + * @version $Id: MPaySelection.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MPaySelection extends X_C_PaySelection +{ + /** + * Default Constructor + * @param ctx context + * @param C_PaySelection_ID id + * @param trxName transaction + */ + public MPaySelection (Properties ctx, int C_PaySelection_ID, String trxName) + { + super(ctx, C_PaySelection_ID, trxName); + if (C_PaySelection_ID == 0) + { + // setC_BankAccount_ID (0); + // setName (null); // @#Date@ + // setPayDate (new Timestamp(System.currentTimeMillis())); // @#Date@ + setTotalAmt (Env.ZERO); + setIsApproved (false); + setProcessed (false); + setProcessing (false); + } + } // MPaySelection + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPaySelection(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPaySelection + + /** Lines */ + private MPaySelectionLine[] m_lines = null; + /** Currency of Bank Account */ + private int m_C_Currency_ID = 0; + + /** + * Get Lines + * @param requery requery + * @return lines + */ + public MPaySelectionLine[] getLines(boolean requery) + { + if (m_lines != null && !requery) + return m_lines; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_PaySelectionLine WHERE C_PaySelection_ID=? ORDER BY Line"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_PaySelection_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MPaySelectionLine(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getLines", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + m_lines = new MPaySelectionLine[list.size ()]; + list.toArray (m_lines); + return m_lines; + } // getLines + + /** + * Get Currency of Bank Account + * @return C_Currency_ID + */ + public int getC_Currency_ID() + { + if (m_C_Currency_ID == 0) + { + String sql = "SELECT C_Currency_ID FROM C_BankAccount " + + "WHERE C_BankAccount_ID=?"; + m_C_Currency_ID = DB.getSQLValue(null, sql, getC_BankAccount_ID()); + } + return m_C_Currency_ID; + } // getC_Currency_ID + + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("MPaySelection["); + sb.append(get_ID()).append(",").append(getName()) + .append("]"); + return sb.toString(); + } // toString + + + +} // MPaySelection diff --git a/base/src/org/compiere/model/MPaySelectionCheck.java b/base/src/org/compiere/model/MPaySelectionCheck.java new file mode 100644 index 0000000000..bf2f282560 --- /dev/null +++ b/base/src/org/compiere/model/MPaySelectionCheck.java @@ -0,0 +1,683 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Payment Print/Export model. + * + * @author Jorg Janke + * @version $Id: MPaySelectionCheck.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public final class MPaySelectionCheck extends X_C_PaySelectionCheck +{ + /** + * Get Check for Payment + * @param ctx context + * @param C_Payment_ID id + * @param trxName transaction + * @return pay selection check for payment or null + */ + public static MPaySelectionCheck getOfPayment (Properties ctx, int C_Payment_ID, String trxName) + { + MPaySelectionCheck retValue = null; + String sql = "SELECT * FROM C_PaySelectionCheck WHERE C_Payment_ID=?"; + int count = 0; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, C_Payment_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MPaySelectionCheck psc = new MPaySelectionCheck (ctx, rs, trxName); + if (retValue == null) + retValue = psc; + else if (!retValue.isProcessed() && psc.isProcessed()) + retValue = psc; + count++; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (count > 1) + s_log.warning ("More then one for C_Payment_ID=" + C_Payment_ID); + return retValue; + } // getOfPayment + + /** + * Create Check for Payment + * @param ctx context + * @param C_Payment_ID id + * @param trxName transaction + * @return pay selection check for payment or null + */ + public static MPaySelectionCheck createForPayment (Properties ctx, int C_Payment_ID, String trxName) + { + if (C_Payment_ID == 0) + return null; + MPayment payment = new MPayment (ctx, C_Payment_ID, null); + // Map Payment Rule <- Tender Type + String PaymentRule = PAYMENTRULE_Check; + if (payment.getTenderType().equals(X_C_Payment.TENDERTYPE_CreditCard)) + PaymentRule = PAYMENTRULE_CreditCard; + else if (payment.getTenderType().equals(X_C_Payment.TENDERTYPE_DirectDebit)) + PaymentRule = PAYMENTRULE_DirectDebit; + else if (payment.getTenderType().equals(X_C_Payment.TENDERTYPE_DirectDeposit)) + PaymentRule = PAYMENTRULE_DirectDeposit; + // else if (payment.getTenderType().equals(MPayment.TENDERTYPE_Check)) + // PaymentRule = MPaySelectionCheck.PAYMENTRULE_Check; + + // Create new PaySelection + MPaySelection ps = new MPaySelection(ctx, 0, trxName); + ps.setC_BankAccount_ID (payment.getC_BankAccount_ID()); + ps.setName (Msg.translate(ctx, "C_Payment_ID") + ": " + payment.getDocumentNo()); + ps.setDescription(payment.getDescription()); + ps.setPayDate (payment.getDateTrx()); + ps.setTotalAmt (payment.getPayAmt()); + ps.setIsApproved (true); + ps.save(); + + // Create new PaySelection Line + MPaySelectionLine psl = null; + if (payment.getC_Invoice_ID() != 0) + { + psl = new MPaySelectionLine (ps, 10, PaymentRule); + psl.setC_Invoice_ID(payment.getC_Invoice_ID()); + psl.setIsSOTrx (payment.isReceipt()); + psl.setOpenAmt(payment.getPayAmt().add(payment.getDiscountAmt())); + psl.setPayAmt (payment.getPayAmt()); + psl.setDiscountAmt(payment.getDiscountAmt()); + psl.setDifferenceAmt (Env.ZERO); + psl.save(); + } + + // Create new PaySelection Check + MPaySelectionCheck psc = new MPaySelectionCheck(ps, PaymentRule); + psc.setC_BPartner_ID (payment.getC_BPartner_ID()); + psc.setC_Payment_ID(payment.getC_Payment_ID()); + psc.setIsReceipt(payment.isReceipt()); + psc.setPayAmt (payment.getPayAmt()); + psc.setDiscountAmt(payment.getDiscountAmt()); + psc.setQty (1); + psc.setDocumentNo(payment.getDocumentNo()); + psc.setProcessed(true); + psc.save(); + + // Update optional Line + if (psl != null) + { + psl.setC_PaySelectionCheck_ID(psc.getC_PaySelectionCheck_ID()); + psl.setProcessed(true); + psl.save(); + } + + // Indicate Done + ps.setProcessed(true); + ps.save(); + return psc; + } // createForPayment + + + /************************************************************************** + * Get Checks of Payment Selection + * + * @param C_PaySelection_ID Payment Selection + * @param PaymentRule Payment Rule + * @param startDocumentNo start document no + * @param trxName transaction + * @return array of checks + */ + static public MPaySelectionCheck[] get (int C_PaySelection_ID, + String PaymentRule, int startDocumentNo, String trxName) + { + s_log.fine("C_PaySelection_ID=" + C_PaySelection_ID + + ", PaymentRule=" + PaymentRule + ", startDocumentNo=" + startDocumentNo); + ArrayList list = new ArrayList(); + + int docNo = startDocumentNo; + String sql = "SELECT * FROM C_PaySelectionCheck " + + "WHERE C_PaySelection_ID=? AND PaymentRule=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, C_PaySelection_ID); + pstmt.setString(2, PaymentRule); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + MPaySelectionCheck check = new MPaySelectionCheck (Env.getCtx(), rs, trxName); + // Set new Check Document No - saved in confirmPrint + check.setDocumentNo(String.valueOf(docNo++)); + list.add(check); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + s_log.log(Level.SEVERE, sql, e); + } + + // convert to Array + MPaySelectionCheck[] retValue = new MPaySelectionCheck[list.size()]; + list.toArray(retValue); + return retValue; + } // createPayments + + + /************************************************************************** + * Export to File + * @param checks array of checks + * @param file file to export checks + * @return number of lines + */ + public static int exportToFile (MPaySelectionCheck[] checks, File file) + { + if (checks == null || checks.length == 0) + return 0; + // Must be a file + if (file.isDirectory()) + { + s_log.log(Level.SEVERE, "exportToFile - file is directory - " + file.getAbsolutePath()); + return 0; + } + // delete if exists + try + { + if (file.exists()) + file.delete(); + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "exportToFile - could not delete - " + file.getAbsolutePath(), e); + } + + char x = '"'; // ease + int noLines = 0; + StringBuffer line = null; + try + { + FileWriter fw = new FileWriter(file); + + // write header + line = new StringBuffer(); + line.append(x).append("Value").append(x).append(",") + .append(x).append("Name").append(x).append(",") + .append(x).append("Contact").append(x).append(",") + .append(x).append("Addr1").append(x).append(",") + .append(x).append("Addr2").append(x).append(",") + .append(x).append("City").append(x).append(",") + .append(x).append("State").append(x).append(",") + .append(x).append("ZIP").append(x).append(",") + .append(x).append("Country").append(x).append(",") + .append(x).append("ReferenceNo").append(x).append(",") + .append(x).append("DocumentNo").append(x).append(",") + .append(x).append("PayDate").append(x).append(",") + .append(x).append("Currency").append(x).append(",") + .append(x).append("PayAmount").append(x).append(",") + .append(x).append("Comment").append(x) + .append(Env.NL); + fw.write(line.toString()); + noLines++; + + // write lines + for (int i = 0; i < checks.length; i++) + { + MPaySelectionCheck mpp = checks[i]; + if (mpp == null) + continue; + // BPartner Info + String bp[] = getBPartnerInfo(mpp.getC_BPartner_ID()); + + // Comment - list of invoice document no + StringBuffer comment = new StringBuffer(); + MPaySelectionLine[] psls = mpp.getPaySelectionLines(false); + for (int l = 0; l < psls.length; l++) + { + if (l > 0) + comment.append(", "); + comment.append(psls[l].getInvoice().getDocumentNo()); + } + line = new StringBuffer(); + line.append(x).append(bp[BP_VALUE]).append(x).append(",") // Value + .append(x).append(bp[BP_NAME]).append(x).append(",") // Name + .append(x).append(bp[BP_CONTACT]).append(x).append(",") // Contact + .append(x).append(bp[BP_ADDR1]).append(x).append(",") // Addr1 + .append(x).append(bp[BP_ADDR2]).append(x).append(",") // Addr2 + .append(x).append(bp[BP_CITY]).append(x).append(",") // City + .append(x).append(bp[BP_REGION]).append(x).append(",") // State + .append(x).append(bp[BP_POSTAL]).append(x).append(",") // ZIP + .append(x).append(bp[BP_COUNTRY]).append(x).append(",") // Country + .append(x).append(bp[BP_REFNO]).append(x).append(",") // ReferenceNo + // Payment Info + .append(x).append(mpp.getDocumentNo()).append(x).append(",") // DocumentNo + .append(mpp.getParent().getPayDate()).append(",") // PayDate + .append(x).append(MCurrency.getISO_Code(Env.getCtx(), mpp.getParent().getC_Currency_ID())).append(x).append(",") // Currency + .append(mpp.getPayAmt()).append(",") // PayAmount + .append(x).append(comment.toString()).append(x) // Comment + .append(Env.NL); + fw.write(line.toString()); + noLines++; + } // write line + + fw.flush(); + fw.close(); + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "", e); + } + + return noLines; + } // exportToFile + + + /** + * Get Customer/Vendor Info. + * Based on BP_ static variables + * @param C_BPartner_ID BPartner + * @return info array + */ + private static String[] getBPartnerInfo (int C_BPartner_ID) + { + String[] bp = new String[10]; + + String sql = "SELECT bp.Value, bp.Name, c.Name AS Contact, " + + "a.Address1, a.Address2, a.City, r.Name AS Region, a.Postal, " + + "cc.Name AS Country, bp.ReferenceNo " + + "FROM C_BPartner bp, AD_User c, C_BPartner_Location l, C_Location a, C_Region r, C_Country cc " + + "WHERE bp.C_BPartner_ID=?" // #1 + + " AND bp.C_BPartner_ID=c.C_BPartner_ID(+)" + + " AND bp.C_BPartner_ID=l.C_BPartner_ID" + + " AND l.C_Location_ID=a.C_Location_ID" + + " AND a.C_Region_ID=r.C_Region_ID(+)" + + " AND a.C_Country_ID=cc.C_Country_ID " + + "ORDER BY l.IsBillTo DESC"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_BPartner_ID); + ResultSet rs = pstmt.executeQuery(); + // + if (rs.next()) + { + bp[BP_VALUE] = rs.getString(1); + if (bp[BP_VALUE] == null) + bp[BP_VALUE] = ""; + bp[BP_NAME] = rs.getString(2); + if (bp[BP_NAME] == null) + bp[BP_NAME] = ""; + bp[BP_CONTACT] = rs.getString(3); + if (bp[BP_CONTACT] == null) + bp[BP_CONTACT] = ""; + bp[BP_ADDR1] = rs.getString(4); + if (bp[BP_ADDR1] == null) + bp[BP_ADDR1] = ""; + bp[BP_ADDR2] = rs.getString(5); + if (bp[BP_ADDR2] == null) + bp[BP_ADDR2] = ""; + bp[BP_CITY] = rs.getString(6); + if (bp[BP_CITY] == null) + bp[BP_CITY] = ""; + bp[BP_REGION] = rs.getString(7); + if (bp[BP_REGION] == null) + bp[BP_REGION] = ""; + bp[BP_POSTAL] = rs.getString(8); + if (bp[BP_POSTAL] == null) + bp[BP_POSTAL] = ""; + bp[BP_COUNTRY] = rs.getString(9); + if (bp[BP_COUNTRY] == null) + bp[BP_COUNTRY] = ""; + bp[BP_REFNO] = rs.getString(10); + if (bp[BP_REFNO] == null) + bp[BP_REFNO] = ""; + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + s_log.log(Level.SEVERE, "getBPartnerInfo", e); + } + return bp; + } // getBPartnerInfo + + + /************************************************************************** + * Confirm Print. + * Create Payments the first time + * @param checks checks + * @param batch batch + * @return last Document number or 0 if nothing printed + */ + public static int confirmPrint (MPaySelectionCheck[] checks, MPaymentBatch batch) + { + int lastDocumentNo = 0; + for (int i = 0; i < checks.length; i++) + { + MPaySelectionCheck check = checks[i]; + MPayment payment = new MPayment(check.getCtx(), check.getC_Payment_ID(), null); + // Existing Payment + if (check.getC_Payment_ID() != 0) + { + // Update check number + if (check.getPaymentRule().equals(PAYMENTRULE_Check)) + { + payment.setCheckNo(check.getDocumentNo()); + if (!payment.save()) + s_log.log(Level.SEVERE, "Payment not saved: " + payment); + } + } + else // New Payment + { + payment = new MPayment(check.getCtx(), 0, null); + payment.setAD_Org_ID(check.getAD_Org_ID()); + // + if (check.getPaymentRule().equals(PAYMENTRULE_Check)) + payment.setBankCheck (check.getParent().getC_BankAccount_ID(), false, check.getDocumentNo()); + else if (check.getPaymentRule().equals(PAYMENTRULE_CreditCard)) + payment.setTenderType(X_C_Payment.TENDERTYPE_CreditCard); + else if (check.getPaymentRule().equals(PAYMENTRULE_DirectDeposit) + || check.getPaymentRule().equals(PAYMENTRULE_DirectDeposit)) + payment.setBankACH(check.getParent().getC_BankAccount_ID(), false); + else + { + s_log.log(Level.SEVERE, "Unsupported Payment Rule=" + check.getPaymentRule()); + continue; + } + payment.setTrxType(X_C_Payment.TRXTYPE_CreditPayment); + payment.setAmount(check.getParent().getC_Currency_ID(), check.getPayAmt()); + payment.setDiscountAmt(check.getDiscountAmt()); + payment.setDateTrx(check.getParent().getPayDate()); + payment.setC_BPartner_ID(check.getC_BPartner_ID()); + // Link to Batch + if (batch != null) + { + if (batch.getC_PaymentBatch_ID() == 0) + batch.save(); // new + payment.setC_PaymentBatch_ID(batch.getC_PaymentBatch_ID()); + } + // Link to Invoice + MPaySelectionLine[] psls = check.getPaySelectionLines(false); + s_log.fine("confirmPrint - " + check + " (#SelectionLines=" + psls.length + ")"); + if (check.getQty() == 1 && psls != null && psls.length == 1) + { + MPaySelectionLine psl = psls[0]; + s_log.fine("Map to Invoice " + psl); + // + payment.setC_Invoice_ID (psl.getC_Invoice_ID()); + payment.setDiscountAmt (psl.getDiscountAmt()); + payment.setWriteOffAmt(psl.getDifferenceAmt()); + BigDecimal overUnder = psl.getOpenAmt().subtract(psl.getPayAmt()) + .subtract(psl.getDiscountAmt()).subtract(psl.getDifferenceAmt()); + payment.setOverUnderAmt(overUnder); + } + else + payment.setDiscountAmt(Env.ZERO); + payment.setWriteOffAmt(Env.ZERO); + if (!payment.save()) + s_log.log(Level.SEVERE, "Payment not saved: " + payment); + // + int C_Payment_ID = payment.get_ID(); + if (C_Payment_ID < 1) + s_log.log(Level.SEVERE, "Payment not created=" + check); + else + { + check.setC_Payment_ID (C_Payment_ID); + check.save(); // Payment process needs it + // Should start WF + payment.processIt(DocAction.ACTION_Complete); + if (!payment.save()) + s_log.log(Level.SEVERE, "Payment not saved: " + payment); + } + } // new Payment + + // Get Check Document No + try + { + int no = Integer.parseInt(check.getDocumentNo()); + if (lastDocumentNo < no) + lastDocumentNo = no; + } + catch (NumberFormatException ex) + { + s_log.log(Level.SEVERE, "DocumentNo=" + check.getDocumentNo(), ex); + } + check.setIsPrinted(true); + check.setProcessed(true); + if (!check.save ()) + s_log.log(Level.SEVERE, "Check not saved: " + check); + } // all checks + + s_log.fine("Last Document No = " + lastDocumentNo); + return lastDocumentNo; + } // confirmPrint + + /** Logger */ + static private CLogger s_log = CLogger.getCLogger (MPaySelectionCheck.class); + + /** BPartner Info Index for Value */ + private static final int BP_VALUE = 0; + /** BPartner Info Index for Name */ + private static final int BP_NAME = 1; + /** BPartner Info Index for Contact Name */ + private static final int BP_CONTACT = 2; + /** BPartner Info Index for Address 1 */ + private static final int BP_ADDR1 = 3; + /** BPartner Info Index for Address 2 */ + private static final int BP_ADDR2 = 4; + /** BPartner Info Index for City */ + private static final int BP_CITY = 5; + /** BPartner Info Index for Region */ + private static final int BP_REGION = 6; + /** BPartner Info Index for Postal Code */ + private static final int BP_POSTAL = 7; + /** BPartner Info Index for Country */ + private static final int BP_COUNTRY = 8; + /** BPartner Info Index for Reference No */ + private static final int BP_REFNO = 9; + + + /************************************************************************** + * Constructor + * @param ctx context + * @param C_PaySelectionCheck_ID C_PaySelectionCheck_ID + * @param trxName transaction + */ + public MPaySelectionCheck (Properties ctx, int C_PaySelectionCheck_ID, String trxName) + { + super(ctx, C_PaySelectionCheck_ID, trxName); + if (C_PaySelectionCheck_ID == 0) + { + // setC_PaySelection_ID (0); + // setC_BPartner_ID (0); + // setPaymentRule (null); + setPayAmt (Env.ZERO); + setDiscountAmt(Env.ZERO); + setIsPrinted (false); + setIsReceipt (false); + setQty (0); + } + } // MPaySelectionCheck + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPaySelectionCheck(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPaySelectionCheck + + /** + * Create from Line + * @param line payment selection + * @param PaymentRule payment rule + */ + public MPaySelectionCheck (MPaySelectionLine line, String PaymentRule) + { + this (line.getCtx(), 0, line.get_TrxName()); + setClientOrg(line); + setC_PaySelection_ID (line.getC_PaySelection_ID()); + setC_BPartner_ID (line.getInvoice().getC_BPartner_ID()); + setPaymentRule (PaymentRule); + // + setIsReceipt(line.isSOTrx()); + setPayAmt (line.getPayAmt()); + setDiscountAmt(line.getDiscountAmt()); + setQty (1); + } // MPaySelectionCheck + + /** + * Create from Pay Selection + * @param ps payment selection + * @param PaymentRule payment rule + */ + public MPaySelectionCheck (MPaySelection ps, String PaymentRule) + { + this (ps.getCtx(), 0, ps.get_TrxName()); + setClientOrg(ps); + setC_PaySelection_ID (ps.getC_PaySelection_ID()); + setPaymentRule (PaymentRule); + } // MPaySelectionCheck + + + /** Parent */ + private MPaySelection m_parent = null; + /** Payment Selection lines of this check */ + private MPaySelectionLine[] m_lines = null; + + + /** + * Add Payment Selection Line + * @param line line + */ + public void addLine (MPaySelectionLine line) + { + if (getC_BPartner_ID() != line.getInvoice().getC_BPartner_ID()) + throw new IllegalArgumentException("Line for fifferent BPartner"); + // + if (isReceipt() == line.isSOTrx()) + { + setPayAmt (getPayAmt().add(line.getPayAmt())); + setDiscountAmt(getDiscountAmt().add(line.getDiscountAmt())); + } + else + { + setPayAmt (getPayAmt().subtract(line.getPayAmt())); + setDiscountAmt(getDiscountAmt().subtract(line.getDiscountAmt())); + } + setQty (getQty()+1); + } // addLine + + /** + * Get Parent + * @return parent + */ + public MPaySelection getParent() + { + if (m_parent == null) + m_parent = new MPaySelection (getCtx(), getC_PaySelection_ID(), get_TrxName()); + return m_parent; + } // getParent + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("MPaymentCheck["); + sb.append(get_ID()).append("-").append(getDocumentNo()) + .append("-").append(getPayAmt()) + .append(",PaymetRule=").append(getPaymentRule()) + .append(",Qty=").append(getQty()) + .append("]"); + return sb.toString(); + } // toString + + /** + * Get Payment Selection Lines of this check + * @param requery requery + * @return array of peyment selection lines + */ + public MPaySelectionLine[] getPaySelectionLines (boolean requery) + { + if (m_lines != null && !requery) + return m_lines; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_PaySelectionLine WHERE C_PaySelectionCheck_ID=? ORDER BY Line"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_PaySelectionCheck_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MPaySelectionLine(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + m_lines = new MPaySelectionLine[list.size ()]; + list.toArray (m_lines); + return m_lines; + } // getPaySelectionLines + + +} // MPaySelectionCheck diff --git a/base/src/org/compiere/model/MPaySelectionLine.java b/base/src/org/compiere/model/MPaySelectionLine.java new file mode 100644 index 0000000000..7e4a9eff15 --- /dev/null +++ b/base/src/org/compiere/model/MPaySelectionLine.java @@ -0,0 +1,178 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Payment Selection Line Model + * + * @author Jorg Janke + * @version $Id: MPaySelectionLine.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MPaySelectionLine extends X_C_PaySelectionLine +{ + /** + * Standard Constructor + * @param ctx context + * @param C_PaySelectionLine_ID id + * @param trxName transaction + */ + public MPaySelectionLine (Properties ctx, int C_PaySelectionLine_ID, String trxName) + { + super(ctx, C_PaySelectionLine_ID, trxName); + if (C_PaySelectionLine_ID == 0) + { + // setC_PaySelection_ID (0); + // setPaymentRule (null); // S + // setLine (0); // @SQL=SELECT NVL(MAX(Line),0)+10 AS DefaultValue FROM C_PaySelectionLine WHERE C_PaySelection_ID=@C_PaySelection_ID@ + // setC_Invoice_ID (0); + setIsSOTrx (false); + setOpenAmt(Env.ZERO); + setPayAmt (Env.ZERO); + setDiscountAmt(Env.ZERO); + setDifferenceAmt (Env.ZERO); + setIsManual (false); + } + } // MPaySelectionLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPaySelectionLine(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPaySelectionLine + + /** + * Parent Constructor + * @param ps parent + * @param Line line + * @param PaymentRule payment rule + */ + public MPaySelectionLine (MPaySelection ps, int Line, String PaymentRule) + { + this (ps.getCtx(), 0, ps.get_TrxName()); + setClientOrg(ps); + setC_PaySelection_ID(ps.getC_PaySelection_ID()); + setLine(Line); + setPaymentRule(PaymentRule); + } // MPaySelectionLine + + /** Invoice */ + private MInvoice m_invoice = null; + + /** + * Set Invoice Info + * @param C_Invoice_ID invoice + * @param isSOTrx sales trx + * @param PayAmt payment + * @param OpenAmt open + * @param DiscountAmt discount + */ + public void setInvoice (int C_Invoice_ID, boolean isSOTrx, BigDecimal OpenAmt, + BigDecimal PayAmt, BigDecimal DiscountAmt) + { + setC_Invoice_ID (C_Invoice_ID); + setIsSOTrx(isSOTrx); + setOpenAmt(OpenAmt); + setPayAmt (PayAmt); + setDiscountAmt(DiscountAmt); + setDifferenceAmt(OpenAmt.subtract(PayAmt).subtract(DiscountAmt)); + } // setInvoive + + /** + * Get Invoice + * @return invoice + */ + public MInvoice getInvoice() + { + if (m_invoice == null) + m_invoice = new MInvoice (getCtx(), getC_Invoice_ID(), get_TrxName()); + return m_invoice; + } // getInvoice + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + setDifferenceAmt(getOpenAmt().subtract(getPayAmt()).subtract(getDiscountAmt())); + return true; + } // beforeSave + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + setHeader(); + return success; + } // afterSave + + /** + * After Delete + * @param success success + * @return sucess + */ + protected boolean afterDelete (boolean success) + { + setHeader(); + return success; + } // afterDelete + + /** + * Recalculate Header Sum + */ + private void setHeader() + { + // Update Header + String sql = "UPDATE C_PaySelection ps " + + "SET TotalAmt = (SELECT COALESCE(SUM(psl.PayAmt),0) " + + "FROM C_PaySelectionLine psl " + + "WHERE ps.C_PaySelection_ID=psl.C_PaySelection_ID AND psl.IsActive='Y') " + + "WHERE C_PaySelection_ID=" + getC_PaySelection_ID(); + DB.executeUpdate(sql, get_TrxName()); + } // setHeader + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("MPaySelectionLine["); + sb.append(get_ID()).append(",C_Invoice_ID=").append(getC_Invoice_ID()) + .append(",PayAmt=").append(getPayAmt()) + .append(",DifferenceAmt=").append(getDifferenceAmt()) + .append("]"); + return sb.toString(); + } // toString + +} // MPaySelectionLine diff --git a/base/src/org/compiere/model/MPayment.java b/base/src/org/compiere/model/MPayment.java new file mode 100644 index 0000000000..c1a4a79b98 --- /dev/null +++ b/base/src/org/compiere/model/MPayment.java @@ -0,0 +1,2290 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.rmi.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.db.*; +import org.compiere.interfaces.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Payment Model. + * - retrieve and create payments for invoice + *
+ *  Event chain
+ *  - Payment inserted
+ *      C_Payment_Trg fires
+ *          update DocumentNo with payment summary
+ *  - Payment posted (C_Payment_Post)
+ *      create allocation line
+ *          C_Allocation_Trg fires
+ *              Update C_BPartner Open Item Amount
+ *      update invoice (IsPaid)
+ *      link invoice-payment if batch
+ *
+ *  Lifeline:
+ *  -   Created by VPayment or directly
+ *  -   When changed in VPayment
+ *      - old payment is reversed
+ *      - new payment created
+ *
+ *  When Payment is posed, the Allocation is made
+ *  
+ * @author Jorg Janke + * @version $Id: MPayment.java,v 1.4 2006/10/02 05:18:39 jjanke Exp $ + */ +public final class MPayment extends X_C_Payment + implements DocAction, ProcessCall +{ + /** + * Get Payments Of BPartner + * @param ctx context + * @param C_BPartner_ID id + * @param trxName transaction + * @return array + */ + public static MPayment[] getOfBPartner (Properties ctx, int C_BPartner_ID, String trxName) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_Payment WHERE C_BPartner_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, C_BPartner_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MPayment(ctx,rs, trxName)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + // + MPayment[] retValue = new MPayment[list.size()]; + list.toArray(retValue); + return retValue; + } // getOfBPartner + + + /************************************************************************** + * Default Constructor + * @param ctx context + * @param C_Payment_ID payment to load, (0 create new payment) + * @param trxName trx name + */ + public MPayment (Properties ctx, int C_Payment_ID, String trxName) + { + super (ctx, C_Payment_ID, trxName); + // New + if (C_Payment_ID == 0) + { + setDocAction(DOCACTION_Complete); + setDocStatus(DOCSTATUS_Drafted); + setTrxType(TRXTYPE_Sales); + // + setR_AvsAddr (R_AVSZIP_Unavailable); + setR_AvsZip (R_AVSZIP_Unavailable); + // + setIsReceipt (true); + setIsApproved (false); + setIsReconciled (false); + setIsAllocated(false); + setIsOnline (false); + setIsSelfService(false); + setIsDelayedCapture (false); + setIsPrepayment(false); + setProcessed(false); + setProcessing(false); + setPosted (false); + // + setPayAmt(Env.ZERO); + setDiscountAmt(Env.ZERO); + setTaxAmt(Env.ZERO); + setWriteOffAmt(Env.ZERO); + setIsOverUnderPayment (false); + setOverUnderAmt(Env.ZERO); + // + setDateTrx (new Timestamp(System.currentTimeMillis())); + setDateAcct (getDateTrx()); + setTenderType(TENDERTYPE_Check); + } + } // MPayment + + /** + * Load Constructor + * @param ctx context + * @param rs result set record + * @param trxName transaction + */ + public MPayment (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPayment + + /** Temporary Payment Processors */ + private MPaymentProcessor[] m_mPaymentProcessors = null; + /** Temporary Payment Processor */ + private MPaymentProcessor m_mPaymentProcessor = null; + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MPayment.class); + /** Error Message */ + private String m_errorMessage = null; + + /** Reversal Indicator */ + public static String REVERSE_INDICATOR = "^"; + + /** + * Reset Payment to new status + */ + public void resetNew() + { + setC_Payment_ID(0); // forces new Record + set_ValueNoCheck ("DocumentNo", null); + setDocAction(DOCACTION_Prepare); + setDocStatus(DOCSTATUS_Drafted); + setProcessed(false); + setPosted (false); + setIsReconciled (false); + setIsAllocated(false); + setIsOnline(false); + setIsDelayedCapture (false); + // setC_BPartner_ID(0); + setC_Invoice_ID(0); + setC_Order_ID(0); + setC_Charge_ID(0); + setC_Project_ID(0); + setIsPrepayment(false); + } // resetNew + + /** + * Is Cashbook Transfer Trx + * @return true if Cash Trx + */ + public boolean isCashTrx() + { + return "X".equals(getTenderType()); + } // isCashTrx + + /************************************************************************** + * Set Credit Card. + * Need to set PatmentProcessor after Amount/Currency Set + * + * @param TrxType Transaction Type see TRX_ + * @param creditCardType CC type + * @param creditCardNumber CC number + * @param creditCardVV CC verification + * @param creditCardExpMM CC Exp MM + * @param creditCardExpYY CC Exp YY + * @return true if valid + */ + public boolean setCreditCard (String TrxType, String creditCardType, String creditCardNumber, + String creditCardVV, int creditCardExpMM, int creditCardExpYY) + { + setTenderType(TENDERTYPE_CreditCard); + setTrxType(TrxType); + // + setCreditCardType (creditCardType); + setCreditCardNumber (creditCardNumber); + setCreditCardVV (creditCardVV); + setCreditCardExpMM (creditCardExpMM); + setCreditCardExpYY (creditCardExpYY); + // + int check = MPaymentValidate.validateCreditCardNumber(creditCardNumber, creditCardType).length() + + MPaymentValidate.validateCreditCardExp(creditCardExpMM, creditCardExpYY).length(); + if (creditCardVV.length() > 0) + check += MPaymentValidate.validateCreditCardVV(creditCardVV, creditCardType).length(); + return check == 0; + } // setCreditCard + + /** + * Set Credit Card - Exp. + * Need to set PatmentProcessor after Amount/Currency Set + * + * @param TrxType Transaction Type see TRX_ + * @param creditCardType CC type + * @param creditCardNumber CC number + * @param creditCardVV CC verification + * @param creditCardExp CC Exp + * @return true if valid + */ + public boolean setCreditCard (String TrxType, String creditCardType, String creditCardNumber, + String creditCardVV, String creditCardExp) + { + return setCreditCard(TrxType, creditCardType, creditCardNumber, + creditCardVV, MPaymentValidate.getCreditCardExpMM(creditCardExp), + MPaymentValidate.getCreditCardExpYY(creditCardExp)); + } // setCreditCard + + /** + * Set ACH BankAccount Info + * + * @param C_BankAccount_ID bank account + * @param isReceipt true if receipt + * @return true if valid + */ + public boolean setBankACH (int C_BankAccount_ID, boolean isReceipt) + { + setBankAccountDetails(C_BankAccount_ID); + setIsReceipt (isReceipt); + // + int check = MPaymentValidate.validateRoutingNo(getRoutingNo()).length() + + MPaymentValidate.validateAccountNo(getAccountNo()).length(); + return check == 0; + } // setBankACH + + /** + * Set ACH BankAccount Info + * + * @param C_BankAccount_ID bank account + * @param isReceipt true if receipt + * @param tenderType - Direct Debit or Direct Deposit + * @param routingNo routing + * @param accountNo account + * @return true if valid + */ + public boolean setBankACH (int C_BankAccount_ID, boolean isReceipt, String tenderType, + String routingNo, String accountNo) + { + setTenderType (tenderType); + setIsReceipt (isReceipt); + // + if (C_BankAccount_ID > 0 + && (routingNo == null || routingNo.length() == 0 || accountNo == null || accountNo.length() == 0)) + setBankAccountDetails(C_BankAccount_ID); + else + { + setC_BankAccount_ID(C_BankAccount_ID); + setRoutingNo (routingNo); + setAccountNo (accountNo); + } + setCheckNo (""); + // + int check = MPaymentValidate.validateRoutingNo(routingNo).length() + + MPaymentValidate.validateAccountNo(accountNo).length(); + return check == 0; + } // setBankACH + + /** + * Set Check BankAccount Info + * + * @param C_BankAccount_ID bank account + * @param isReceipt true if receipt + * @param checkNo chack no + * @return true if valid + */ + public boolean setBankCheck (int C_BankAccount_ID, boolean isReceipt, String checkNo) + { + return setBankCheck (C_BankAccount_ID, isReceipt, null, null, checkNo); + } // setBankCheck + + /** + * Set Check BankAccount Info + * + * @param C_BankAccount_ID bank account + * @param isReceipt true if receipt + * @param routingNo routing no + * @param accountNo account no + * @param checkNo chack no + * @return true if valid + */ + public boolean setBankCheck (int C_BankAccount_ID, boolean isReceipt, + String routingNo, String accountNo, String checkNo) + { + setTenderType (TENDERTYPE_Check); + setIsReceipt (isReceipt); + // + if (C_BankAccount_ID > 0 + && (routingNo == null || routingNo.length() == 0 + || accountNo == null || accountNo.length() == 0)) + setBankAccountDetails(C_BankAccount_ID); + else + { + setC_BankAccount_ID(C_BankAccount_ID); + setRoutingNo (routingNo); + setAccountNo (accountNo); + } + setCheckNo (checkNo); + // + int check = MPaymentValidate.validateRoutingNo(routingNo).length() + + MPaymentValidate.validateAccountNo(accountNo).length() + + MPaymentValidate.validateCheckNo(checkNo).length(); + return check == 0; // no error message + } // setBankCheck + + /** + * Set Bank Account Details. + * Look up Routing No & Bank Acct No + * @param C_BankAccount_ID bank account + */ + public void setBankAccountDetails (int C_BankAccount_ID) + { + if (C_BankAccount_ID == 0) + return; + setC_BankAccount_ID(C_BankAccount_ID); + // + String sql = "SELECT b.RoutingNo, ba.AccountNo " + + "FROM C_BankAccount ba" + + " INNER JOIN C_Bank b ON (ba.C_Bank_ID=b.C_Bank_ID) " + + "WHERE C_BankAccount_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, C_BankAccount_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + setRoutingNo (rs.getString(1)); + setAccountNo (rs.getString(2)); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + } // setBankAccountDetails + + /** + * Set Account Address + * + * @param name name + * @param street street + * @param city city + * @param state state + * @param zip zip + * @param country country + */ + public void setAccountAddress (String name, String street, + String city, String state, String zip, String country) + { + setA_Name (name); + setA_Street (street); + setA_City (city); + setA_State (state); + setA_Zip (zip); + setA_Country(country); + } // setAccountAddress + + + /************************************************************************** + * Process Payment + * @return true if approved + */ + public boolean processOnline() + { + log.info ("Amt=" + getPayAmt()); + // + setIsOnline(true); + setErrorMessage(null); + // prevent charging twice + if (isApproved()) + { + log.info("Already processed - " + getR_Result() + " - " + getR_RespMsg()); + setErrorMessage("Payment already Processed"); + return true; + } + + if (m_mPaymentProcessor == null) + setPaymentProcessor(); + if (m_mPaymentProcessor == null) + { + log.log(Level.WARNING, "No Payment Processor Model"); + setErrorMessage("No Payment Processor Model"); + return false; + } + + boolean approved = false; + /** Process Payment on Server */ + if (DB.isRemoteObjects()) + { + Server server = CConnection.get().getServer(); + try + { + if (server != null) + { // See ServerBean + String trxName = null; // unconditionally save + save(trxName); // server reads from disk + approved = server.paymentOnline (getCtx(), getC_Payment_ID(), + m_mPaymentProcessor.getC_PaymentProcessor_ID(), trxName); + if (CLogMgt.isLevelFinest()) + s_log.fine("server => " + approved); + load(trxName); // server saves to disk + setIsApproved(approved); + return approved; + } + log.log(Level.WARNING, "AppsServer not found"); + } + catch (RemoteException ex) + { + log.log(Level.SEVERE, "AppsServer error", ex); + } + } + /** **/ + + // Try locally + try + { + PaymentProcessor pp = PaymentProcessor.create(m_mPaymentProcessor, this); + if (pp == null) + setErrorMessage("No Payment Processor"); + else + { + approved = pp.processCC (); + if (approved) + setErrorMessage(null); + else + setErrorMessage("From " + getCreditCardName() + ": " + getR_RespMsg()); + } + } + catch (Exception e) + { + log.log(Level.SEVERE, "processOnline", e); + setErrorMessage("Payment Processor Error"); + } + setIsApproved(approved); + return approved; + } // processOnline + + /** + * Process Online Payment. + * implements ProcessCall after standard constructor + * Called when pressing the Process_Online button in C_Payment + * + * @param ctx Context + * @param pi Process Info + * @param trx transaction + * @return true if the next process should be performed + */ + public boolean startProcess (Properties ctx, ProcessInfo pi, Trx trx) + { + log.info("startProcess - " + pi.getRecord_ID()); + boolean retValue = false; + // + if (pi.getRecord_ID() != get_ID()) + { + log.log(Level.SEVERE, "startProcess - Not same Payment - " + pi.getRecord_ID()); + return false; + } + // Process it + retValue = processOnline(); + save(); + return retValue; // Payment processed + } // startProcess + + + /** + * Before Save + * @param newRecord new + * @return save + */ + protected boolean beforeSave (boolean newRecord) + { + // We have a charge + if (getC_Charge_ID() != 0) + { + if (newRecord || is_ValueChanged("C_Charge_ID")) + { + setC_Order_ID(0); + setC_Invoice_ID(0); + setWriteOffAmt(Env.ZERO); + setDiscountAmt(Env.ZERO); + setIsOverUnderPayment(false); + setOverUnderAmt(Env.ZERO); + setIsPrepayment(false); + } + } + // We need a BPartner + else if (getC_BPartner_ID() == 0 && !isCashTrx()) + { + if (getC_Invoice_ID() != 0) + ; + else if (getC_Order_ID() != 0) + ; + else + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@NotFound@: @C_BPartner_ID@")); + return false; + } + } + // Prepayment: No charge and order or project (not as acct dimension) + if (newRecord + || is_ValueChanged("C_Charge_ID") || is_ValueChanged("C_Invoice_ID") + || is_ValueChanged("C_Order_ID") || is_ValueChanged("C_Project_ID")) + setIsPrepayment (getC_Charge_ID() == 0 + && getC_BPartner_ID() != 0 + && (getC_Order_ID() != 0 + || (getC_Project_ID() != 0 && getC_Invoice_ID() == 0))); + if (isPrepayment()) + { + if (newRecord + || is_ValueChanged("C_Order_ID") || is_ValueChanged("C_Project_ID")) + { + setWriteOffAmt(Env.ZERO); + setDiscountAmt(Env.ZERO); + setIsOverUnderPayment(false); + setOverUnderAmt(Env.ZERO); + } + } + + // Document Type/Receipt + if (getC_DocType_ID() == 0) + setC_DocType_ID(); + else + { + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + setIsReceipt(dt.isSOTrx()); + } + setDocumentNo(); + // + if (getDateAcct() == null) + setDateAcct(getDateTrx()); + // + if (!isOverUnderPayment()) + setOverUnderAmt(Env.ZERO); + + // Organization + if ((newRecord || is_ValueChanged("C_BankAccount_ID")) + && getC_Charge_ID() == 0) // allow different org for charge + { + MBankAccount ba = MBankAccount.get(getCtx(), getC_BankAccount_ID()); + if (ba.getAD_Org_ID() != 0) + setAD_Org_ID(ba.getAD_Org_ID()); + } + + return true; + } // beforeSave + + /** + * Get Allocated Amt in Payment Currency + * @return amount or null + */ + public BigDecimal getAllocatedAmt () + { + BigDecimal retValue = null; + if (getC_Charge_ID() != 0) + return getPayAmt(); + // + String sql = "SELECT SUM(currencyConvert(al.Amount," + + "ah.C_Currency_ID, p.C_Currency_ID,ah.DateTrx,p.C_ConversionType_ID, al.AD_Client_ID,al.AD_Org_ID)) " + + "FROM C_AllocationLine al" + + " INNER JOIN C_AllocationHdr ah ON (al.C_AllocationHdr_ID=ah.C_AllocationHdr_ID) " + + " INNER JOIN C_Payment p ON (al.C_Payment_ID=p.C_Payment_ID) " + + "WHERE al.C_Payment_ID=?" + + " AND ah.IsActive='Y' AND al.IsActive='Y'"; + // + " AND al.C_Invoice_ID IS NOT NULL"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_Payment_ID()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + retValue = rs.getBigDecimal(1); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getAllocatedAmt", e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // log.fine("getAllocatedAmt - " + retValue); + // ? ROUND(NVL(v_AllocatedAmt,0), 2); + return retValue; + } // getAllocatedAmt + + /** + * Test Allocation (and set allocated flag) + * @return true if updated + */ + public boolean testAllocation() + { + // Cash Trx always allocated + if (isCashTrx()) + { + if (!isAllocated()) + { + setIsAllocated(true); + return true; + } + return false; + } + // + BigDecimal alloc = getAllocatedAmt(); + if (alloc == null) + alloc = Env.ZERO; + BigDecimal total = getPayAmt(); + if (!isReceipt()) + total = total.negate(); + boolean test = total.compareTo(alloc) == 0; + boolean change = test != isAllocated(); + if (change) + setIsAllocated(test); + log.fine("Allocated=" + test + + " (" + alloc + "=" + total + ")"); + return change; + } // testAllocation + + /** + * Set Allocated Flag for payments + * @param ctx context + * @param C_BPartner_ID if 0 all + * @param trxName trx + */ + public static void setIsAllocated (Properties ctx, int C_BPartner_ID, String trxName) + { + int counter = 0; + String sql = "SELECT * FROM C_Payment " + + "WHERE IsAllocated='N' AND DocStatus IN ('CO','CL')"; + if (C_BPartner_ID > 1) + sql += " AND C_BPartner_ID=?"; + else + sql += " AND AD_Client_ID=" + Env.getAD_Client_ID(ctx); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + if (C_BPartner_ID > 1) + pstmt.setInt (1, C_BPartner_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MPayment pay = new MPayment (ctx, rs, trxName); + if (pay.testAllocation()) + if (pay.save()) + counter++; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + s_log.config("#" + counter); + } // setIsAllocated + + /************************************************************************** + * Set Error Message + * @param errorMessage error message + */ + public void setErrorMessage(String errorMessage) + { + m_errorMessage = errorMessage; + } // setErrorMessage + + /** + * Get Error Message + * @return error message + */ + public String getErrorMessage() + { + return m_errorMessage; + } // getErrorMessage + + + /** + * Set Bank Account for Payment. + * @param C_BankAccount_ID C_BankAccount_ID + */ + public void setC_BankAccount_ID (int C_BankAccount_ID) + { + if (C_BankAccount_ID == 0) + { + setPaymentProcessor(); + if (getC_BankAccount_ID() == 0) + throw new IllegalArgumentException("Can't find Bank Account"); + } + else + super.setC_BankAccount_ID(C_BankAccount_ID); + } // setC_BankAccount_ID + + /** + * Set BankAccount and PaymentProcessor + * @return true if found + */ + public boolean setPaymentProcessor () + { + return setPaymentProcessor (getTenderType(), getCreditCardType()); + } // setPaymentProcessor + + /** + * Set BankAccount and PaymentProcessor + * @param tender TenderType see TENDER_ + * @param CCType CC Type see CC_ + * @return true if found + */ + public boolean setPaymentProcessor (String tender, String CCType) + { + m_mPaymentProcessor = null; + // Get Processor List + if (m_mPaymentProcessors == null || m_mPaymentProcessors.length == 0) + m_mPaymentProcessors = MPaymentProcessor.find (getCtx(), tender, CCType, getAD_Client_ID(), + getC_Currency_ID(), getPayAmt(), get_TrxName()); + // Relax Amount + if (m_mPaymentProcessors == null || m_mPaymentProcessors.length == 0) + m_mPaymentProcessors = MPaymentProcessor.find (getCtx(), tender, CCType, getAD_Client_ID(), + getC_Currency_ID(), Env.ZERO, get_TrxName()); + if (m_mPaymentProcessors == null || m_mPaymentProcessors.length == 0) + return false; + + // Find the first right one + for (int i = 0; i < m_mPaymentProcessors.length; i++) + { + if (m_mPaymentProcessors[i].accepts (tender, CCType)) + { + m_mPaymentProcessor = m_mPaymentProcessors[i]; + } + } + if (m_mPaymentProcessor != null) + setC_BankAccount_ID (m_mPaymentProcessor.getC_BankAccount_ID()); + // + return m_mPaymentProcessor != null; + } // setPaymentProcessor + + + /** + * Get Accepted Credit Cards for PayAmt (default 0) + * @return credit cards + */ + public ValueNamePair[] getCreditCards () + { + return getCreditCards(getPayAmt()); + } // getCreditCards + + + /** + * Get Accepted Credit Cards for amount + * @param amt trx amount + * @return credit cards + */ + public ValueNamePair[] getCreditCards (BigDecimal amt) + { + try + { + if (m_mPaymentProcessors == null || m_mPaymentProcessors.length == 0) + m_mPaymentProcessors = MPaymentProcessor.find (getCtx (), null, null, + getAD_Client_ID (), getC_Currency_ID (), amt, get_TrxName()); + // + HashMap map = new HashMap(); // to eliminate duplicates + for (int i = 0; i < m_mPaymentProcessors.length; i++) + { + if (m_mPaymentProcessors[i].isAcceptAMEX ()) + map.put (CREDITCARDTYPE_Amex, getCreditCardPair (CREDITCARDTYPE_Amex)); + if (m_mPaymentProcessors[i].isAcceptDiners ()) + map.put (CREDITCARDTYPE_Diners, getCreditCardPair (CREDITCARDTYPE_Diners)); + if (m_mPaymentProcessors[i].isAcceptDiscover ()) + map.put (CREDITCARDTYPE_Discover, getCreditCardPair (CREDITCARDTYPE_Discover)); + if (m_mPaymentProcessors[i].isAcceptMC ()) + map.put (CREDITCARDTYPE_MasterCard, getCreditCardPair (CREDITCARDTYPE_MasterCard)); + if (m_mPaymentProcessors[i].isAcceptCorporate ()) + map.put (CREDITCARDTYPE_PurchaseCard, getCreditCardPair (CREDITCARDTYPE_PurchaseCard)); + if (m_mPaymentProcessors[i].isAcceptVisa ()) + map.put (CREDITCARDTYPE_Visa, getCreditCardPair (CREDITCARDTYPE_Visa)); + } // for all payment processors + // + ValueNamePair[] retValue = new ValueNamePair[map.size ()]; + map.values ().toArray (retValue); + log.fine("getCreditCards - #" + retValue.length + " - Processors=" + m_mPaymentProcessors.length); + return retValue; + } + catch (Exception ex) + { + ex.printStackTrace(); + return null; + } + } // getCreditCards + + /** + * Get Type and name pair + * @param CreditCardType credit card Type + * @return pair + */ + private ValueNamePair getCreditCardPair (String CreditCardType) + { + return new ValueNamePair (CreditCardType, getCreditCardName(CreditCardType)); + } // getCreditCardPair + + + /************************************************************************** + * Credit Card Number + * @param CreditCardNumber CreditCard Number + */ + public void setCreditCardNumber (String CreditCardNumber) + { + super.setCreditCardNumber (MPaymentValidate.checkNumeric(CreditCardNumber)); + } // setCreditCardNumber + + /** + * Verification Code + * @param newCreditCardVV CC verification + */ + public void setCreditCardVV(String newCreditCardVV) + { + super.setCreditCardVV (MPaymentValidate.checkNumeric(newCreditCardVV)); + } // setCreditCardVV + + /** + * Two Digit CreditCard MM + * @param CreditCardExpMM Exp month + */ + public void setCreditCardExpMM (int CreditCardExpMM) + { + if (CreditCardExpMM < 1 || CreditCardExpMM > 12) + ; + else + super.setCreditCardExpMM (CreditCardExpMM); + } // setCreditCardExpMM + + /** + * Two digit CreditCard YY (til 2020) + * @param newCreditCardExpYY 2 or 4 digit year + */ + public void setCreditCardExpYY (int newCreditCardExpYY) + { + int CreditCardExpYY = newCreditCardExpYY; + if (newCreditCardExpYY > 1999) + CreditCardExpYY = newCreditCardExpYY-2000; + super.setCreditCardExpYY(CreditCardExpYY); + } // setCreditCardExpYY + + /** + * CreditCard Exp MMYY + * @param mmyy Exp in form of mmyy + * @return true if valid + */ + public boolean setCreditCardExp (String mmyy) + { + if (MPaymentValidate.validateCreditCardExp(mmyy).length() != 0) + return false; + // + String exp = MPaymentValidate.checkNumeric(mmyy); + String mmStr = exp.substring(0,2); + String yyStr = exp.substring(2,4); + setCreditCardExpMM (Integer.parseInt(mmStr)); + setCreditCardExpYY (Integer.parseInt(yyStr)); + return true; + } // setCreditCardExp + + + /** + * CreditCard Exp MMYY + * @param delimiter / - or null + * @return Exp + */ + public String getCreditCardExp(String delimiter) + { + String mm = String.valueOf(getCreditCardExpMM()); + String yy = String.valueOf(getCreditCardExpYY()); + + StringBuffer retValue = new StringBuffer(); + if (mm.length() == 1) + retValue.append("0"); + retValue.append(mm); + // + if (delimiter != null) + retValue.append(delimiter); + // + if (yy.length() == 1) + retValue.append("0"); + retValue.append(yy); + // + return (retValue.toString()); + } // getCreditCardExp + + /** + * MICR + * @param MICR MICR + */ + public void setMicr (String MICR) + { + super.setMicr (MPaymentValidate.checkNumeric(MICR)); + } // setBankMICR + + /** + * Routing No + * @param RoutingNo Routing No + */ + public void setRoutingNo(String RoutingNo) + { + super.setRoutingNo (MPaymentValidate.checkNumeric(RoutingNo)); + } // setBankRoutingNo + + + /** + * Bank Account No + * @param AccountNo AccountNo + */ + public void setAccountNo (String AccountNo) + { + super.setAccountNo (MPaymentValidate.checkNumeric(AccountNo)); + } // setBankAccountNo + + + /** + * Check No + * @param CheckNo Check No + */ + public void setCheckNo(String CheckNo) + { + super.setCheckNo(MPaymentValidate.checkNumeric(CheckNo)); + } // setBankCheckNo + + + /** + * Set DocumentNo to Payment info. + * If there is a R_PnRef that is set automatically + */ + private void setDocumentNo() + { + // Cash Transfer + if ("X".equals(getTenderType())) + return; + // Current Document No + String documentNo = getDocumentNo(); + // Existing reversal + if (documentNo != null + && documentNo.indexOf(REVERSE_INDICATOR) >= 0) + return; + + // If external number exists - enforce it + if (getR_PnRef() != null && getR_PnRef().length() > 0) + { + if (!getR_PnRef().equals(documentNo)) + setDocumentNo(getR_PnRef()); + return; + } + + documentNo = ""; + // Credit Card + if (TENDERTYPE_CreditCard.equals(getTenderType())) + { + documentNo = getCreditCardType() + + " " + Obscure.obscure(getCreditCardNumber()) + + " " + getCreditCardExpMM() + + "/" + getCreditCardExpYY(); + } + // Own Check No + else if (TENDERTYPE_Check.equals(getTenderType()) + && !isReceipt() + && getCheckNo() != null && getCheckNo().length() > 0) + { + documentNo = getCheckNo(); + } + // Customer Check: Routing: Account #Check + else if (TENDERTYPE_Check.equals(getTenderType()) + && isReceipt()) + { + if (getRoutingNo() != null) + documentNo = getRoutingNo() + ": "; + if (getAccountNo() != null) + documentNo += getAccountNo(); + if (getCheckNo() != null) + { + if (documentNo.length() > 0) + documentNo += " "; + documentNo += "#" + getCheckNo(); + } + } + + // Set Document No + documentNo = documentNo.trim(); + if (documentNo.length() > 0) + setDocumentNo(documentNo); + } // setDocumentNo + + /** + * Set Refernce No (and Document No) + * @param R_PnRef reference + */ + public void setR_PnRef (String R_PnRef) + { + super.setR_PnRef (R_PnRef); + if (R_PnRef != null) + setDocumentNo (R_PnRef); + } // setR_PnRef + + // --------------- + + /** + * Set Payment Amount + * @param PayAmt Pay Amt + */ + public void setPayAmt (BigDecimal PayAmt) + { + super.setPayAmt(PayAmt == null ? Env.ZERO : PayAmt); + } // setPayAmt + + /** + * Set Payment Amount + * + * @param C_Currency_ID currency + * @param payAmt amount + */ + public void setAmount (int C_Currency_ID, BigDecimal payAmt) + { + if (C_Currency_ID == 0) + C_Currency_ID = MClient.get(getCtx()).getC_Currency_ID(); + setC_Currency_ID(C_Currency_ID); + setPayAmt(payAmt); + } // setAmount + + /** + * Discount Amt + * @param DiscountAmt Discount + */ + public void setDiscountAmt (BigDecimal DiscountAmt) + { + super.setDiscountAmt (DiscountAmt == null ? Env.ZERO : DiscountAmt); + } // setDiscountAmt + + /** + * WriteOff Amt + * @param WriteOffAmt WriteOff + */ + public void setWriteOffAmt (BigDecimal WriteOffAmt) + { + super.setWriteOffAmt (WriteOffAmt == null ? Env.ZERO : WriteOffAmt); + } // setWriteOffAmt + + /** + * OverUnder Amt + * @param OverUnderAmt OverUnder + */ + public void setOverUnderAmt (BigDecimal OverUnderAmt) + { + super.setOverUnderAmt (OverUnderAmt == null ? Env.ZERO : OverUnderAmt); + setIsOverUnderPayment(getOverUnderAmt().compareTo(Env.ZERO) != 0); + } // setOverUnderAmt + + /** + * Tax Amt + * @param TaxAmt Tax + */ + public void setTaxAmt (BigDecimal TaxAmt) + { + super.setTaxAmt (TaxAmt == null ? Env.ZERO : TaxAmt); + } // setTaxAmt + + /** + * Set Info from BP Bank Account + * @param ba BP bank account + */ + public void setBP_BankAccount (MBPBankAccount ba) + { + log.fine("" + ba); + if (ba == null) + return; + setC_BPartner_ID(ba.getC_BPartner_ID()); + setAccountAddress(ba.getA_Name(), ba.getA_Street(), ba.getA_City(), + ba.getA_State(), ba.getA_Zip(), ba.getA_Country()); + setA_EMail(ba.getA_EMail()); + setA_Ident_DL(ba.getA_Ident_DL()); + setA_Ident_SSN(ba.getA_Ident_SSN()); + // CC + if (ba.getCreditCardType() != null) + setCreditCardType(ba.getCreditCardType()); + if (ba.getCreditCardNumber() != null) + setCreditCardNumber(ba.getCreditCardNumber()); + if (ba.getCreditCardExpMM() != 0) + setCreditCardExpMM(ba.getCreditCardExpMM()); + if (ba.getCreditCardExpYY() != 0) + setCreditCardExpYY(ba.getCreditCardExpYY()); + if (ba.getCreditCardVV() != null) + setCreditCardVV(ba.getCreditCardVV()); + // Bank + if (ba.getAccountNo() != null) + setAccountNo(ba.getAccountNo()); + if (ba.getRoutingNo() != null) + setRoutingNo(ba.getRoutingNo()); + } // setBP_BankAccount + + /** + * Save Info from BP Bank Account + * @param ba BP bank account + * @return true if saved + */ + public boolean saveToBP_BankAccount (MBPBankAccount ba) + { + if (ba == null) + return false; + ba.setA_Name(getA_Name()); + ba.setA_Street(getA_Street()); + ba.setA_City(getA_City()); + ba.setA_State(getA_State()); + ba.setA_Zip(getA_Zip()); + ba.setA_Country(getA_Country()); + ba.setA_EMail(getA_EMail()); + ba.setA_Ident_DL(getA_Ident_DL()); + ba.setA_Ident_SSN(getA_Ident_SSN()); + // CC + ba.setCreditCardType(getCreditCardType()); + ba.setCreditCardNumber(getCreditCardNumber()); + ba.setCreditCardExpMM(getCreditCardExpMM()); + ba.setCreditCardExpYY(getCreditCardExpYY()); + ba.setCreditCardVV(getCreditCardVV()); + // Bank + if (getAccountNo() != null) + ba.setAccountNo(getAccountNo()); + if (getRoutingNo() != null) + ba.setRoutingNo(getRoutingNo()); + // Trx + ba.setR_AvsAddr(getR_AvsAddr()); + ba.setR_AvsZip(getR_AvsZip()); + // + boolean ok = ba.save(get_TrxName()); + log.fine("saveToBP_BankAccount - " + ba); + return ok; + } // setBP_BankAccount + + /** + * Set Doc Type bases on IsReceipt + */ + private void setC_DocType_ID () + { + setC_DocType_ID(isReceipt()); + } // setC_DocType_ID + + /** + * Set Doc Type + * @param isReceipt is receipt + */ + public void setC_DocType_ID (boolean isReceipt) + { + setIsReceipt(isReceipt); + String sql = "SELECT C_DocType_ID FROM C_DocType WHERE AD_Client_ID=? AND DocBaseType=? ORDER BY IsDefault DESC"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getAD_Client_ID()); + if (isReceipt) + pstmt.setString(2, MDocType.DOCBASETYPE_ARReceipt); + else + pstmt.setString(2, MDocType.DOCBASETYPE_APPayment); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + setC_DocType_ID(rs.getInt(1)); + else + log.warning ("setDocType - NOT found - isReceipt=" + isReceipt); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + } // setC_DocType_ID + + + /** + * Set Document Type + * @param C_DocType_ID doc type + */ + public void setC_DocType_ID (int C_DocType_ID) + { + // if (getDocumentNo() != null && getC_DocType_ID() != C_DocType_ID) + // setDocumentNo(null); + super.setC_DocType_ID(C_DocType_ID); + } // setC_DocType_ID + + /** + * Verify Document Type with Invoice + * @return true if ok + */ + private boolean verifyDocType() + { + if (getC_DocType_ID() == 0) + return false; + // + Boolean invoiceSO = null; + // Check Invoice First + if (getC_Invoice_ID() > 0) + { + String sql = "SELECT idt.IsSOTrx " + + "FROM C_Invoice i" + + " INNER JOIN C_DocType idt ON (i.C_DocType_ID=idt.C_DocType_ID) " + + "WHERE i.C_Invoice_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_Invoice_ID()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + invoiceSO = new Boolean ("Y".equals(rs.getString(1))); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + } // Invoice + + // DocumentType + Boolean paymentSO = null; + PreparedStatement pstmt = null; + String sql = "SELECT IsSOTrx " + + "FROM C_DocType " + + "WHERE C_DocType_ID=?"; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_DocType_ID()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + paymentSO = new Boolean ("Y".equals(rs.getString(1))); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // No Payment info + if (paymentSO == null) + return false; + setIsReceipt(paymentSO.booleanValue()); + + // We have an Invoice .. and it does not match + if (invoiceSO != null + && invoiceSO.booleanValue() != paymentSO.booleanValue()) + return false; + // OK + return true; + } // verifyDocType + + + /** + * Get ISO Code of Currency + * @return Currency ISO + */ + public String getCurrencyISO() + { + return MCurrency.getISO_Code (getCtx(), getC_Currency_ID()); + } // getCurrencyISO + + /** + * Get Document Status + * @return Document Status Clear Text + */ + public String getDocStatusName() + { + return MRefList.getListName(getCtx(), 131, getDocStatus()); + } // getDocStatusName + + /** + * Get Name of Credit Card + * @return Name + */ + public String getCreditCardName() + { + return getCreditCardName(getCreditCardType()); + } // getCreditCardName + + /** + * Get Name of Credit Card + * @param CreditCardType credit card type + * @return Name + */ + public String getCreditCardName(String CreditCardType) + { + if (CreditCardType == null) + return "--"; + else if (CREDITCARDTYPE_MasterCard.equals(CreditCardType)) + return "MasterCard"; + else if (CREDITCARDTYPE_Visa.equals(CreditCardType)) + return "Visa"; + else if (CREDITCARDTYPE_Amex.equals(CreditCardType)) + return "Amex"; + else if (CREDITCARDTYPE_ATM.equals(CreditCardType)) + return "ATM"; + else if (CREDITCARDTYPE_Diners.equals(CreditCardType)) + return "Diners"; + else if (CREDITCARDTYPE_Discover.equals(CreditCardType)) + return "Discover"; + else if (CREDITCARDTYPE_PurchaseCard.equals(CreditCardType)) + return "PurchaseCard"; + return "?" + CreditCardType + "?"; + } // getCreditCardName + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + + /** + * Get Pay Amt + * @param absolute if true the absolute amount (i.e. negative if payment) + * @return amount + */ + public BigDecimal getPayAmt (boolean absolute) + { + if (isReceipt()) + return super.getPayAmt(); + return super.getPayAmt().negate(); + } // getPayAmt + + /** + * Get Pay Amt in cents + * @return amount in cents + */ + public int getPayAmtInCents () + { + BigDecimal bd = super.getPayAmt().multiply(Env.ONEHUNDRED); + return bd.intValue(); + } // getPayAmtInCents + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // process + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info("unlockIt - " + toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info("invalidateIt - " + toString()); + setDocAction(DOCACTION_Prepare); + return true; + } // invalidateIt + + + /************************************************************************** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + + // Std Period open? + if (!MPeriod.isOpen(getCtx(), getDateAcct(), + isReceipt() ? MDocType.DOCBASETYPE_ARReceipt : MDocType.DOCBASETYPE_APPayment)) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + + // Unsuccessful Online Payment + if (isOnline() && !isApproved()) + { + if (getR_Result() != null) + m_processMsg = "@OnlinePaymentFailed@"; + else + m_processMsg = "@PaymentNotProcessed@"; + return DocAction.STATUS_Invalid; + } + + // Waiting Payment - Need to create Invoice & Shipment + if (getC_Order_ID() != 0 && getC_Invoice_ID() == 0) + { // see WebOrder.process + MOrder order = new MOrder (getCtx(), getC_Order_ID(), get_TrxName()); + if (DOCSTATUS_WaitingPayment.equals(order.getDocStatus())) + { + order.setC_Payment_ID(getC_Payment_ID()); + order.setDocAction(MOrder.DOCACTION_WaitComplete); + order.set_TrxName(get_TrxName()); + boolean ok = order.processIt (MOrder.DOCACTION_WaitComplete); + m_processMsg = order.getProcessMsg(); + order.save(get_TrxName()); + // Set Invoice + MInvoice[] invoices = order.getInvoices(); + int length = invoices.length; + if (length > 0) // get last invoice + setC_Invoice_ID (invoices[length-1].getC_Invoice_ID()); + // + if (getC_Invoice_ID() == 0) + { + m_processMsg = "@NotFound@ @C_Invoice_ID@"; + return DocAction.STATUS_Invalid; + } + } // WaitingPayment + } + + // Consistency of Invoice / Document Type and IsReceipt + if (!verifyDocType()) + { + m_processMsg = "@PaymentDocTypeInvoiceInconsistent@"; + return DocAction.STATUS_Invalid; + } + + // Do not pay when Credit Stop/Hold + if (!isReceipt()) + { + MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName()); + if (MBPartner.SOCREDITSTATUS_CreditStop.equals(bp.getSOCreditStatus())) + { + m_processMsg = "@BPartnerCreditStop@ - @TotalOpenBalance@=" + + bp.getTotalOpenBalance() + + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); + return DocAction.STATUS_Invalid; + } + if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus())) + { + m_processMsg = "@BPartnerCreditHold@ - @TotalOpenBalance@=" + + bp.getTotalOpenBalance() + + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); + return DocAction.STATUS_Invalid; + } + } + + m_justPrepared = true; + if (!DOCACTION_Complete.equals(getDocAction())) + setDocAction(DOCACTION_Complete); + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info(toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info(toString()); + setIsApproved(false); + return true; + } // rejectIt + + + /************************************************************************** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + // Implicit Approval + if (!isApproved()) + approveIt(); + log.info(toString()); + + // Charge Handling + if (getC_Charge_ID() != 0) + { + setIsAllocated(true); + } + else + { + allocateIt(); // Create Allocation Records + testAllocation(); + } + + // Project update + if (getC_Project_ID() != 0) + { + // MProject project = new MProject(getCtx(), getC_Project_ID()); + } + // Update BP for Prepayments + if (getC_BPartner_ID() != 0 && getC_Invoice_ID() == 0) + { + MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName()); + bp.setTotalOpenBalance(); + bp.save(); + } + + // Counter Doc + MPayment counter = createCounterDoc(); + if (counter != null) + m_processMsg += " @CounterDoc@: @C_Payment_ID@=" + counter.getDocumentNo(); + + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + m_processMsg = valid; + return DocAction.STATUS_Invalid; + } + // + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + /** + * Create Counter Document + * @return payment + */ + private MPayment createCounterDoc() + { + // Is this a counter doc ? + if (getRef_Payment_ID() != 0) + return null; + + // Org Must be linked to BPartner + MOrg org = MOrg.get(getCtx(), getAD_Org_ID()); + int counterC_BPartner_ID = org.getLinkedC_BPartner_ID(); + if (counterC_BPartner_ID == 0) + return null; + // Business Partner needs to be linked to Org + MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), null); + int counterAD_Org_ID = bp.getAD_OrgBP_ID_Int(); + if (counterAD_Org_ID == 0) + return null; + + MBPartner counterBP = new MBPartner (getCtx(), counterC_BPartner_ID, null); + MOrgInfo counterOrgInfo = MOrgInfo.get(getCtx(), counterAD_Org_ID); + log.info("Counter BP=" + counterBP.getName()); + + // Document Type + int C_DocTypeTarget_ID = 0; + MDocTypeCounter counterDT = MDocTypeCounter.getCounterDocType(getCtx(), getC_DocType_ID()); + if (counterDT != null) + { + log.fine(counterDT.toString()); + if (!counterDT.isCreateCounter() || !counterDT.isValid()) + return null; + C_DocTypeTarget_ID = counterDT.getCounter_C_DocType_ID(); + } + else // indirect + { + C_DocTypeTarget_ID = MDocTypeCounter.getCounterDocType_ID(getCtx(), getC_DocType_ID()); + log.fine("Indirect C_DocTypeTarget_ID=" + C_DocTypeTarget_ID); + if (C_DocTypeTarget_ID <= 0) + return null; + } + + // Deep Copy + MPayment counter = new MPayment (getCtx(), 0, get_TrxName()); + counter.setAD_Org_ID(counterAD_Org_ID); + counter.setC_BPartner_ID(counterBP.getC_BPartner_ID()); + counter.setIsReceipt(!isReceipt()); + counter.setC_DocType_ID(C_DocTypeTarget_ID); + counter.setTrxType(getTrxType()); + counter.setTenderType(getTenderType()); + // + counter.setPayAmt(getPayAmt()); + counter.setDiscountAmt(getDiscountAmt()); + counter.setTaxAmt(getTaxAmt()); + counter.setWriteOffAmt(getWriteOffAmt()); + counter.setIsOverUnderPayment (isOverUnderPayment()); + counter.setOverUnderAmt(getOverUnderAmt()); + counter.setC_Currency_ID(getC_Currency_ID()); + counter.setC_ConversionType_ID(getC_ConversionType_ID()); + // + counter.setDateTrx (getDateTrx()); + counter.setDateAcct (getDateAcct()); + counter.setRef_Payment_ID(getC_Payment_ID()); + // + String sql = "SELECT C_BankAccount_ID FROM C_BankAccount " + + "WHERE C_Currency_ID=? AND AD_Org_ID IN (0,?) AND IsActive='Y' " + + "ORDER BY IsDefault DESC"; + int C_BankAccount_ID = DB.getSQLValue(get_TrxName(), sql, getC_Currency_ID(), counterAD_Org_ID); + counter.setC_BankAccount_ID(C_BankAccount_ID); + + // Refernces + counter.setC_Activity_ID(getC_Activity_ID()); + counter.setC_Campaign_ID(getC_Campaign_ID()); + counter.setC_Project_ID(getC_Project_ID()); + counter.setUser1_ID(getUser1_ID()); + counter.setUser2_ID(getUser2_ID()); + counter.save(get_TrxName()); + log.fine(counter.toString()); + setRef_Payment_ID(counter.getC_Payment_ID()); + + // Document Action + if (counterDT != null) + { + if (counterDT.getDocAction() != null) + { + counter.setDocAction(counterDT.getDocAction()); + counter.processIt(counterDT.getDocAction()); + counter.save(get_TrxName()); + } + } + return counter; + } // createCounterDoc + + /** + * Allocate It. + * Only call when there is NO allocation as it will create duplicates. + * If an invoice exists, it allocates that + * otherwise it allocates Payment Selection. + * @return true if allocated + */ + public boolean allocateIt() + { + // Create invoice Allocation - See also MCash.completeIt + if (getC_Invoice_ID() != 0) + return allocateInvoice(); + // Invoices of a AP Payment Selection + if (allocatePaySelection()) + return true; + + if (getC_Order_ID() != 0) + return false; + + // Allocate to multiple Payments based on entry + MPaymentAllocate[] pAllocs = MPaymentAllocate.get(this); + if (pAllocs.length == 0) + return false; + + MAllocationHdr alloc = new MAllocationHdr(getCtx(), false, + getDateTrx(), getC_Currency_ID(), + Msg.translate(getCtx(), "C_Payment_ID") + ": " + getDocumentNo(), + get_TrxName()); + alloc.setAD_Org_ID(getAD_Org_ID()); + if (!alloc.save()) + { + log.severe("P.Allocations not created"); + return false; + } + // Lines + for (int i = 0; i < pAllocs.length; i++) + { + MPaymentAllocate pa = pAllocs[i]; + MAllocationLine aLine = null; + if (isReceipt()) + aLine = new MAllocationLine (alloc, pa.getAmount(), + pa.getDiscountAmt(), pa.getWriteOffAmt(), pa.getOverUnderAmt()); + else + aLine = new MAllocationLine (alloc, pa.getAmount().negate(), + pa.getDiscountAmt().negate(), pa.getWriteOffAmt().negate(), pa.getOverUnderAmt().negate()); + aLine.setDocInfo(pa.getC_BPartner_ID(), 0, pa.getC_Invoice_ID()); + aLine.setPaymentInfo(getC_Payment_ID(), 0); + if (!aLine.save(get_TrxName())) + log.warning("P.Allocations - line not saved"); + else + { + pa.setC_AllocationLine_ID(aLine.getC_AllocationLine_ID()); + pa.save(); + } + } + // Should start WF + alloc.processIt(DocAction.ACTION_Complete); + m_processMsg = "@C_AllocationHdr_ID@: " + alloc.getDocumentNo(); + return alloc.save(get_TrxName()); + } // allocateIt + + /** + * Allocate single AP/AR Invoice + * @return true if allocated + */ + private boolean allocateInvoice() + { + // calculate actual allocation + BigDecimal allocationAmt = getPayAmt(); // underpayment + if (getOverUnderAmt().signum() < 0 && getPayAmt().signum() > 0) + allocationAmt = allocationAmt.add(getOverUnderAmt()); // overpayment (negative) + + MAllocationHdr alloc = new MAllocationHdr(getCtx(), false, + getDateTrx(), getC_Currency_ID(), + Msg.translate(getCtx(), "C_Payment_ID") + ": " + getDocumentNo() + " [1]", get_TrxName()); + alloc.setAD_Org_ID(getAD_Org_ID()); + if (!alloc.save()) + { + log.log(Level.SEVERE, "Could not create Allocation Hdr"); + return false; + } + MAllocationLine aLine = null; + if (isReceipt()) + aLine = new MAllocationLine (alloc, allocationAmt, + getDiscountAmt(), getWriteOffAmt(), getOverUnderAmt()); + else + aLine = new MAllocationLine (alloc, allocationAmt.negate(), + getDiscountAmt().negate(), getWriteOffAmt().negate(), getOverUnderAmt().negate()); + aLine.setDocInfo(getC_BPartner_ID(), 0, getC_Invoice_ID()); + aLine.setC_Payment_ID(getC_Payment_ID()); + if (!aLine.save(get_TrxName())) + { + log.log(Level.SEVERE, "Could not create Allocation Line"); + return false; + } + // Should start WF + alloc.processIt(DocAction.ACTION_Complete); + alloc.save(get_TrxName()); + m_processMsg = "@C_AllocationHdr_ID@: " + alloc.getDocumentNo(); + + // Get Project from Invoice + int C_Project_ID = DB.getSQLValue(get_TrxName(), + "SELECT MAX(C_Project_ID) FROM C_Invoice WHERE C_Invoice_ID=?", getC_Invoice_ID()); + if (C_Project_ID > 0 && getC_Project_ID() == 0) + setC_Project_ID(C_Project_ID); + else if (C_Project_ID > 0 && getC_Project_ID() > 0 && C_Project_ID != getC_Project_ID()) + log.warning("Invoice C_Project_ID=" + C_Project_ID + + " <> Payment C_Project_ID=" + getC_Project_ID()); + return true; + } // allocateInvoice + + /** + * Allocate Payment Selection + * @return true if allocated + */ + private boolean allocatePaySelection() + { + MAllocationHdr alloc = new MAllocationHdr(getCtx(), false, + getDateTrx(), getC_Currency_ID(), + Msg.translate(getCtx(), "C_Payment_ID") + ": " + getDocumentNo() + " [n]", get_TrxName()); + alloc.setAD_Org_ID(getAD_Org_ID()); + + String sql = "SELECT psc.C_BPartner_ID, psl.C_Invoice_ID, psl.IsSOTrx, " // 1..3 + + " psl.PayAmt, psl.DiscountAmt, psl.DifferenceAmt, psl.OpenAmt " + + "FROM C_PaySelectionLine psl" + + " INNER JOIN C_PaySelectionCheck psc ON (psl.C_PaySelectionCheck_ID=psc.C_PaySelectionCheck_ID) " + + "WHERE psc.C_Payment_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_Payment_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + int C_BPartner_ID = rs.getInt(1); + int C_Invoice_ID = rs.getInt(2); + if (C_BPartner_ID == 0 && C_Invoice_ID == 0) + continue; + boolean isSOTrx = "Y".equals(rs.getString(3)); + BigDecimal PayAmt = rs.getBigDecimal(4); + BigDecimal DiscountAmt = rs.getBigDecimal(5); + BigDecimal WriteOffAmt = rs.getBigDecimal(6); + BigDecimal OpenAmt = rs.getBigDecimal(7); + BigDecimal OverUnderAmt = OpenAmt.subtract(PayAmt) + .subtract(DiscountAmt).subtract(WriteOffAmt); + // + if (alloc.get_ID() == 0 && !alloc.save(get_TrxName())) + { + log.log(Level.SEVERE, "Could not create Allocation Hdr"); + rs.close(); + pstmt.close(); + return false; + } + MAllocationLine aLine = null; + if (isSOTrx) + aLine = new MAllocationLine (alloc, PayAmt, + DiscountAmt, WriteOffAmt, OverUnderAmt); + else + aLine = new MAllocationLine (alloc, PayAmt.negate(), + DiscountAmt.negate(), WriteOffAmt.negate(), OverUnderAmt.negate()); + aLine.setDocInfo(C_BPartner_ID, 0, C_Invoice_ID); + aLine.setC_Payment_ID(getC_Payment_ID()); + if (!aLine.save(get_TrxName())) + log.log(Level.SEVERE, "Could not create Allocation Line"); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "allocatePaySelection", e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + // Should start WF + boolean ok = true; + if (alloc.get_ID() == 0) + { + log.fine("No Allocation created - C_Payment_ID=" + + getC_Payment_ID()); + ok = false; + } + else + { + alloc.processIt(DocAction.ACTION_Complete); + ok = alloc.save(get_TrxName()); + m_processMsg = "@C_AllocationHdr_ID@: " + alloc.getDocumentNo(); + } + return ok; + } // allocatePaySelection + + /** + * De-allocate Payment. + * Unkink Invoices and Orders and delete Allocations + */ + private void deAllocate() + { + if (getC_Order_ID() != 0) + setC_Order_ID(0); + // if (getC_Invoice_ID() == 0) + // return; + // De-Allocate all + MAllocationHdr[] allocations = MAllocationHdr.getOfPayment(getCtx(), + getC_Payment_ID(), get_TrxName()); + log.fine("#" + allocations.length); + for (int i = 0; i < allocations.length; i++) + { + allocations[i].set_TrxName(get_TrxName()); + allocations[i].setDocAction(DocAction.ACTION_Reverse_Correct); + allocations[i].processIt(DocAction.ACTION_Reverse_Correct); + allocations[i].save(); + } + + // Unlink (in case allocation did not get it) + if (getC_Invoice_ID() != 0) + { + // Invoice + String sql = "UPDATE C_Invoice " + + "SET C_Payment_ID = NULL, IsPaid='N' " + + "WHERE C_Invoice_ID=" + getC_Invoice_ID() + + " AND C_Payment_ID=" + getC_Payment_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Unlink Invoice #" + no); + // Order + sql = "UPDATE C_Order o " + + "SET C_Payment_ID = NULL " + + "WHERE EXISTS (SELECT * FROM C_Invoice i " + + "WHERE o.C_Order_ID=i.C_Order_ID AND i.C_Invoice_ID=" + getC_Invoice_ID() + ")" + + " AND C_Payment_ID=" + getC_Payment_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Unlink Order #" + no); + } + // + setC_Invoice_ID(0); + setIsAllocated(false); + } // deallocate + + /** + * Void Document. + * @return true if success + */ + public boolean voidIt() + { + log.info(toString()); + if (DOCSTATUS_Closed.equals(getDocStatus()) + || DOCSTATUS_Reversed.equals(getDocStatus()) + || DOCSTATUS_Voided.equals(getDocStatus())) + { + m_processMsg = "Document Closed: " + getDocStatus(); + setDocAction(DOCACTION_None); + return false; + } + // If on Bank Statement, don't void it - reverse it + if (getC_BankStatementLine_ID() > 0) + return reverseCorrectIt(); + + // Not Processed + if (DOCSTATUS_Drafted.equals(getDocStatus()) + || DOCSTATUS_Invalid.equals(getDocStatus()) + || DOCSTATUS_InProgress.equals(getDocStatus()) + || DOCSTATUS_Approved.equals(getDocStatus()) + || DOCSTATUS_NotApproved.equals(getDocStatus()) ) + { + addDescription(Msg.getMsg(getCtx(), "Voided") + " (" + getPayAmt() + ")"); + setPayAmt(Env.ZERO); + setDiscountAmt(Env.ZERO); + setWriteOffAmt(Env.ZERO); + setOverUnderAmt(Env.ZERO); + setIsAllocated(false); + // Unlink & De-Allocate + deAllocate(); + } + else + return reverseCorrectIt(); + + // + setProcessed(true); + setDocAction(DOCACTION_None); + return true; + } // voidIt + + /** + * Close Document. + * @return true if success + */ + public boolean closeIt() + { + log.info(toString()); + setDocAction(DOCACTION_None); + return true; + } // closeIt + + /** + * Reverse Correction + * @return true if success + */ + public boolean reverseCorrectIt() + { + log.info(toString()); + + // Std Period open? + Timestamp dateAcct = getDateAcct(); + if (!MPeriod.isOpen(getCtx(), dateAcct, + isReceipt() ? MDocType.DOCBASETYPE_ARReceipt : MDocType.DOCBASETYPE_APPayment)) + dateAcct = new Timestamp(System.currentTimeMillis()); + + // Auto Reconcile if not on Bank Statement + boolean reconciled = false; // getC_BankStatementLine_ID() == 0; + + // Create Reversal + MPayment reversal = new MPayment (getCtx(), 0, get_TrxName()); + copyValues(this, reversal); + reversal.setClientOrg(this); + reversal.setC_Order_ID(0); + reversal.setC_Invoice_ID(0); + reversal.setDateAcct(dateAcct); + // + reversal.setDocumentNo(getDocumentNo() + REVERSE_INDICATOR); // indicate reversals + reversal.setDocStatus(DOCSTATUS_Drafted); + reversal.setDocAction(DOCACTION_Complete); + // + reversal.setPayAmt(getPayAmt().negate()); + reversal.setDiscountAmt(getDiscountAmt().negate()); + reversal.setWriteOffAmt(getWriteOffAmt().negate()); + reversal.setOverUnderAmt(getOverUnderAmt().negate()); + // + reversal.setIsAllocated(true); + reversal.setIsReconciled(reconciled); // to put on bank statement + reversal.setIsOnline(false); + reversal.setIsApproved(true); + reversal.setR_PnRef(null); + reversal.setR_Result(null); + reversal.setR_RespMsg(null); + reversal.setR_AuthCode(null); + reversal.setR_Info(null); + reversal.setProcessing(false); + reversal.setOProcessing("N"); + reversal.setProcessed(false); + reversal.setPosted(false); + reversal.setDescription(getDescription()); + reversal.addDescription("{->" + getDocumentNo() + ")"); + reversal.save(get_TrxName()); + // Post Reversal + if (!reversal.processIt(DocAction.ACTION_Complete)) + { + m_processMsg = "Reversal ERROR: " + reversal.getProcessMsg(); + return false; + } + reversal.closeIt(); + reversal.setDocStatus(DOCSTATUS_Reversed); + reversal.setDocAction(DOCACTION_None); + reversal.save(get_TrxName()); + + // Unlink & De-Allocate + deAllocate(); + setIsReconciled (reconciled); + setIsAllocated (true); // the allocation below is overwritten + // Set Status + addDescription("(" + reversal.getDocumentNo() + "<-)"); + setDocStatus(DOCSTATUS_Reversed); + setDocAction(DOCACTION_None); + setProcessed(true); + + // Create automatic Allocation + MAllocationHdr alloc = new MAllocationHdr (getCtx(), false, + getDateTrx(), getC_Currency_ID(), + Msg.translate(getCtx(), "C_Payment_ID") + ": " + reversal.getDocumentNo(), get_TrxName()); + alloc.setAD_Org_ID(getAD_Org_ID()); + if (!alloc.save()) + log.warning("Automatic allocation - hdr not saved"); + else + { + // Original Allocation + MAllocationLine aLine = new MAllocationLine (alloc, getPayAmt(true), + Env.ZERO, Env.ZERO, Env.ZERO); + aLine.setDocInfo(getC_BPartner_ID(), 0, 0); + aLine.setPaymentInfo(getC_Payment_ID(), 0); + if (!aLine.save(get_TrxName())) + log.warning("Automatic allocation - line not saved"); + // Reversal Allocation + aLine = new MAllocationLine (alloc, reversal.getPayAmt(true), + Env.ZERO, Env.ZERO, Env.ZERO); + aLine.setDocInfo(reversal.getC_BPartner_ID(), 0, 0); + aLine.setPaymentInfo(reversal.getC_Payment_ID(), 0); + if (!aLine.save(get_TrxName())) + log.warning("Automatic allocation - reversal line not saved"); + } + alloc.processIt(DocAction.ACTION_Complete); + alloc.save(get_TrxName()); + // + StringBuffer info = new StringBuffer (reversal.getDocumentNo()); + info.append(" - @C_AllocationHdr_ID@: ").append(alloc.getDocumentNo()); + + // Update BPartner + if (getC_BPartner_ID() != 0) + { + MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName()); + bp.setTotalOpenBalance(); + bp.save(get_TrxName()); + } + + m_processMsg = info.toString(); + return true; + } // reverseCorrectionIt + + /** + * Get Bank Statement Line of payment or 0 + * @return id or 0 + */ + private int getC_BankStatementLine_ID() + { + String sql = "SELECT C_BankStatementLine_ID FROM C_BankStatementLine WHERE C_Payment_ID=?"; + int id = DB.getSQLValue(get_TrxName(), sql, getC_Payment_ID()); + if (id < 0) + return 0; + return id; + } // getC_BankStatementLine_ID + + /** + * Reverse Accrual - none + * @return true if success + */ + public boolean reverseAccrualIt() + { + log.info(toString()); + return false; + } // reverseAccrualIt + + /** + * Re-activate + * @return true if success + */ + public boolean reActivateIt() + { + log.info(toString()); + if (reverseCorrectIt()) + return true; + return false; + } // reActivateIt + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MPayment["); + sb.append(get_ID()).append("-").append(getDocumentNo()) + .append(",Receipt=").append(isReceipt()) + .append(",PayAmt=").append(getPayAmt()) + .append(",Discount=").append(getDiscountAmt()) + .append(",WriteOff=").append(getWriteOffAmt()) + .append(",OverUnder=").append(getOverUnderAmt()); + return sb.toString (); + } // toString + + /** + * Get Document Info + * @return document info (untranslated) + */ + public String getDocumentInfo() + { + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + return dt.getName() + " " + getDocumentNo(); + } // getDocumentInfo + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + // ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.PAYMENT, getC_Payment_ID()); + // if (re == null) + return null; + // return re.getPDF(file); + } // createPDF + + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getDocumentNo()); + // : Total Lines = 123.00 (#1) + sb.append(": ") + .append(Msg.translate(getCtx(),"PayAmt")).append("=").append(getPayAmt()) + .append(",").append(Msg.translate(getCtx(),"WriteOffAmt")).append("=").append(getWriteOffAmt()); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner (Responsible) + * @return AD_User_ID + */ + public int getDoc_User_ID() + { + return getCreatedBy(); + } // getDoc_User_ID + + /** + * Get Document Approval Amount + * @return amount payment(AP) or write-off(AR) + */ + public BigDecimal getApprovalAmt() + { + if (isReceipt()) + return getWriteOffAmt(); + return getPayAmt(); + } // getApprovalAmt + +} // MPayment diff --git a/base/src/org/compiere/model/MPaymentAllocate.java b/base/src/org/compiere/model/MPaymentAllocate.java new file mode 100644 index 0000000000..b0ad98d4af --- /dev/null +++ b/base/src/org/compiere/model/MPaymentAllocate.java @@ -0,0 +1,188 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.math.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Payment Allocate Model + * + * @author Jorg Janke + * @version $Id: MPaymentAllocate.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MPaymentAllocate extends X_C_PaymentAllocate +{ + /** + * Get active Payment Allocation of Payment + * @param parent payment + * @return array of allocations + */ + public static MPaymentAllocate[] get (MPayment parent) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_PaymentAllocate WHERE C_Payment_ID=? AND IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, parent.getC_Payment_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MPaymentAllocate (parent.getCtx(), rs, parent.get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + MPaymentAllocate[] retValue = new MPaymentAllocate[list.size ()]; + list.toArray (retValue); + return retValue; + } // get + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MPaymentAllocate.class); + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param C_PaymentAllocate_ID id + * @param trxName trx + */ + public MPaymentAllocate (Properties ctx, int C_PaymentAllocate_ID, String trxName) + { + super (ctx, C_PaymentAllocate_ID, trxName); + if (C_PaymentAllocate_ID == 0) + { + // setC_Payment_ID (0); // Parent + // setC_Invoice_ID (0); + setAmount (Env.ZERO); + setDiscountAmt (Env.ZERO); + setOverUnderAmt (Env.ZERO); + setWriteOffAmt (Env.ZERO); + setInvoiceAmt(Env.ZERO); + } + } // MPaymentAllocate + + /** The Invoice */ + private MInvoice m_invoice = null; + + /** + * Load Cosntructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MPaymentAllocate (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MPaymentAllocate + + /** + * Set C_Invoice_ID + * @param C_Invoice_ID id + */ + public void setC_Invoice_ID (int C_Invoice_ID) + { + super.setC_Invoice_ID (C_Invoice_ID); + m_invoice = null; + } // setC_Invoice_ID + + /** + * Get Invoice + * @return invoice + */ + public MInvoice getInvoice() + { + if (m_invoice == null && getC_Invoice_ID() != 0) + m_invoice = new MInvoice(getCtx(), getC_Invoice_ID(), get_TrxName()); + return m_invoice; + } // getInvoice + + /** + * Get BPartner of Invoice + * @return bp + */ + public int getC_BPartner_ID() + { + if (m_invoice == null) + getInvoice(); + if (m_invoice == null) + return 0; + return m_invoice.getC_BPartner_ID(); + } // getC_BPartner_ID + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + MPayment payment = new MPayment (getCtx(), getC_Payment_ID(), get_TrxName()); + if ((newRecord || is_ValueChanged("C_Invoice_ID")) + && (payment.getC_Charge_ID() != 0 + || payment.getC_Invoice_ID() != 0 + || payment.getC_Order_ID() != 0)) + { + log.saveError("PaymentIsAllocated", ""); + return false; + } + + BigDecimal check = getAmount() + .add(getDiscountAmt()) + .add(getWriteOffAmt()) + .add(getOverUnderAmt()); + if (check.compareTo(getInvoiceAmt()) != 0) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), + "@InvoiceAmt@(" + getInvoiceAmt() + + ") <> @Totals@(" + check + ")")); + return false; + } + + // Org + if (newRecord || is_ValueChanged("C_Invoice_ID")) + { + getInvoice(); + if (m_invoice != null) + setAD_Org_ID(m_invoice.getAD_Org_ID()); + } + + return true; + } // beforeSave + +} // MPaymentAllocate diff --git a/base/src/org/compiere/model/MPaymentBatch.java b/base/src/org/compiere/model/MPaymentBatch.java new file mode 100644 index 0000000000..a4d7cb1788 --- /dev/null +++ b/base/src/org/compiere/model/MPaymentBatch.java @@ -0,0 +1,95 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.ResultSet; +import java.util.Properties; + +/** + * Payment Batch Model + * + * @author Jorg Janke + * @version $Id: MPaymentBatch.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MPaymentBatch extends X_C_PaymentBatch +{ + /** + * Get Payment Batch for PaySelection + * @param ctx context + * @param C_PaySelection_ID id + * @param trxName transaction + * @return payment batch + */ + public static MPaymentBatch getForPaySelection (Properties ctx, int C_PaySelection_ID, String trxName) + { + MPaySelection ps = new MPaySelection (ctx, C_PaySelection_ID, trxName); + MPaymentBatch retValue = new MPaymentBatch (ps); + return retValue; + } // getForPaySelection + + /** + * Standard Constructor + * @param ctx context + * @param C_PaymentBatch_ID id + * @param trxName transaction + */ + public MPaymentBatch (Properties ctx, int C_PaymentBatch_ID, String trxName) + { + super(ctx, C_PaymentBatch_ID, trxName); + if (C_PaymentBatch_ID == 0) + { + // setName (null); + setProcessed (false); + setProcessing (false); + } + } // MPaymentBatch + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPaymentBatch (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPaymentBatch + + /** + * New Constructor + * @param ctx context + * @param Name name + * @param trxName trx + */ + public MPaymentBatch (Properties ctx, String Name, String trxName) + { + this (ctx, 0, trxName); + setName (Name); + } // MPaymentBatch + + /** + * Parent Constructor + * @param ps Pay Selection + */ + public MPaymentBatch (MPaySelection ps) + { + this (ps.getCtx(), 0, ps.get_TrxName()); + setClientOrg(ps); + setName (ps.getName()); + } // MPaymentBatch + +} // MPaymentBatch diff --git a/base/src/org/compiere/model/MPaymentProcessor.java b/base/src/org/compiere/model/MPaymentProcessor.java new file mode 100644 index 0000000000..691868d082 --- /dev/null +++ b/base/src/org/compiere/model/MPaymentProcessor.java @@ -0,0 +1,189 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Payment Processor Model + * + * @author Jorg Janke + * @version $Id: MPaymentProcessor.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MPaymentProcessor extends X_C_PaymentProcessor +{ + /** + * Get BankAccount & PaymentProcessor + * @param ctx context + * @param tender optional Tender see TENDER_ + * @param CCType optional CC Type see CC_ + * @param AD_Client_ID Client + * @param C_Currency_ID Currency (ignored) + * @param Amt Amount (ignored) + * @param trxName transaction + * @return Array of BankAccount[0] & PaymentProcessor[1] or null + */ + protected static MPaymentProcessor[] find (Properties ctx, + String tender, String CCType, + int AD_Client_ID, int C_Currency_ID, BigDecimal Amt, String trxName) + { + ArrayList list = new ArrayList(); + StringBuffer sql = new StringBuffer("SELECT * " + + "FROM C_PaymentProcessor " + + "WHERE AD_Client_ID=? AND IsActive='Y'" // #1 + + " AND (C_Currency_ID IS NULL OR C_Currency_ID=?)" // #2 + + " AND (MinimumAmt IS NULL OR MinimumAmt = 0 OR MinimumAmt <= ?)"); // #3 + if (MPayment.TENDERTYPE_DirectDeposit.equals(tender)) + sql.append(" AND AcceptDirectDeposit='Y'"); + else if (MPayment.TENDERTYPE_DirectDebit.equals(tender)) + sql.append(" AND AcceptDirectDebit='Y'"); + else if (MPayment.TENDERTYPE_Check.equals(tender)) + sql.append(" AND AcceptCheck='Y'"); + // CreditCards + else if (MPayment.CREDITCARDTYPE_ATM.equals(CCType)) + sql.append(" AND AcceptATM='Y'"); + else if (MPayment.CREDITCARDTYPE_Amex.equals(CCType)) + sql.append(" AND AcceptAMEX='Y'"); + else if (MPayment.CREDITCARDTYPE_Visa.equals(CCType)) + sql.append(" AND AcceptVISA='Y'"); + else if (MPayment.CREDITCARDTYPE_MasterCard.equals(CCType)) + sql.append(" AND AcceptMC='Y'"); + else if (MPayment.CREDITCARDTYPE_Diners.equals(CCType)) + sql.append(" AND AcceptDiners='Y'"); + else if (MPayment.CREDITCARDTYPE_Discover.equals(CCType)) + sql.append(" AND AcceptDiscover='Y'"); + else if (MPayment.CREDITCARDTYPE_PurchaseCard.equals(CCType)) + sql.append(" AND AcceptCORPORATE='Y'"); + // + try + { + PreparedStatement pstmt = DB.prepareStatement(sql.toString(), trxName); + pstmt.setInt(1, AD_Client_ID); + pstmt.setInt(2, C_Currency_ID); + pstmt.setBigDecimal(3, Amt); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MPaymentProcessor (ctx, rs, trxName)); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + s_log.log(Level.SEVERE, "find - " + sql, e); + return null; + } + // + if (list.size() == 0) + s_log.warning("find - not found - AD_Client_ID=" + AD_Client_ID + + ", C_Currency_ID=" + C_Currency_ID + ", Amt=" + Amt); + else + s_log.fine("find - #" + list.size() + " - AD_Client_ID=" + AD_Client_ID + + ", C_Currency_ID=" + C_Currency_ID + ", Amt=" + Amt); + MPaymentProcessor[] retValue = new MPaymentProcessor[list.size()]; + list.toArray(retValue); + return retValue; + } // find + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MPaymentProcessor.class); + + + /************************************************************************** + * Payment Processor Model + * @param ctx context + * @param C_PaymentProcessor_ID payment processor + * @param trxName transaction + */ + public MPaymentProcessor (Properties ctx, int C_PaymentProcessor_ID, String trxName) + { + super (ctx, C_PaymentProcessor_ID, trxName); + if (C_PaymentProcessor_ID == 0) + { + // setC_BankAccount_ID (0); // Parent + // setUserID (null); + // setPassword (null); + // setHostAddress (null); + // setHostPort (0); + setCommission (Env.ZERO); + setAcceptVisa (false); + setAcceptMC (false); + setAcceptAMEX (false); + setAcceptDiners (false); + setCostPerTrx (Env.ZERO); + setAcceptCheck (false); + setRequireVV (false); + setAcceptCorporate (false); + setAcceptDiscover (false); + setAcceptATM (false); + setAcceptDirectDeposit(false); + setAcceptDirectDebit(false); + // setName (null); + } + } // MPaymentProcessor + + /** + * Payment Processor Model + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPaymentProcessor (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPaymentProcessor + + /** + * String representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MPaymentProcessor[") + .append(get_ID ()).append("-").append(getName()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Does Payment Processor accepts tender / CC + * @param TenderType tender type + * @param CreditCardType credit card type + * @return true if acceptes + */ + public boolean accepts (String TenderType, String CreditCardType) + { + if ((MPayment.TENDERTYPE_DirectDeposit.equals(TenderType) && isAcceptDirectDeposit()) + || (MPayment.TENDERTYPE_DirectDebit.equals(TenderType) && isAcceptDirectDebit()) + || (MPayment.TENDERTYPE_Check.equals(TenderType) && isAcceptCheck()) + // + || (MPayment.CREDITCARDTYPE_ATM.equals(CreditCardType) && isAcceptATM()) + || (MPayment.CREDITCARDTYPE_Amex.equals(CreditCardType) && isAcceptAMEX()) + || (MPayment.CREDITCARDTYPE_PurchaseCard.equals(CreditCardType) && isAcceptCorporate()) + || (MPayment.CREDITCARDTYPE_Diners.equals(CreditCardType) && isAcceptDiners()) + || (MPayment.CREDITCARDTYPE_Discover.equals(CreditCardType) && isAcceptDiscover()) + || (MPayment.CREDITCARDTYPE_MasterCard.equals(CreditCardType) && isAcceptMC()) + || (MPayment.CREDITCARDTYPE_Visa.equals(CreditCardType) && isAcceptVisa())) + return true; + return false; + } // accepts + +} // MPaymentProcessor diff --git a/base/src/org/compiere/model/MPaymentTerm.java b/base/src/org/compiere/model/MPaymentTerm.java new file mode 100644 index 0000000000..0af349ee6f --- /dev/null +++ b/base/src/org/compiere/model/MPaymentTerm.java @@ -0,0 +1,305 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Payment Term Model + * + * @author Jorg Janke + * @version $Id: MPaymentTerm.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MPaymentTerm extends X_C_PaymentTerm +{ + + /** + * Standard Constructor + * @param ctx context + * @param C_PaymentTerm_ID id + * @param trxName transaction + */ + public MPaymentTerm(Properties ctx, int C_PaymentTerm_ID, String trxName) + { + super(ctx, C_PaymentTerm_ID, trxName); + if (C_PaymentTerm_ID == 0) + { + setAfterDelivery (false); + setNetDays (0); + setDiscount (Env.ZERO); + setDiscount2 (Env.ZERO); + setDiscountDays (0); + setDiscountDays2 (0); + setGraceDays (0); + setIsDueFixed (false); + setIsValid (false); + } } // MPaymentTerm + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPaymentTerm(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPaymentTerm + + /** 100 */ + private final static BigDecimal HUNDRED = new BigDecimal(100); + + /** Payment Schedule children */ + private MPaySchedule[] m_schedule; + + /** + * Get Payment Schedule + * @param requery if true re-query + * @return array of schedule + */ + public MPaySchedule[] getSchedule (boolean requery) + { + if (m_schedule != null && !requery) + return m_schedule; + String sql = "SELECT * FROM C_PaySchedule WHERE C_PaymentTerm_ID=? ORDER BY NetDays"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_PaymentTerm_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + MPaySchedule ps = new MPaySchedule(getCtx(), rs, get_TrxName()); + ps.setParent(this); + list.add (ps); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getSchedule", e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + m_schedule = new MPaySchedule[list.size()]; + list.toArray(m_schedule); + return m_schedule; + } // getSchedule + + /** + * Validate Payment Term & Schedule + * @return Validation Message @OK@ or error + */ + public String validate() + { + getSchedule(true); + if (m_schedule.length == 0) + { + setIsValid(true); + return "@OK@"; + } + if (m_schedule.length == 1) + { + setIsValid(false); + return "@Invalid@ @Count@ # = 1 (@C_PaySchedule_ID@)"; + } + + // Add up + BigDecimal total = Env.ZERO; + for (int i = 0; i < m_schedule.length; i++) + { + BigDecimal percent = m_schedule[i].getPercentage(); + if (percent != null) + total = total.add(percent); + } + boolean valid = total.compareTo(HUNDRED) == 0; + setIsValid (valid); + for (int i = 0; i < m_schedule.length; i++) + { + if (m_schedule[i].isValid() != valid) + { + m_schedule[i].setIsValid(valid); + m_schedule[i].save(); + } + } + String msg = "@OK@"; + if (!valid) + msg = "@Total@ = " + total + " - @Difference@ = " + HUNDRED.subtract(total); + return Msg.parseTranslation(getCtx(), msg); + } // validate + + + /************************************************************************* + * Apply Payment Term to Invoice - + * @param C_Invoice_ID invoice + * @return true if payment schedule is valid + */ + public boolean apply (int C_Invoice_ID) + { + MInvoice invoice = new MInvoice (getCtx(), C_Invoice_ID, get_TrxName()); + if (invoice == null || invoice.get_ID() == 0) + { + log.log(Level.SEVERE, "apply - Not valid C_Invoice_ID=" + C_Invoice_ID); + return false; + } + return apply (invoice); + } // apply + + /** + * Apply Payment Term to Invoice + * @param invoice invoice + * @return true if payment schedule is valid + */ + public boolean apply (MInvoice invoice) + { + if (invoice == null || invoice.get_ID() == 0) + { + log.log(Level.SEVERE, "No valid invoice - " + invoice); + return false; + } + + if (!isValid()) + return applyNoSchedule (invoice); + // + getSchedule(true); + if (m_schedule.length <= 1) + return applyNoSchedule (invoice); + else // only if valid + return applySchedule(invoice); + } // apply + + /** + * Apply Payment Term without schedule to Invoice + * @param invoice invoice + * @return false as no payment schedule + */ + private boolean applyNoSchedule (MInvoice invoice) + { + deleteInvoicePaySchedule (invoice.getC_Invoice_ID(), invoice.get_TrxName()); + // updateInvoice + if (invoice.getC_PaymentTerm_ID() != getC_PaymentTerm_ID()) + invoice.setC_PaymentTerm_ID(getC_PaymentTerm_ID()); + if (invoice.isPayScheduleValid()) + invoice.setIsPayScheduleValid(false); + return false; + } // applyNoSchedule + + /** + * Apply Payment Term with schedule to Invoice + * @param invoice invoice + * @return true if payment schedule is valid + */ + private boolean applySchedule (MInvoice invoice) + { + deleteInvoicePaySchedule (invoice.getC_Invoice_ID(), invoice.get_TrxName()); + // Create Schedule + MInvoicePaySchedule ips = null; + BigDecimal remainder = invoice.getGrandTotal(); + for (int i = 0; i < m_schedule.length; i++) + { + ips = new MInvoicePaySchedule (invoice, m_schedule[i]); + ips.save(invoice.get_TrxName()); + log.fine(ips.toString()); + remainder = remainder.subtract(ips.getDueAmt()); + } // for all schedules + // Remainder - update last + if (remainder.compareTo(Env.ZERO) != 0 && ips != null) + { + ips.setDueAmt(ips.getDueAmt().add(remainder)); + ips.save(invoice.get_TrxName()); + log.fine("Remainder=" + remainder + " - " + ips); + } + + // updateInvoice + if (invoice.getC_PaymentTerm_ID() != getC_PaymentTerm_ID()) + invoice.setC_PaymentTerm_ID(getC_PaymentTerm_ID()); + return invoice.validatePaySchedule(); + } // applySchedule + + /** + * Delete existing Invoice Payment Schedule + * @param C_Invoice_ID id + * @param trxName transaction + */ + private void deleteInvoicePaySchedule (int C_Invoice_ID, String trxName) + { + String sql = "DELETE C_InvoicePaySchedule WHERE C_Invoice_ID=" + C_Invoice_ID; + int no = DB.executeUpdate(sql, trxName); + log.fine("C_Invoice_ID=" + C_Invoice_ID + " - #" + no); + } // deleteInvoicePaySchedule + + + /************************************************************************** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MPaymentTerm["); + sb.append(get_ID()).append("-").append(getName()) + .append(",Valid=").append(isValid()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (isDueFixed()) + { + int dd = getFixMonthDay(); + if (dd < 1 || dd > 31) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@Invalid@ @FixMonthDay@")); + return false; + } + dd = getFixMonthCutoff(); + if (dd < 1 || dd > 31) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@Invalid@ @FixMonthCutoff@")); + return false; + } + } + + if (!newRecord || !isValid()) + validate(); + return true; + } // beforeSave + +} // MPaymentTerm diff --git a/base/src/org/compiere/model/MPaymentValidate.java b/base/src/org/compiere/model/MPaymentValidate.java new file mode 100644 index 0000000000..4c37123f32 --- /dev/null +++ b/base/src/org/compiere/model/MPaymentValidate.java @@ -0,0 +1,438 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.util.*; +import org.compiere.util.*; + + +/** + * Payment Validion Routines + * + * @author Jorg Janke + * @version $Id: MPaymentValidate.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MPaymentValidate +{ + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MPaymentValidate.class); + + + /** + * Is this a valid Credit Card Exp Date? + * @param mmyy Exp in form of mmyy + * @return "" or Error AD_Message + */ + public static String validateCreditCardExp (String mmyy) + { + String exp = checkNumeric(mmyy); + if (exp.length() != 4) + return "CreditCardExpFormat"; + // + String mmStr = exp.substring(0,2); + String yyStr = exp.substring(2,4); + // + int mm = 0; + int yy = 0; + try + { + mm = Integer.parseInt(mmStr); + yy = Integer.parseInt(yyStr); + } + catch (Exception e) + { + return "CreditCardExpFormat"; + } + return validateCreditCardExp(mm,yy); + } // validateCreditCardExp + + /** + * Return Month of Exp + * @param mmyy Exp in form of mmyy + * @return month + */ + public static int getCreditCardExpMM (String mmyy) + { + String mmStr = mmyy.substring(0,2); + int mm = 0; + try + { + mm = Integer.parseInt(mmStr); + } + catch (Exception e) + { + } + return mm; + } // getCreditCardExpMM + + /** + * Return Year of Exp + * @param mmyy Exp in form of mmyy + * @return year + */ + public static int getCreditCardExpYY (String mmyy) + { + String yyStr = mmyy.substring(2); + int yy = 0; + try + { + yy = Integer.parseInt(yyStr); + } + catch (Exception e) + { + } + return yy; + } // getCreditCardExpYY + + /** + * Is this a valid Credit Card Exp Date? + * @param mm month + * @param yy year + * @return "" or Error AD_Message + */ + public static String validateCreditCardExp (int mm, int yy) + { + if (mm < 1 || mm > 12) + return "CreditCardExpMonth"; + // if (yy < 0 || yy > EXP_YEAR) + // return "CreditCardExpYear"; + + // Today's date + Calendar cal = Calendar.getInstance(); + int year = cal.get(Calendar.YEAR) - 2000; // two digits + int month = cal.get(Calendar.MONTH) + 1; // zero based + // + if (yy < year) + return "CreditCardExpired"; + else if (yy == year && mm < month) + return "CreditCardExpired"; + return ""; + } // validateCreditCardExp + + + /** + * Validate Credit Card Number. + * - Based on LUHN formula + * @param creditCardNumber credit card number + * @return "" or Error AD_Message + */ + public static String validateCreditCardNumber (String creditCardNumber) + { + if (creditCardNumber == null || creditCardNumber.length() == 0) + return "CreditCardNumberError"; + + /** + * 1: Double the value of alternate digits beginning with + * the first right-hand digit (low order). + * 2: Add the individual digits comprising the products + * obtained in step 1 to each of the unaffected digits + * in the original number. + * 3: Subtract the total obtained in step 2 from the next higher + * number ending in 0 [this in the equivalent of calculating + * the "tens complement" of the low order digit (unit digit) + * of the total]. + * If the total obtained in step 2 is a number ending in zero + * (30, 40 etc.), the check digit is 0. + * Example: + * Account number: 4992 73 9871 6 + * + * 4 9 9 2 7 3 9 8 7 1 6 + * x2 x2 x2 x2 x2 + * ------------------------------- + * 4 18 9 4 7 6 9 16 7 2 6 + * + * 4 + 1 + 8 + 9 + 4 + 7 + 6 + 9 + 1 + 6 + 7 + 2 + 6 = 70 + * 70 % 10 = 0 + */ + + // Clean up number + String ccNumber1 = checkNumeric(creditCardNumber); + int ccLength = ccNumber1.length(); + // Reverse string + StringBuffer buf = new StringBuffer(); + for (int i = ccLength; i != 0; i--) + buf.append(ccNumber1.charAt(i-1)); + String ccNumber = buf.toString(); + + int sum = 0; + for (int i = 0; i < ccLength; i++) + { + int digit = Character.getNumericValue(ccNumber.charAt(i)); + if (i % 2 == 1) + { + digit *= 2; + if (digit > 9) + digit -= 9; + } + sum += digit; + } + if (sum % 10 == 0) + return ""; + + s_log.fine("validateCreditCardNumber - " + creditCardNumber + " -> " + + ccNumber + ", Luhn=" + sum); + return "CreditCardNumberError"; + } // validateCreditCardNumber + + /** + * Validate Credit Card Number. + * - Check Card Type and Length + * @param creditCardNumber CC Number + * @param creditCardType CC Type + * @return "" or Error AD_Message + */ + public static String validateCreditCardNumber (String creditCardNumber, String creditCardType) + { + if (creditCardNumber == null || creditCardType == null) + return "CreditCardNumberError"; + + // http://www.beachnet.com/~hstiles/cardtype.html + // http://staff.semel.fi/~kribe/document/luhn.htm + + String ccStartList = ""; // comma separated list of starting numbers + String ccLengthList = ""; // comma separated list of lengths + // + if (creditCardType.equals(MPayment.CREDITCARDTYPE_MasterCard)) + { + ccStartList = "51,52,53,54,55"; + ccLengthList = "16"; + } + else if (creditCardType.equals(MPayment.CREDITCARDTYPE_Visa)) + { + ccStartList = "4"; + ccLengthList = "13,16"; + } + else if (creditCardType.equals(MPayment.CREDITCARDTYPE_Amex)) + { + ccStartList = "34,37"; + ccLengthList = "15"; + } + else if (creditCardType.equals(MPayment.CREDITCARDTYPE_Discover)) + { + ccStartList = "6011"; + ccLengthList = "16"; + } + else if (creditCardType.equals(MPayment.CREDITCARDTYPE_Diners)) + { + ccStartList = "300,301,302,303,304,305,36,38"; + ccLengthList = "14"; + } + else + { + // enRouteCard + ccStartList = "2014,2149"; + ccLengthList = "15"; + // JCBCard + ccStartList += ",3088,3096,3112,3158,3337,3528"; + ccLengthList += ",16"; + // JCBCard + ccStartList += ",2131,1800"; + ccLengthList += ",15"; + } + + // Clean up number + String ccNumber = checkNumeric(creditCardNumber); + + /** + * Check Length + */ + int ccLength = ccNumber.length(); + boolean ccLengthOK = false; + StringTokenizer st = new StringTokenizer(ccLengthList, ",", false); + while (st.hasMoreTokens() && !ccLengthOK) + { + int l = Integer.parseInt(st.nextToken()); + if (ccLength == l) + ccLengthOK = true; + } + if (!ccLengthOK) + { + s_log.fine("validateCreditCardNumber Length=" + + ccLength + " <> " + ccLengthList); + return "CreditCardNumberError"; + } + + /** + * Check Start Digits + */ + boolean ccIdentified = false; + st = new StringTokenizer(ccStartList, ",", false); + while (st.hasMoreTokens() && !ccIdentified) + { + if (ccNumber.startsWith(st.nextToken())) + ccIdentified = true; + } + if (!ccIdentified) + s_log.fine("validateCreditCardNumber Type=" + + creditCardType + " <> " + ccStartList); + + // + String check = validateCreditCardNumber(ccNumber); + if (check.length() != 0) + return check; + if (!ccIdentified) + return "CreditCardNumberProblem?"; + return ""; + } // validateCreditCardNumber + + + /** + * Validate Validation Code + * @param creditCardVV CC Verification Code + * @return "" or Error AD_Message + */ + public static String validateCreditCardVV (String creditCardVV) + { + if (creditCardVV == null) + return ""; + int length = checkNumeric(creditCardVV).length(); + if (length == 3 || length == 4) + return ""; + try + { + Integer.parseInt (creditCardVV); + return ""; + } + catch (NumberFormatException ex) + { + s_log.fine("validateCreditCardVV - " + ex); + } + s_log.fine("validateCreditCardVV - length=" + length); + return "CreditCardVVError"; + } // validateCreditCardVV + + /** + * Validate Validation Code + * @param creditCardVV CC Verification Code + * @param creditCardType CC Type see CC_ + * @return "" or Error AD_Message + */ + public static String validateCreditCardVV (String creditCardVV, String creditCardType) + { + // no data + if (creditCardVV == null || creditCardVV.length() == 0 + || creditCardType == null || creditCardType.length() == 0) + return ""; + + int length = checkNumeric(creditCardVV).length(); + + // Amex = 4 digits + if (creditCardType.equals(MPayment.CREDITCARDTYPE_Amex)) + { + if (length == 4) + { + try + { + Integer.parseInt (creditCardVV); + return ""; + } + catch (NumberFormatException ex) + { + s_log.fine("validateCreditCardVV - " + ex); + } + } + s_log.fine("validateCreditCardVV(4) CC=" + creditCardType + ", length=" + length); + return "CreditCardVVError"; + } + // Visa & MasterCard - 3 digits + if (creditCardType.equals(MPayment.CREDITCARDTYPE_Visa) + || creditCardType.equals(MPayment.CREDITCARDTYPE_MasterCard)) + { + if (length == 3) + { + try + { + Integer.parseInt (creditCardVV); + return ""; + } + catch (NumberFormatException ex) + { + s_log.fine("validateCreditCardVV - " + ex); + } + } + s_log.fine("validateCreditCardVV(3) CC=" + creditCardType + ", length=" + length); + return "CreditCardVVError"; + } + + // Other + return ""; + } // validateCreditCardVV + + + /************************************************************************** + * Validate Routing Number + * @param routingNo Routing No + * @return "" or Error AD_Message + */ + public static String validateRoutingNo (String routingNo) + { + int length = checkNumeric(routingNo).length(); + // US - length 9 + // Germany - length 8 + // Japan - 7 + if (length == 7 || length == 8 || length == 9) + return ""; + return "PaymentBankRoutingNotValid"; + } // validateBankRoutingNo + + /** + * Validate Account No + * @param AccountNo AccountNo + * @return "" or Error AD_Message + */ + public static String validateAccountNo (String AccountNo) + { + int length = checkNumeric(AccountNo).length(); + if (length > 0) + return ""; + return "PaymentBankAccountNotValid"; + } // validateBankAccountNo + + /** + * Validate Check No + * @param CheckNo CheckNo + * @return "" or Error AD_Message + */ + public static String validateCheckNo (String CheckNo) + { + int length = checkNumeric(CheckNo).length(); + if (length > 0) + return ""; + return "PaymentBankCheckNotValid"; + } // validateBankCheckNo + + /** + * Check Numeric + * @param data input + * @return the digits of the data - ignore the rest + */ + public static String checkNumeric (String data) + { + if (data == null || data.length() == 0) + return ""; + // Remove all non Digits + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < data.length(); i++) + { + if (Character.isDigit(data.charAt(i))) + sb.append(data.charAt(i)); + } + return sb.toString(); + } // checkNumeric + + +} // MPaymentValidate diff --git a/base/src/org/compiere/model/MPeriod.java b/base/src/org/compiere/model/MPeriod.java new file mode 100644 index 0000000000..f1e1d46784 --- /dev/null +++ b/base/src/org/compiere/model/MPeriod.java @@ -0,0 +1,472 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Calendar Period Model + * + * @author Jorg Janke + * @version $Id: MPeriod.java,v 1.4 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MPeriod extends X_C_Period +{ + /** + * Get Period from Cache + * @param ctx context + * @param C_Period_ID id + * @return MPeriod + */ + public static MPeriod get (Properties ctx, int C_Period_ID) + { + Integer key = new Integer (C_Period_ID); + MPeriod retValue = (MPeriod) s_cache.get (key); + if (retValue != null) + return retValue; + // + retValue = new MPeriod (ctx, C_Period_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** + * Find standard Period of DateAcct based on Client Calendar + * @param ctx context + * @param DateAcct date + * @return active Period or null + */ + public static MPeriod get (Properties ctx, Timestamp DateAcct) + { + if (DateAcct == null) + return null; + // Search in Cache first + Iterator it = s_cache.values().iterator(); + while (it.hasNext()) + { + MPeriod period = (MPeriod)it.next(); + if (period.isStandardPeriod() && period.isInPeriod(DateAcct)) + return period; + } + + // Get it from DB + MPeriod retValue = null; + int AD_Client_ID = Env.getAD_Client_ID(ctx); + String sql = "SELECT * " + + "FROM C_Period " + + "WHERE C_Year_ID IN " + + "(SELECT C_Year_ID FROM C_Year WHERE C_Calendar_ID= " + + "(SELECT C_Calendar_ID FROM AD_ClientInfo WHERE AD_Client_ID=?))" + + " AND ? BETWEEN TRUNC(StartDate) AND TRUNC(EndDate)" + + " AND IsActive='Y' AND PeriodType='S'"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt (1, AD_Client_ID); + pstmt.setTimestamp (2, TimeUtil.getDay(DateAcct)); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + MPeriod period = new MPeriod(ctx, rs, null); + Integer key = new Integer (period.getC_Period_ID()); + s_cache.put (key, period); + if (period.isStandardPeriod()) + retValue = period; + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException e) + { + s_log.log(Level.SEVERE, "DateAcct=" + DateAcct, e); + } + if (retValue == null) + s_log.warning("No Standard Period for " + DateAcct + + " (AD_Client_ID=" + AD_Client_ID + ")"); + return retValue; + } // get + + /** + * Find valid standard Period of DateAcct based on Client Calendar + * @param ctx context + * @param DateAcct date + * @return C_Period_ID or 0 + */ + public static int getC_Period_ID (Properties ctx, Timestamp DateAcct) + { + MPeriod period = get (ctx, DateAcct); + if (period == null) + return 0; + return period.getC_Period_ID(); + } // getC_Period_ID + + /** + * Is standard Period Open for Document Base Type + * @param ctx context + * @param DateAcct date + * @param DocBaseType base type + * @return true if open + */ + public static boolean isOpen (Properties ctx, Timestamp DateAcct, String DocBaseType) + { + if (DateAcct == null) + { + s_log.warning("No DateAcct"); + return false; + } + if (DocBaseType == null) + { + s_log.warning("No DocBaseType"); + return false; + } + MPeriod period = MPeriod.get (ctx, DateAcct); + if (period == null) + { + s_log.warning("No Period for " + DateAcct + " (" + DocBaseType + ")"); + return false; + } + boolean open = period.isOpen(DocBaseType); + if (!open) + s_log.warning(period.getName() + + ": Not open for " + DocBaseType + " (" + DateAcct + ")"); + return open; + } // isOpen + + /** + * Find first Year Period of DateAcct based on Client Calendar + * @param ctx context + * @param DateAcct date + * @return active first Period + */ + public static MPeriod getFirstInYear (Properties ctx, Timestamp DateAcct) + { + MPeriod retValue = null; + int AD_Client_ID = Env.getAD_Client_ID(ctx); + String sql = "SELECT * " + + "FROM C_Period " + + "WHERE C_Year_ID IN " + + "(SELECT p.C_Year_ID " + + "FROM AD_ClientInfo c" + + " INNER JOIN C_Year y ON (c.C_Calendar_ID=y.C_Calendar_ID)" + + " INNER JOIN C_Period p ON (y.C_Year_ID=p.C_Year_ID) " + + "WHERE c.AD_Client_ID=?" + + " AND ? BETWEEN StartDate AND EndDate)" + + " AND IsActive='Y' AND PeriodType='S' " + + "ORDER BY StartDate"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt (1, AD_Client_ID); + pstmt.setTimestamp (2, DateAcct); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) // first only + retValue = new MPeriod(ctx, rs, null); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + s_log.log(Level.SEVERE, sql, e); + } + return retValue; + } // getFirstInYear + + /** Cache */ + private static CCache s_cache = new CCache("C_Period", 10); + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MPeriod.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param C_Period_ID id + * @param trxName transaction + */ + public MPeriod (Properties ctx, int C_Period_ID, String trxName) + { + super (ctx, C_Period_ID, trxName); + if (C_Period_ID == 0) + { + // setC_Period_ID (0); // PK + // setC_Year_ID (0); // Parent + // setName (null); + // setPeriodNo (0); + // setStartDate (new Timestamp(System.currentTimeMillis())); + setPeriodType (PERIODTYPE_StandardCalendarPeriod); + } + } // MPeriod + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPeriod (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPeriod + + /** + * Parent constructor + * @param year year + * @param PeriodNo no + * @param name name + * @param startDate start + * @param endDate end + */ + public MPeriod (MYear year, int PeriodNo, String name, + Timestamp startDate,Timestamp endDate) + { + this (year.getCtx(), 0, year.get_TrxName()); + setClientOrg(year); + setC_Year_ID(year.getC_Year_ID()); + setPeriodNo(PeriodNo); + setName(name); + setStartDate(startDate); + setEndDate(endDate); + } // MPeriod + + + /** Period Controls */ + private MPeriodControl[] m_controls = null; + + /** + * Get Period Control + * @param requery requery + * @return period controls + */ + public MPeriodControl[] getPeriodControls (boolean requery) + { + if (m_controls != null && !requery) + return m_controls; + // + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_PeriodControl " + + "WHERE C_Period_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_Period_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add (new MPeriodControl (getCtx(), rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + m_controls = new MPeriodControl[list.size ()]; + list.toArray (m_controls); + return m_controls; + } // getPeriodControls + + /** + * Get Period Control + * @param DocBaseType Document Base Type + * @return period control or null + */ + public MPeriodControl getPeriodControl (String DocBaseType) + { + if (DocBaseType == null) + return null; + getPeriodControls(false); + for (int i = 0; i < m_controls.length; i++) + { + // log.fine("getPeriodControl - " + 1 + " - " + m_controls[i]); + if (DocBaseType.equals(m_controls[i].getDocBaseType())) + return m_controls[i]; + } + return null; + } // getPeriodControl + + /** + * Date In Period + * @param date date + * @return true if in period + */ + public boolean isInPeriod (Timestamp date) + { + if (date == null) + return false; + Timestamp dateOnly = TimeUtil.getDay(date); + Timestamp from = TimeUtil.getDay(getStartDate()); + if (dateOnly.before(from)) + return false; + Timestamp to = TimeUtil.getDay(getEndDate()); + if (dateOnly.after(to)) + return false; + return true; + } // isInPeriod + + /** + * Is Period Open for Doc Base Type + * @param DocBaseType document base type + * @return true if open + */ + public boolean isOpen (String DocBaseType) + { + if (!isActive()) + { + s_log.warning("Period not active: " + getName()); + return false; + } + + MAcctSchema as = MClient.get(getCtx(), getAD_Client_ID()).getAcctSchema(); + if (as != null && as.isAutoPeriodControl()) + { + // if (as.getC_Period_ID() == getC_Period_ID()) + // return true; + Timestamp today = new Timestamp (System.currentTimeMillis()); + Timestamp first = TimeUtil.addDays(today, - as.getPeriod_OpenHistory()); + Timestamp last = TimeUtil.addDays(today, as.getPeriod_OpenFuture()); + if (today.before(first)) + { + log.warning ("Today before first day - " + first); + return false; + } + if (today.after(last)) + { + log.warning ("Today after last day - " + first); + return false; + } + // We are OK + if (isInPeriod(today)) + { + as.setC_Period_ID(getC_Period_ID()); + as.save(); + } + return true; + } + + // Standard Period Control + if (DocBaseType == null) + { + log.warning(getName() + " - No DocBaseType"); + return false; + } + MPeriodControl pc = getPeriodControl (DocBaseType); + if (pc == null) + { + log.warning(getName() + " - Period Control not found for " + DocBaseType); + return false; + } + log.fine(getName() + ": " + DocBaseType); + return pc.isOpen(); + } // isOpen + + /** + * Standard Period + * @return true if standard calendar perios + */ + public boolean isStandardPeriod() + { + return PERIODTYPE_StandardCalendarPeriod.equals(getPeriodType()); + } // isStandardPeriod + + + /** + * Before Save. + * Truncate Dates + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Truncate Dates + Timestamp date = getStartDate(); + if (date != null) + setStartDate(TimeUtil.getDay(date)); + else + return false; + // + date = getEndDate(); + if (date != null) + setEndDate(TimeUtil.getDay(date)); + else + setEndDate(TimeUtil.getMonthLastDay(getStartDate())); + return true; + } // beforeSave + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (newRecord) + { + // SELECT Value FROM AD_Ref_List WHERE AD_Reference_ID=183 + MDocType[] types = MDocType.getOfClient(getCtx()); + int count = 0; + ArrayList baseTypes = new ArrayList(); + for (int i = 0; i < types.length; i++) + { + MDocType type = types[i]; + String DocBaseType = type.getDocBaseType(); + if (baseTypes.contains(DocBaseType)) + continue; + MPeriodControl pc = new MPeriodControl(this, DocBaseType); + if (pc.save()) + count++; + baseTypes.add (DocBaseType); + } + log.fine("PeriodControl #" + count); + } + return success; + } // afterSave + + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MPeriod["); + sb.append (get_ID()) + .append("-").append (getName()) + .append(", ").append(getStartDate()).append("-").append(getEndDate()) + .append ("]"); + return sb.toString (); + } // toString + +} // MPeriod diff --git a/base/src/org/compiere/model/MPeriodControl.java b/base/src/org/compiere/model/MPeriodControl.java new file mode 100644 index 0000000000..27436d22ab --- /dev/null +++ b/base/src/org/compiere/model/MPeriodControl.java @@ -0,0 +1,111 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Period Control Model + * + * @author Jorg Janke + * @version $Id: MPeriodControl.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MPeriodControl extends X_C_PeriodControl +{ + /** + * Standard Constructor + * @param ctx context + * @param C_PeriodControl_ID 0 + * @param trxName transaction + */ + public MPeriodControl (Properties ctx, int C_PeriodControl_ID, String trxName) + { + super(ctx, C_PeriodControl_ID, trxName); + if (C_PeriodControl_ID == 0) + { + // setC_Period_ID (0); + // setDocBaseType (null); + setPeriodAction (PERIODACTION_NoAction); + setPeriodStatus (PERIODSTATUS_NeverOpened); + } + } // MPeriodControl + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPeriodControl (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPeriodControl + + /** + * Parent Constructor + * @param period parent + * @param DocBaseType doc base type + */ + public MPeriodControl (MPeriod period, String DocBaseType) + { + this (period.getCtx(), period.getAD_Client_ID(), period.getC_Period_ID(), + DocBaseType, period.get_TrxName()); + } // MPeriodControl + + /** + * New Constructor + * @param ctx context + * @param AD_Client_ID client + * @param C_Period_ID period + * @param DocBaseType doc base type + * @param trxName transaction + */ + public MPeriodControl (Properties ctx, int AD_Client_ID, int C_Period_ID, + String DocBaseType, String trxName) + { + this (ctx, 0, trxName); + setClientOrg(AD_Client_ID, 0); + setC_Period_ID (C_Period_ID); + setDocBaseType (DocBaseType); + } // MPeriodControl + + /** + * Is Period Open + * @return true if open + */ + public boolean isOpen() + { + return PERIODSTATUS_Open.equals(getPeriodStatus()); + } // isOpen + + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MPeriodControl["); + sb.append(get_ID()).append(",").append(getDocBaseType()) + .append(",Status=").append(getPeriodStatus()) + .append ("]"); + return sb.toString (); + } // toString + +} // MPeriodControl + diff --git a/base/src/org/compiere/model/MPreference.java b/base/src/org/compiere/model/MPreference.java new file mode 100644 index 0000000000..3dc9803f05 --- /dev/null +++ b/base/src/org/compiere/model/MPreference.java @@ -0,0 +1,103 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.ResultSet; +import java.util.Properties; + +/** + * Preference Model + * + * @author Jorg Janke + * @version $Id: MPreference.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MPreference extends X_AD_Preference +{ + /** Null Indicator */ + public static String NULL = "null"; + + /** + * Standatrd Constructor + * @param ctx ctx + * @param AD_Preference_ID id + * @param trxName transaction + */ + public MPreference(Properties ctx, int AD_Preference_ID, String trxName) + { + super(ctx, AD_Preference_ID, trxName); + if (AD_Preference_ID == 0) + { + // setAD_Preference_ID (0); + // setAttribute (null); + // setValue (null); + } + } // MPreference + + /** + * Load Contsructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPreference(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPreference + + /** + * Full Constructor + * @param ctx context + * @param Attribute attribute + * @param Value value + * @param trxName trx + */ + public MPreference (Properties ctx, String Attribute, String Value, String trxName) + { + this (ctx, 0, trxName); + setAttribute (Attribute); + setValue (Value); + } // MPreference + + /** + * Before Save + * @param newRecord + * @return true if can be saved + */ + protected boolean beforeSave (boolean newRecord) + { + String value = getValue(); + if (value == null) + value = ""; + if (value.equals("-1")) + setValue(""); + return true; + } // beforeSave + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MPreference["); + sb.append (get_ID()).append("-") + .append(getAttribute()).append("-").append(getValue()) + .append ("]"); + return sb.toString (); + } // toString + +} // MPreference diff --git a/base/src/org/compiere/model/MPriceList.java b/base/src/org/compiere/model/MPriceList.java new file mode 100644 index 0000000000..6841796e3e --- /dev/null +++ b/base/src/org/compiere/model/MPriceList.java @@ -0,0 +1,269 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Price List Model + * + * @author Jorg Janke + * @version $Id: MPriceList.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MPriceList extends X_M_PriceList +{ + /** + * Get Price List (cached) + * @param ctx context + * @param M_PriceList_ID id + * @param trxName transaction + * @return PriceList + */ + public static MPriceList get (Properties ctx, int M_PriceList_ID, String trxName) + { + Integer key = new Integer (M_PriceList_ID); + MPriceList retValue = (MPriceList)s_cache.get(key); + if (retValue == null) + { + retValue = new MPriceList (ctx, M_PriceList_ID, trxName); + s_cache.put(key, retValue); + } + return retValue; + } // get + + /** + * Get Default Price List for Client (cached) + * @param ctx context + * @param IsSOPriceList SO or PO + * @return PriceList or null + */ + public static MPriceList getDefault (Properties ctx, boolean IsSOPriceList) + { + int AD_Client_ID = Env.getAD_Client_ID(ctx); + MPriceList retValue = null; + // Search for it in cache + Iterator it = s_cache.values().iterator(); + while (it.hasNext()) + { + retValue = (MPriceList)it.next(); + if (retValue.isDefault() && retValue.getAD_Client_ID() == AD_Client_ID) + return retValue; + } + + /** Get from DB **/ + retValue = null; + String sql = "SELECT * FROM M_PriceList " + + "WHERE AD_Client_ID=?" + + " AND IsDefault='Y'" + + " AND IsSOPriceList='Y'" + + "ORDER BY M_PriceList_ID"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Client_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + retValue = new MPriceList (ctx, rs, null); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // Return value + if (retValue != null) + { + Integer key = new Integer (retValue.getM_PriceList_ID()); + s_cache.put(key, retValue); + } + return retValue; + } // getDefault + + /** + * Get Standard Currency Precision + * @param ctx context + * @param M_PriceList_ID price list + * @return precision + */ + public static int getStandardPrecision (Properties ctx, int M_PriceList_ID) + { + MPriceList pl = MPriceList.get(ctx, M_PriceList_ID, null); + return pl.getStandardPrecision(); + } // getStandardPrecision + + /** + * Get Price Precision + * @param ctx context + * @param M_PriceList_ID price list + * @return precision + */ + public static int getPricePrecision (Properties ctx, int M_PriceList_ID) + { + MPriceList pl = MPriceList.get(ctx, M_PriceList_ID, null); + return pl.getPricePrecisionInt(); + } // getPricePrecision + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger(MPriceList.class); + /** Cache of Price Lists */ + private static CCache s_cache = new CCache("M_PriceList", 5); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_PriceList_ID id + * @param trxName transaction + */ + public MPriceList(Properties ctx, int M_PriceList_ID, String trxName) + { + super(ctx, M_PriceList_ID, trxName); + if (M_PriceList_ID == 0) + { + setEnforcePriceLimit (false); + setIsDefault (false); + setIsSOPriceList (false); + setIsTaxIncluded (false); + setPricePrecision (2); // 2 + // setName (null); + // setC_Currency_ID (0); + } + } // MPriceList + + /** + * Load Cosntructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPriceList (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPriceList + + /** Cached PLV */ + private MPriceListVersion m_plv = null; + /** Cached Precision */ + private Integer m_precision = null; + + /** + * Get Price List Version + * @param valid date where PLV must be valid or today if null + * @return PLV + */ + public MPriceListVersion getPriceListVersion (Timestamp valid) + { + if (valid == null) + valid = new Timestamp (System.currentTimeMillis()); + // Assume there is no later + if (m_plv != null && m_plv.getValidFrom().before(valid)) + return m_plv; + + String sql = "SELECT * FROM M_PriceList_Version " + + "WHERE M_PriceList_ID=?" + + " AND TRUNC(ValidFrom)<=? AND IsActive='Y'" + + "ORDER BY ValidFrom DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getM_PriceList_ID()); + pstmt.setTimestamp(2, valid); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + m_plv = new MPriceListVersion (getCtx(), rs, get_TrxName()); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (m_plv == null) + log.warning("None found M_PriceList_ID=" + + getM_PriceList_ID() + " - " + valid + " - " + sql); + else + log.fine(m_plv.toString()); + return m_plv; + } // getPriceListVersion + + /** + * Get Standard Currency Precision + * @return precision + */ + public int getStandardPrecision() + { + if (m_precision == null) + { + MCurrency c = MCurrency.get(getCtx(), getC_Currency_ID()); + m_precision = new Integer (c.getStdPrecision()); + } + return m_precision.intValue(); + } // getStandardPrecision + + + /** + * Set Price Precision + * @param PricePrecision precision + */ + public void setPricePrecision (int PricePrecision) + { + setPricePrecision (new BigDecimal(PricePrecision)); + } // setPricePrecision + + + /** + * Get Price Precision as int + * @return precision - -1 for none + */ + public int getPricePrecisionInt () + { + BigDecimal bd = getPricePrecision (); + if (bd == null) + return -1; + return bd.intValue(); + } // getPricePrecisionInt + +} // MPriceList diff --git a/base/src/org/compiere/model/MPriceListVersion.java b/base/src/org/compiere/model/MPriceListVersion.java new file mode 100644 index 0000000000..b0e30f1e27 --- /dev/null +++ b/base/src/org/compiere/model/MPriceListVersion.java @@ -0,0 +1,99 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Price List Version Model + * + * @author Jorg Janke + * @version $Id: MPriceListVersion.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MPriceListVersion extends X_M_PriceList_Version +{ + /** + * Standard Cinstructor + * @param ctx context + * @param M_PriceList_Version_ID id + * @param trxName transaction + */ + public MPriceListVersion(Properties ctx, int M_PriceList_Version_ID, String trxName) + { + super(ctx, M_PriceList_Version_ID, trxName); + if (M_PriceList_Version_ID == 0) + { + // setName (null); // @#Date@ + // setM_PriceList_ID (0); + // setValidFrom (TimeUtil.getDay(null)); // @#Date@ + // setM_DiscountSchema_ID (0); + } + } // MPriceListVersion + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MPriceListVersion(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MPriceListVersion + + /** + * Parent Constructor + * @param pl parent + */ + public MPriceListVersion (MPriceList pl) + { + this (pl.getCtx(), 0, pl.get_TrxName()); + setClientOrg(pl); + setM_PriceList_ID(pl.getM_PriceList_ID()); + } // MPriceListVersion + + /** + * Set Name to Valid From Date. + * If valid from not set, use today + */ + public void setName() + { + if (getValidFrom() == null) + setValidFrom (TimeUtil.getDay(null)); + if (getName() == null) + { + String name = DisplayType.getDateFormat(DisplayType.Date) + .format(getValidFrom()); + setName(name); + } + } // setName + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + setName(); + + return true; + } // beforeSave + +} // MPriceListVersion diff --git a/base/src/org/compiere/model/MProduct.java b/base/src/org/compiere/model/MProduct.java new file mode 100644 index 0000000000..b564b0bef3 --- /dev/null +++ b/base/src/org/compiere/model/MProduct.java @@ -0,0 +1,688 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Product Model + * + * @author Jorg Janke + * @version $Id: MProduct.java,v 1.5 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MProduct extends X_M_Product +{ + /** + * Get MProduct from Cache + * @param ctx context + * @param M_Product_ID id + * @return MProduct + */ + public static MProduct get (Properties ctx, int M_Product_ID) + { + Integer key = new Integer (M_Product_ID); + MProduct retValue = (MProduct) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MProduct (ctx, M_Product_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** + * Get MProduct from Cache + * @param ctx context + * @param whereClause sql where clause + * @param trxName trx + * @return MProduct + */ + public static MProduct[] get (Properties ctx, String whereClause, String trxName) + { + String sql = "SELECT * FROM M_Product"; + if (whereClause != null && whereClause.length() > 0) + sql += " WHERE AD_Client_ID=? AND " + whereClause; + ArrayList list = new ArrayList(); + int AD_Client_ID = Env.getAD_Client_ID(ctx); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt(1, AD_Client_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MProduct (ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MProduct[] retValue = new MProduct[list.size ()]; + list.toArray (retValue); + return retValue; + } // get + + + /** + * Is Product Stocked + * @param ctx context + * @param M_Product_ID id + * @return true if found and stocked - false otherwise + */ + public static boolean isProductStocked (Properties ctx, int M_Product_ID) + { + boolean retValue = false; + MProduct product = get (ctx, M_Product_ID); + return product.isStocked(); + } // isProductStocked + + /** Cache */ + private static CCache s_cache = new CCache("M_Product", 40, 5); // 5 minutes + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MProduct.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_Product_ID id + * @param trxName transaction + */ + public MProduct (Properties ctx, int M_Product_ID, String trxName) + { + super (ctx, M_Product_ID, trxName); + if (M_Product_ID == 0) + { + // setValue (null); + // setName (null); + // setM_Product_Category_ID (0); + // setC_TaxCategory_ID (0); + // setC_UOM_ID (0); + // + setProductType (PRODUCTTYPE_Item); // I + setIsBOM (false); // N + setIsInvoicePrintDetails (false); + setIsPickListPrintDetails (false); + setIsPurchased (true); // Y + setIsSold (true); // Y + setIsStocked (true); // Y + setIsSummary (false); + setIsVerified (false); // N + setIsWebStoreFeatured (false); + setIsSelfService(true); + setIsExcludeAutoDelivery(false); + setProcessing (false); // N + } + } // MProduct + + /** + * Load constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MProduct (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MProduct + + /** + * Parent Constructor + * @param et parent + */ + public MProduct (MExpenseType et) + { + this (et.getCtx(), 0, et.get_TrxName()); + setProductType(MProduct.PRODUCTTYPE_ExpenseType); + setExpenseType(et); + } // MProduct + + /** + * Parent Constructor + * @param resource parent + * @param resourceType resource type + */ + public MProduct (MResource resource, MResourceType resourceType) + { + this (resource.getCtx(), 0, resource.get_TrxName()); + setProductType(MProduct.PRODUCTTYPE_Resource); + setResource(resource); + setResource(resourceType); + } // MProduct + + /** + * Import Constructor + * @param impP import + */ + public MProduct (X_I_Product impP) + { + this (impP.getCtx(), 0, impP.get_TrxName()); + setClientOrg(impP); + setUpdatedBy(impP.getUpdatedBy()); + // + setValue(impP.getValue()); + setName(impP.getName()); + setDescription(impP.getDescription()); + setDocumentNote(impP.getDocumentNote()); + setHelp(impP.getHelp()); + setUPC(impP.getUPC()); + setSKU(impP.getSKU()); + setC_UOM_ID(impP.getC_UOM_ID()); + setM_Product_Category_ID(impP.getM_Product_Category_ID()); + setProductType(impP.getProductType()); + setImageURL(impP.getImageURL()); + setDescriptionURL(impP.getDescriptionURL()); + } // MProduct + + /** Additional Downloads */ + private MProductDownload[] m_downloads = null; + + /** + * Set Expense Type + * @param parent expense type + * @return true if changed + */ + public boolean setExpenseType (MExpenseType parent) + { + boolean changed = false; + if (!PRODUCTTYPE_ExpenseType.equals(getProductType())) + { + setProductType(PRODUCTTYPE_ExpenseType); + changed = true; + } + if (parent.getS_ExpenseType_ID() != getS_ExpenseType_ID()) + { + setS_ExpenseType_ID(parent.getS_ExpenseType_ID()); + changed = true; + } + if (parent.isActive() != isActive()) + { + setIsActive(parent.isActive()); + changed = true; + } + // + if (!parent.getValue().equals(getValue())) + { + setValue(parent.getValue()); + changed = true; + } + if (!parent.getName().equals(getName())) + { + setName(parent.getName()); + changed = true; + } + if ((parent.getDescription() == null && getDescription() != null) + || (parent.getDescription() != null && !parent.getDescription().equals(getDescription()))) + { + setDescription(parent.getDescription()); + changed = true; + } + if (parent.getC_UOM_ID() != getC_UOM_ID()) + { + setC_UOM_ID(parent.getC_UOM_ID()); + changed = true; + } + if (parent.getM_Product_Category_ID() != getM_Product_Category_ID()) + { + setM_Product_Category_ID(parent.getM_Product_Category_ID()); + changed = true; + } + if (parent.getC_TaxCategory_ID() != getC_TaxCategory_ID()) + { + setC_TaxCategory_ID(parent.getC_TaxCategory_ID()); + changed = true; + } + // + return changed; + } // setExpenseType + + /** + * Set Resource + * @param parent resource + * @return true if changed + */ + public boolean setResource (MResource parent) + { + boolean changed = false; + if (!PRODUCTTYPE_Resource.equals(getProductType())) + { + setProductType(PRODUCTTYPE_Resource); + changed = true; + } + if (parent.getS_Resource_ID() != getS_Resource_ID()) + { + setS_Resource_ID(parent.getS_Resource_ID()); + changed = true; + } + if (parent.isActive() != isActive()) + { + setIsActive(parent.isActive()); + changed = true; + } + // + if (!parent.getValue().equals(getValue())) + { + setValue(parent.getValue()); + changed = true; + } + if (!parent.getName().equals(getName())) + { + setName(parent.getName()); + changed = true; + } + if ((parent.getDescription() == null && getDescription() != null) + || (parent.getDescription() != null && !parent.getDescription().equals(getDescription()))) + { + setDescription(parent.getDescription()); + changed = true; + } + // + return changed; + } // setResource + + /** + * Set Resource Type + * @param parent resource type + * @return true if changed + */ + public boolean setResource (MResourceType parent) + { + boolean changed = false; + if (PRODUCTTYPE_Resource.equals(getProductType())) + { + setProductType(PRODUCTTYPE_Resource); + changed = true; + } + // + if (parent.getC_UOM_ID() != getC_UOM_ID()) + { + setC_UOM_ID(parent.getC_UOM_ID()); + changed = true; + } + if (parent.getM_Product_Category_ID() != getM_Product_Category_ID()) + { + setM_Product_Category_ID(parent.getM_Product_Category_ID()); + changed = true; + } + if (parent.getC_TaxCategory_ID() != getC_TaxCategory_ID()) + { + setC_TaxCategory_ID(parent.getC_TaxCategory_ID()); + changed = true; + } + // + return changed; + } // setResource + + + /** UOM Precision */ + private Integer m_precision = null; + + /** + * Get UOM Standard Precision + * @return UOM Standard Precision + */ + public int getUOMPrecision() + { + if (m_precision == null) + { + int C_UOM_ID = getC_UOM_ID(); + if (C_UOM_ID == 0) + return 0; // EA + m_precision = new Integer (MUOM.getPrecision(getCtx(), C_UOM_ID)); + } + return m_precision.intValue(); + } // getUOMPrecision + + + /** + * Create Asset Group for this product + * @return asset group id + */ + public int getA_Asset_Group_ID() + { + MProductCategory pc = MProductCategory.get(getCtx(), getM_Product_Category_ID()); + return pc.getA_Asset_Group_ID(); + } // getA_Asset_Group_ID + + /** + * Create Asset for this product + * @return true if asset is created + */ + public boolean isCreateAsset() + { + MProductCategory pc = MProductCategory.get(getCtx(), getM_Product_Category_ID()); + return pc.getA_Asset_Group_ID() != 0; + } // isCreated + + /** + * Get Attribute Set + * @return set or null + */ + public MAttributeSet getAttributeSet() + { + if (getM_AttributeSet_ID() != 0) + return MAttributeSet.get(getCtx(), getM_AttributeSet_ID()); + return null; + } // getAttributeSet + + /** + * Has the Product Instance Attribute + * @return true if instance attributes + */ + public boolean isInstanceAttribute() + { + if (getM_AttributeSet_ID() == 0) + return false; + MAttributeSet mas = MAttributeSet.get(getCtx(), getM_AttributeSet_ID()); + return mas.isInstanceAttribute(); + } // isInstanceAttribute + + /** + * Create One Asset Per UOM + * @return individual asset + */ + public boolean isOneAssetPerUOM() + { + MProductCategory pc = MProductCategory.get(getCtx(), getM_Product_Category_ID()); + if (pc.getA_Asset_Group_ID() == 0) + return false; + MAssetGroup ag = MAssetGroup.get(getCtx(), pc.getA_Asset_Group_ID()); + return ag.isOneAssetPerUOM(); + } // isOneAssetPerUOM + + /** + * Product is Item + * @return true if item + */ + public boolean isItem() + { + return PRODUCTTYPE_Item.equals(getProductType()); + } // isItem + + /** + * Product is an Item and Stocked + * @return true if stocked and item + */ + public boolean isStocked () + { + return super.isStocked() && isItem(); + } // isStocked + + /** + * Is Service + * @return true if service (resource, online) + */ + public boolean isService() + { + // PRODUCTTYPE_Service, PRODUCTTYPE_Resource, PRODUCTTYPE_Online + return !isItem(); // + } // isService + + /** + * Get UOM Symbol + * @return UOM Symbol + */ + public String getUOMSymbol() + { + int C_UOM_ID = getC_UOM_ID(); + if (C_UOM_ID == 0) + return ""; + return MUOM.get(getCtx(), C_UOM_ID).getUOMSymbol(); + } // getUOMSymbol + + /** + * Get Active(!) Product Downloads + * @param requery requery + * @return array of downloads + */ + public MProductDownload[] getProductDownloads (boolean requery) + { + if (m_downloads != null && !requery) + return m_downloads; + // + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_ProductDownload " + + "WHERE M_Product_ID=? AND IsActive='Y' ORDER BY Name"; + // + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getM_Product_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MProductDownload (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + m_downloads = new MProductDownload[list.size ()]; + list.toArray (m_downloads); + return m_downloads; + } // getProductDownloads + + /** + * Does the product have downloads + * @return true if downloads exists + */ + public boolean hasDownloads() + { + getProductDownloads(false); + return m_downloads != null && m_downloads.length > 0; + } // hasDownloads + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("MProduct["); + sb.append(get_ID()).append("-").append(getValue()) + .append("]"); + return sb.toString(); + } // toString + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Check Storage + if (!newRecord && // + ((is_ValueChanged("IsActive") && !isActive()) // now not active + || (is_ValueChanged("IsStocked") && !isStocked()) // now not stocked + || (is_ValueChanged("ProductType") // from Item + && PRODUCTTYPE_Item.equals(get_ValueOld("ProductType"))))) + { + MStorage[] storages = MStorage.getOfProduct(getCtx(), get_ID(), get_TrxName()); + BigDecimal OnHand = Env.ZERO; + BigDecimal Ordered = Env.ZERO; + BigDecimal Reserved = Env.ZERO; + for (int i = 0; i < storages.length; i++) + { + OnHand = OnHand.add(storages[i].getQtyOnHand()); + Ordered = OnHand.add(storages[i].getQtyOrdered()); + Reserved = OnHand.add(storages[i].getQtyReserved()); + } + String errMsg = ""; + if (OnHand.signum() != 0) + errMsg = "@QtyOnHand@ = " + OnHand; + if (Ordered.signum() != 0) + errMsg += " - @QtyOrdered@ = " + Ordered; + if (Reserved.signum() != 0) + errMsg += " - @QtyReserved@" + Reserved; + if (errMsg.length() > 0) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), errMsg)); + return false; + } + } // storage + + // Reset Stocked if not Item + if (isStocked() && !PRODUCTTYPE_Item.equals(getProductType())) + setIsStocked(false); + + // UOM reset + if (m_precision != null && is_ValueChanged("C_UOM_ID")) + m_precision = null; + + return true; + } // beforeSave + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + + // Value/Name change in Account + if (!newRecord && (is_ValueChanged("Value") || is_ValueChanged("Name"))) + MAccount.updateValueDescription(getCtx(), "M_Product_ID=" + getM_Product_ID(), get_TrxName()); + + // Name/Description Change in Asset MAsset.setValueNameDescription + if (!newRecord && (is_ValueChanged("Name") || is_ValueChanged("Description"))) + { + String sql = "UPDATE A_Asset a " + + "SET (Name, Description)=" + + "(SELECT SUBSTR(bp.Name || ' - ' || p.Name,1,60), p.Description " + + "FROM M_Product p, C_BPartner bp " + + "WHERE p.M_Product_ID=a.M_Product_ID AND bp.C_BPartner_ID=a.C_BPartner_ID) " + + "WHERE IsActive='Y'" + // + " AND GuaranteeDate > SysDate" + + " AND M_Product_ID=" + getM_Product_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + log.fine("Asset Description updated #" + no); + } + + // New - Acct, Tree, Old Costing + if (newRecord) + { + insert_Accounting("M_Product_Acct", "M_Product_Category_Acct", + "p.M_Product_Category_ID=" + getM_Product_Category_ID()); + insert_Tree(MTree_Base.TREETYPE_Product); + // + MAcctSchema[] mass = MAcctSchema.getClientAcctSchema(getCtx(), getAD_Client_ID(), get_TrxName()); + for (int i = 0; i < mass.length; i++) + { + // Old + MProductCosting pcOld = new MProductCosting(this, mass[i].getC_AcctSchema_ID()); + pcOld.save(); + } + } + + // New Costing + if (newRecord || is_ValueChanged("M_Product_Category")) + MCost.create(this); + + return success; + } // afterSave + + /** + * Before Delete + * @return true if it can be deleted + */ + protected boolean beforeDelete () + { + // Check Storage + if (isStocked() || PRODUCTTYPE_Item.equals(getProductType())) + { + MStorage[] storages = MStorage.getOfProduct(getCtx(), get_ID(), get_TrxName()); + BigDecimal OnHand = Env.ZERO; + BigDecimal Ordered = Env.ZERO; + BigDecimal Reserved = Env.ZERO; + for (int i = 0; i < storages.length; i++) + { + OnHand = OnHand.add(storages[i].getQtyOnHand()); + Ordered = OnHand.add(storages[i].getQtyOrdered()); + Reserved = OnHand.add(storages[i].getQtyReserved()); + } + String errMsg = ""; + if (OnHand.signum() != 0) + errMsg = "@QtyOnHand@ = " + OnHand; + if (Ordered.signum() != 0) + errMsg += " - @QtyOrdered@ = " + Ordered; + if (Reserved.signum() != 0) + errMsg += " - @QtyReserved@" + Reserved; + if (errMsg.length() > 0) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), errMsg)); + return false; + } + + } + // delete costing + MProductCosting[] costings = MProductCosting.getOfProduct(getCtx(), get_ID(), get_TrxName()); + for (int i = 0; i < costings.length; i++) + costings[i].delete(true, get_TrxName()); + // + return delete_Accounting("M_Product_Acct"); + } // beforeDelete + + /** + * After Delete + * @param success + * @return deleted + */ + protected boolean afterDelete (boolean success) + { + if (success) + delete_Tree(MTree_Base.TREETYPE_Product); + return success; + } // afterDelete + +} // MProduct diff --git a/base/src/org/compiere/model/MProductBOM.java b/base/src/org/compiere/model/MProductBOM.java new file mode 100644 index 0000000000..e1819b6431 --- /dev/null +++ b/base/src/org/compiere/model/MProductBOM.java @@ -0,0 +1,191 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Product BOM Model (old). + * M_Product_ID = the parent + * M_Product_BOM_ID = the BOM line + * M_ProductBOM_ID = the BOM line product + * + * @author Jorg Janke + * @version $Id: MProductBOM.java,v 1.5 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MProductBOM extends X_M_Product_BOM +{ + /** + * Get BOM Lines for Product + * @param product product + * @return array of BOMs + */ + public static MProductBOM[] getBOMLines (MProduct product) + { + return getBOMLines(product.getCtx(), product.getM_Product_ID(), product.get_TrxName()); + } // getBOMLines + + /** + * Get BOM Lines for Product + * @param ctx context + * @param M_Product_ID product + * @param trxName transaction + * @return array of BOMs + */ + public static MProductBOM[] getBOMLines (Properties ctx, int M_Product_ID, String trxName) + { + String sql = "SELECT * FROM M_Product_BOM WHERE M_Product_ID=? ORDER BY Line"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, M_Product_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MProductBOM (ctx, rs, trxName)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + // s_log.fine("getBOMLines - #" + list.size() + " - M_Product_ID=" + M_Product_ID); + MProductBOM[] retValue = new MProductBOM[list.size()]; + list.toArray(retValue); + return retValue; + } // getBOMLines + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger(MProductBOM.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_Product_BOM_ID id + * @param trxName transaction + */ + public MProductBOM (Properties ctx, int M_Product_BOM_ID, String trxName) + { + super (ctx, M_Product_BOM_ID, trxName); + if (M_Product_BOM_ID == 0) + { + // setM_Product_ID (0); // parent + // setLine (0); // @SQL=SELECT NVL(MAX(Line),0)+10 AS DefaultValue FROM M_Product_BOM WHERE M_Product_ID=@M_Product_ID@ + // setM_ProductBOM_ID(0); + setBOMQty (Env.ZERO); // 1 + } + } // MProductBOM + + /** + * Load Construvtor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MProductBOM (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MProductBOM + + /** Included Product */ + private MProduct m_product = null; + + + /** + * Get BOM Product + * @return product + */ + public MProduct getProduct() + { + if (m_product == null && getM_ProductBOM_ID() != 0) + m_product = MProduct.get (getCtx(), getM_ProductBOM_ID()); + return m_product; + } // getProduct + + /** + * Set included Product + * @param M_ProductBOM_ID product ID + */ + public void setM_ProductBOM_ID(int M_ProductBOM_ID) + { + super.setM_ProductBOM_ID (M_ProductBOM_ID); + m_product = null; + } // setM_ProductBOM_ID + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("MProductBOM["); + sb.append(get_ID()).append(",Line=").append(getLine()) + .append(",Type=").append(getBOMType()).append(",Qty=").append(getBOMQty()); + if (m_product == null) + sb.append(",M_Product_ID=").append(getM_ProductBOM_ID()); + else + sb.append(",").append(m_product); + sb.append("]"); + return sb.toString(); + } // toString + + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + // Product Line was changed + if (newRecord || is_ValueChanged("M_ProductBOM_ID")) + { + // Invalidate BOM + MProduct product = new MProduct (getCtx(), getM_Product_ID(), get_TrxName()); + if (get_TrxName() != null) + product.load(get_TrxName()); + if (product.isVerified()) + { + product.setIsVerified(false); + product.save(get_TrxName()); + } + // Invalidate Products where BOM is used + + } + return success; + } // afterSave + +} // MProductBOM diff --git a/base/src/org/compiere/model/MProductCategory.java b/base/src/org/compiere/model/MProductCategory.java new file mode 100644 index 0000000000..0053effd76 --- /dev/null +++ b/base/src/org/compiere/model/MProductCategory.java @@ -0,0 +1,175 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Product Category Model + * + * @author Jorg Janke + * @version $Id: MProductCategory.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MProductCategory extends X_M_Product_Category +{ + /** + * Get from Cache + * @param ctx context + * @param M_Product_Category_ID id + * @return category + */ + public static MProductCategory get (Properties ctx, int M_Product_Category_ID) + { + Integer ii = new Integer (M_Product_Category_ID); + MProductCategory pc = (MProductCategory)s_cache.get(ii); + if (pc == null) + pc = new MProductCategory (ctx, M_Product_Category_ID, null); + return pc; + } // get + + /** + * Is Product in Category + * @param M_Product_Category_ID category + * @param M_Product_ID product + * @return true if product has category + */ + public static boolean isCategory (int M_Product_Category_ID, int M_Product_ID) + { + if (M_Product_ID == 0 || M_Product_Category_ID == 0) + return false; + // Look up + Integer product = new Integer (M_Product_ID); + Integer category = (Integer)s_products.get(product); + if (category != null) + return category.intValue() == M_Product_Category_ID; + + String sql = "SELECT M_Product_Category_ID FROM M_Product WHERE M_Product_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, M_Product_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + category = new Integer(rs.getInt(1)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (category != null) + { + // TODO: LRU logic + s_products.put(product, category); + // + s_log.fine("M_Product_ID=" + M_Product_ID + "(" + category + + ") in M_Product_Category_ID=" + M_Product_Category_ID + + " - " + (category.intValue() == M_Product_Category_ID)); + return category.intValue() == M_Product_Category_ID; + } + s_log.log(Level.SEVERE, "Not found M_Product_ID=" + M_Product_ID); + return false; + } // isCategory + + /** Categopry Cache */ + private static CCache s_cache = new CCache("M_Product_Category", 20); + /** Product Cache */ + private static CCache s_products = new CCache("M_Product", 100); + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MProductCategory.class); + + + /************************************************************************** + * Default Constructor + * @param ctx context + * @param M_Product_Category_ID id + * @param trxName transaction + */ + public MProductCategory (Properties ctx, int M_Product_Category_ID, String trxName) + { + super(ctx, M_Product_Category_ID, trxName); + if (M_Product_Category_ID == 0) + { + // setName (null); + // setValue (null); + setMMPolicy (MMPOLICY_FiFo); // F + setPlannedMargin (Env.ZERO); + setIsDefault (false); + setIsSelfService (true); // Y + } + } // MProductCategory + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MProductCategory(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MProductCategory + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (newRecord & success) + insert_Accounting("M_Product_Category_Acct", "C_AcctSchema_Default", null); + + return success; + } // afterSave + + /** + * Before Delete + * @return true + */ + protected boolean beforeDelete () + { + return delete_Accounting("M_Product_Category_Acct"); + } // beforeDelete + + /** + * FiFo Material Movement Policy + * @return true if FiFo + */ + public boolean isFiFo() + { + return MMPOLICY_FiFo.equals(getMMPolicy()); + } // isFiFo + +} // MProductCategory diff --git a/base/src/org/compiere/model/MProductCategoryAcct.java b/base/src/org/compiere/model/MProductCategoryAcct.java new file mode 100644 index 0000000000..e9f1c0bab6 --- /dev/null +++ b/base/src/org/compiere/model/MProductCategoryAcct.java @@ -0,0 +1,125 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Product Category Account Model + * @author Jorg Janke + * @version $Id: MProductCategoryAcct.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MProductCategoryAcct extends X_M_Product_Category_Acct +{ + /** + * Get Category Acct + * @param ctx context + * @param M_Product_Category_ID category + * @param C_AcctSchema_ID acct schema + * @param trxName trx + * @return category acct + */ + public static MProductCategoryAcct get (Properties ctx, + int M_Product_Category_ID, int C_AcctSchema_ID, String trxName) + { + MProductCategoryAcct retValue = null; + PreparedStatement pstmt = null; + String sql = "SELECT * FROM M_Product_Category_Acct " + + "WHERE M_Product_Category_ID=? AND C_AcctSchema_ID=?"; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_Product_Category_ID); + pstmt.setInt (2, C_AcctSchema_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = new MProductCategoryAcct (ctx, rs, trxName); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return retValue; + } // get + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MProductCategoryAcct.class); + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param ignored ignored + * @param trxName + */ + public MProductCategoryAcct (Properties ctx, int ignored, String trxName) + { + super (ctx, ignored, trxName); + if (ignored != 0) + throw new IllegalArgumentException("Multi-Key"); + } // MProductCategoryAcct + + /** + * Load Cosntructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MProductCategoryAcct (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MProductCategoryAcct + + /** + * Check Costing Setup + */ + public void checkCosting() + { + // Create Cost Elements + if (getCostingMethod() != null && getCostingMethod().length() > 0) + MCostElement.getMaterialCostElement(this, getCostingMethod()); + } // checkCosting + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + checkCosting(); + return success; + } // afterSave + +} // MProductCategoryAcct diff --git a/base/src/org/compiere/model/MProductCosting.java b/base/src/org/compiere/model/MProductCosting.java new file mode 100644 index 0000000000..b1baac99c3 --- /dev/null +++ b/base/src/org/compiere/model/MProductCosting.java @@ -0,0 +1,185 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Product Costing Model (old). + * deprecated old costing + * + * @author Jorg Janke + * @version $Id: MProductCosting.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MProductCosting extends X_M_Product_Costing +{ + /** + * Get Costing Of Product + * @param ctx context + * @param M_Product_ID product + * @param trxName trx + * @return array of costs + */ + public static MProductCosting[] getOfProduct (Properties ctx, int M_Product_ID, String trxName) + { + String sql = "SELECT * FROM M_Product_Costing WHERE M_Product_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_Product_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + list.add (new MProductCosting (ctx, rs, trxName)); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + MProductCosting[] retValue = new MProductCosting[list.size()]; + list.toArray(retValue); + return retValue; + } // getOfProduct + + /** + * Get Costing + * @param ctx context + * @param M_Product_ID product + * @param C_AcctSchema_ID as + * @param trxName trx + * @return array of costs + */ + public static MProductCosting get (Properties ctx, int M_Product_ID, + int C_AcctSchema_ID, String trxName) + { + MProductCosting retValue = null; + String sql = "SELECT * FROM M_Product_Costing WHERE M_Product_ID=? AND C_AcctSchema_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_Product_ID); + pstmt.setInt (2, C_AcctSchema_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next()) + retValue = new MProductCosting (ctx, rs, trxName); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + return retValue; + } // get + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MProductCosting.class); + + + /************************************************************************** + * Standard Constructor (odl) + * @param ctx context + * @param ignored (multi key) + * @param trxName transaction + */ + public MProductCosting (Properties ctx, int ignored, String trxName) + { + super (ctx, ignored, trxName); + if (ignored != 0) + throw new IllegalArgumentException("Multi-Key"); + else + { + // setM_Product_ID (0); + // setC_AcctSchema_ID (0); + // + setCostAverage (Env.ZERO); + setCostAverageCumAmt (Env.ZERO); + setCostAverageCumQty (Env.ZERO); + setCostStandard (Env.ZERO); + setCostStandardCumAmt (Env.ZERO); + setCostStandardCumQty (Env.ZERO); + setCostStandardPOAmt (Env.ZERO); + setCostStandardPOQty (Env.ZERO); + setCurrentCostPrice (Env.ZERO); + setFutureCostPrice (Env.ZERO); + setPriceLastInv (Env.ZERO); + setPriceLastPO (Env.ZERO); + setTotalInvAmt (Env.ZERO); + setTotalInvQty (Env.ZERO); + } + } // MProductCosting + + /** + * Parent Constructor (old) + * @param product parent + * @param C_AcctSchema_ID accounting schema + */ + public MProductCosting (MProduct product, int C_AcctSchema_ID) + { + super (product.getCtx(), 0, product.get_TrxName()); + setClientOrg(product); + setM_Product_ID (product.getM_Product_ID()); + setC_AcctSchema_ID (C_AcctSchema_ID); + } // MProductCosting + + + /** + * Load Constructor (old) + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MProductCosting (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MProductCosting + +} // MProductCosting + diff --git a/base/src/org/compiere/model/MProductDownload.java b/base/src/org/compiere/model/MProductDownload.java new file mode 100644 index 0000000000..b66e38b15d --- /dev/null +++ b/base/src/org/compiere/model/MProductDownload.java @@ -0,0 +1,258 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.net.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + + +/** + * Product Download Model + * @author Jorg Janke + * @version $Id: MProductDownload.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MProductDownload extends X_M_ProductDownload +{ + /** + * Migrate Download URLs (2.5.2c) + * @param ctx context + */ + public static void migrateDownloads (Properties ctx) + { + String sql = "SELECT COUNT(*) FROM M_ProductDownload"; + int no = DB.getSQLValue(null, sql); + if (no > 0) + return; + // + int count = 0; + sql = "SELECT AD_Client_ID, AD_Org_ID, M_Product_ID, Name, DownloadURL " + + "FROM M_Product " + + "WHERE DownloadURL IS NOT NULL"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + int AD_Client_ID = rs.getInt(1); + int AD_Org_ID = rs.getInt(2); + int M_Product_ID = rs.getInt(3); + String Name = rs.getString(4); + String DownloadURL = rs.getString(5); + // + MProductDownload pdl = new MProductDownload(ctx, 0, null); + pdl.setClientOrg(AD_Client_ID, AD_Org_ID); + pdl.setM_Product_ID(M_Product_ID); + pdl.setName(Name); + pdl.setDownloadURL(DownloadURL); + if (pdl.save()) + { + count++; + String sqlUpdate = "UPDATE M_Product SET DownloadURL = NULL WHERE M_Product_ID=" + M_Product_ID; + int updated = DB.executeUpdate(sqlUpdate, null); + if (updated != 1) + s_log.warning("Product not updated"); + } + else + s_log.warning("Product Download not created M_Product_ID=" + M_Product_ID); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + s_log.info("#" + count); + } // migrateDownloads + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MProductDownload.class); + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_ProductDownload_ID id + * @param trxName trx + */ + public MProductDownload (Properties ctx, int M_ProductDownload_ID, + String trxName) + { + super (ctx, M_ProductDownload_ID, trxName); + if (M_ProductDownload_ID == 0) + { + // setM_Product_ID (0); + // setName (null); + // setDownloadURL (null); + } + } // MProductDownload + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MProductDownload (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MProductDownload + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MProductDownload[") + .append(get_ID()) + .append(",M_Product_ID=").append(getM_Product_ID()) + .append(",").append(getDownloadURL()) + .append ("]"); + return sb.toString (); + } // toString + + + /** + * Get Download Name + * @return download name (last part of name) + */ + public String getDownloadName() + { + String url = getDownloadURL(); + if (url == null || !isActive()) + return null; + int pos = Math.max(url.lastIndexOf('/'), url.lastIndexOf('\\')); + if (pos != -1) + return url.substring(pos+1); + return url; + } // getDownloadName + + + /** + * Get Download URL + * @param directory optional directory + * @return url + */ + public URL getDownloadURL (String directory) + { + String dl_url = getDownloadURL(); + if (dl_url == null || !isActive()) + return null; + + URL url = null; + try + { + if (dl_url.indexOf ("://") != -1) + url = new URL (dl_url); + else + { + File f = getDownloadFile (directory); + if (f != null) + url = f.toURL (); + } + } + catch (Exception ex) + { + log.log(Level.SEVERE, dl_url, ex); + return null; + } + return url; + } // getDownloadURL + + + /** + * Find download url + * @param directory optional directory + * @return file or null + */ + public File getDownloadFile (String directory) + { + File file = new File (getDownloadURL()); // absolute file + if (file.exists()) + return file; + if (directory == null || directory.length() == 0) + { + log.log(Level.SEVERE, "Not found " + getDownloadURL()); + return null; + } + String downloadURL2 = directory; + if (!downloadURL2.endsWith(File.separator)) + downloadURL2 += File.separator; + downloadURL2 += getDownloadURL(); + file = new File (downloadURL2); + if (file.exists()) + return file; + + log.log(Level.SEVERE, "Not found " + getDownloadURL() + " + " + downloadURL2); + return null; + } // getDownloadFile + + /** + * Get Download Stream + * @param directory optional directory + * @return input stream + */ + public InputStream getDownloadStream (String directory) + { + String dl_url = getDownloadURL(); + if (dl_url == null || !isActive()) + return null; + + InputStream in = null; + try + { + if (dl_url.indexOf ("://") != -1) + { + URL url = new URL (dl_url); + in = url.openStream(); + } + else // file + { + File file = getDownloadFile(directory); + if (file == null) + return null; + in = new FileInputStream (file); + } + } + catch (Exception ex) + { + log.log(Level.SEVERE, dl_url, ex); + return null; + } + return in; + } // getDownloadStream + + +} // MProductDownload diff --git a/base/src/org/compiere/model/MProductPO.java b/base/src/org/compiere/model/MProductPO.java new file mode 100644 index 0000000000..e5feeb153c --- /dev/null +++ b/base/src/org/compiere/model/MProductPO.java @@ -0,0 +1,112 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Product PO Model + * + * @author Jorg Janke + * @version $Id: MProductPO.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MProductPO extends X_M_Product_PO +{ + /** + * Get current PO of Product + * @param ctx context + * @param M_Product_ID product + * @param trxName transaction + * @return PO - current vendor first + */ + public static MProductPO[] getOfProduct (Properties ctx, int M_Product_ID, String trxName) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_Product_PO " + + "WHERE M_Product_ID=? AND IsActive='Y' " + + "ORDER BY IsCurrentVendor DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_Product_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + list.add(new MProductPO (ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (SQLException ex) + { + s_log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + // + MProductPO[] retValue = new MProductPO[list.size()]; + list.toArray(retValue); + return retValue; + } // getOfProduct + + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger(MProductPO.class); + + /** + * Persistency Constructor + * @param ctx context + * @param ignored ignored + * @param trxName transaction + */ + public MProductPO (Properties ctx, int ignored, String trxName) + { + super(ctx, 0, trxName); + if (ignored != 0) + throw new IllegalArgumentException("Multi-Key"); + else + { + // setM_Product_ID (0); // @M_Product_ID@ + // setC_BPartner_ID (0); // 0 + // setVendorProductNo (null); // @Value@ + setIsCurrentVendor (true); // Y + } + } // MProduct_PO + + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MProductPO(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MProductPO + +} // MProductPO diff --git a/base/src/org/compiere/model/MProductPrice.java b/base/src/org/compiere/model/MProductPrice.java new file mode 100644 index 0000000000..e39083f168 --- /dev/null +++ b/base/src/org/compiere/model/MProductPrice.java @@ -0,0 +1,171 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Product Price + * + * @author Jorg Janke + * @version $Id: MProductPrice.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MProductPrice extends X_M_ProductPrice +{ + + /** + * Get Product Price + * @param ctx ctx + * @param M_PriceList_Version_ID id + * @param M_Product_ID id + * @param trxName trx + * @return product price or null + */ + public static MProductPrice get (Properties ctx, int M_PriceList_Version_ID, int M_Product_ID, + String trxName) + { + MProductPrice retValue = null; + String sql = "SELECT * FROM M_ProductPrice WHERE M_PriceList_Version_ID=? AND M_Product_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_PriceList_Version_ID); + pstmt.setInt (2, M_Product_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + retValue = new MProductPrice (ctx, rs, trxName); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return retValue; + } // get + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MProductPrice.class); + + /** + * Persistency Constructor + * @param ctx context + * @param ignored ignored + * @param trxName transaction + */ + public MProductPrice (Properties ctx, int ignored, String trxName) + { + super(ctx, 0, trxName); + if (ignored != 0) + throw new IllegalArgumentException("Multi-Key"); + setPriceLimit (Env.ZERO); + setPriceList (Env.ZERO); + setPriceStd (Env.ZERO); + } // MProductPrice + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MProductPrice (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MProductPrice + + /** + * New Constructor + * @param ctx context + * @param M_PriceList_Version_ID Price List Version + * @param M_Product_ID product + * @param trxName transaction + */ + public MProductPrice (Properties ctx, int M_PriceList_Version_ID, int M_Product_ID, String trxName) + { + this (ctx, 0, trxName); + setM_PriceList_Version_ID (M_PriceList_Version_ID); // FK + setM_Product_ID (M_Product_ID); // FK + } // MProductPrice + + /** + * New Constructor + * @param ctx context + * @param M_PriceList_Version_ID Price List Version + * @param M_Product_ID product + * @param PriceList list price + * @param PriceStd standard price + * @param PriceLimit limit price + * @param trxName transaction + */ + public MProductPrice (Properties ctx, int M_PriceList_Version_ID, int M_Product_ID, + BigDecimal PriceList, BigDecimal PriceStd, BigDecimal PriceLimit, String trxName) + { + this (ctx, M_PriceList_Version_ID, M_Product_ID, trxName); + setPrices (PriceList, PriceStd, PriceLimit); + } // MProductPrice + + /** + * Parent Constructor + * @param plv price list version + * @param M_Product_ID product + * @param PriceList list price + * @param PriceStd standard price + * @param PriceLimit limit price + */ + public MProductPrice (MPriceListVersion plv, int M_Product_ID, + BigDecimal PriceList, BigDecimal PriceStd, BigDecimal PriceLimit) + { + this (plv.getCtx(), 0, plv.get_TrxName()); + setClientOrg(plv); + setM_PriceList_Version_ID(plv.getM_PriceList_Version_ID()); + setM_Product_ID(M_Product_ID); + setPrices (PriceList, PriceStd, PriceLimit); + } // MProductPrice + + /** + * Set Prices + * @param PriceList list price + * @param PriceStd standard price + * @param PriceLimit limit price + */ + public void setPrices (BigDecimal PriceList, BigDecimal PriceStd, BigDecimal PriceLimit) + { + setPriceLimit (PriceLimit); + setPriceList (PriceList); + setPriceStd (PriceStd); + } // setPrice + +} // MProductPrice diff --git a/base/src/org/compiere/model/MProductPricing.java b/base/src/org/compiere/model/MProductPricing.java new file mode 100644 index 0000000000..dfe34df708 --- /dev/null +++ b/base/src/org/compiere/model/MProductPricing.java @@ -0,0 +1,660 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Product Price Calculations + * + * @author Jorg Janke + * @version $Id: MProductPricing.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MProductPricing +{ + /** + * Constructor + * @param M_Product_ID product + * @param C_BPartner_ID partner + * @param Qty quantity + * @param isSOTrx SO or PO + */ + public MProductPricing (int M_Product_ID, int C_BPartner_ID, + BigDecimal Qty, boolean isSOTrx) + { + m_M_Product_ID = M_Product_ID; + m_C_BPartner_ID = C_BPartner_ID; + if (Qty != null && Env.ZERO.compareTo(Qty) != 0) + m_Qty = Qty; + m_isSOTrx = isSOTrx; + } // MProductPricing + + private int m_M_Product_ID; + private int m_C_BPartner_ID; + private BigDecimal m_Qty = Env.ONE; + private boolean m_isSOTrx = true; + // + private int m_M_PriceList_ID = 0; + private int m_M_PriceList_Version_ID = 0; + private Timestamp m_PriceDate; + /** Precision -1 = no rounding */ + private int m_precision = -1; + + + private boolean m_calculated = false; + private Boolean m_found = null; + + private BigDecimal m_PriceList = Env.ZERO; + private BigDecimal m_PriceStd = Env.ZERO; + private BigDecimal m_PriceLimit = Env.ZERO; + private int m_C_Currency_ID = 0; + private boolean m_enforcePriceLimit = false; + private int m_C_UOM_ID = 0; + private int m_M_Product_Category_ID; + private boolean m_discountSchema = false; + private boolean m_isTaxIncluded = false; + + /** Logger */ + protected CLogger log = CLogger.getCLogger(getClass()); + + + /** + * Calculate Price + * @return true if calculated + */ + public boolean calculatePrice () + { + if (m_M_Product_ID == 0 + || (m_found != null && !m_found.booleanValue())) // previously not found + return false; + // Price List Version known + if (!m_calculated) + m_calculated = calculatePLV (); + // Price List known + if (!m_calculated) + m_calculated = calculatePL(); + // Base Price List used + if (!m_calculated) + m_calculated = calculateBPL(); + // Set UOM, Prod.Category + if (!m_calculated) + setBaseInfo(); + // User based Discount + if (m_calculated) + calculateDiscount(); + setPrecision(); // from Price List + // + m_found = new Boolean (m_calculated); + return m_calculated; + } // calculatePrice + + /** + * Calculate Price based on Price List Version + * @return true if calculated + */ + private boolean calculatePLV() + { + if (m_M_Product_ID == 0 || m_M_PriceList_Version_ID == 0) + return false; + // + String sql = "SELECT bomPriceStd(p.M_Product_ID,pv.M_PriceList_Version_ID) AS PriceStd," // 1 + + " bomPriceList(p.M_Product_ID,pv.M_PriceList_Version_ID) AS PriceList," // 2 + + " bomPriceLimit(p.M_Product_ID,pv.M_PriceList_Version_ID) AS PriceLimit," // 3 + + " p.C_UOM_ID,pv.ValidFrom,pl.C_Currency_ID,p.M_Product_Category_ID," // 4..7 + + " pl.EnforcePriceLimit, pl.IsTaxIncluded " // 8..9 + + "FROM M_Product p" + + " INNER JOIN M_ProductPrice pp ON (p.M_Product_ID=pp.M_Product_ID)" + + " INNER JOIN M_PriceList_Version pv ON (pp.M_PriceList_Version_ID=pv.M_PriceList_Version_ID)" + + " INNER JOIN M_Pricelist pl ON (pv.M_PriceList_ID=pl.M_PriceList_ID) " + + "WHERE pv.IsActive='Y'" + + " AND p.M_Product_ID=?" // #1 + + " AND pv.M_PriceList_Version_ID=?"; // #2 + m_calculated = false; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, m_M_Product_ID); + pstmt.setInt(2, m_M_PriceList_Version_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + // Prices + m_PriceStd = rs.getBigDecimal(1); + if (rs.wasNull()) + m_PriceStd = Env.ZERO; + m_PriceList = rs.getBigDecimal(2); + if (rs.wasNull()) + m_PriceList = Env.ZERO; + m_PriceLimit = rs.getBigDecimal(3); + if (rs.wasNull()) + m_PriceLimit = Env.ZERO; + // + m_C_UOM_ID = rs.getInt(4); + m_C_Currency_ID = rs.getInt(6); + m_M_Product_Category_ID = rs.getInt(7); + m_enforcePriceLimit = "Y".equals(rs.getString(8)); + m_isTaxIncluded = "Y".equals(rs.getString(9)); + // + log.fine("M_PriceList_Version_ID=" + m_M_PriceList_Version_ID + " - " + m_PriceStd); + m_calculated = true; + } + rs.close(); + pstmt.close(); + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + m_calculated = false; + } + return m_calculated; + } // calculatePLV + + /** + * Calculate Price based on Price List + * @return true if calculated + */ + private boolean calculatePL() + { + if (m_M_Product_ID == 0) + return false; + + // Get Price List + /** + if (m_M_PriceList_ID == 0) + { + String sql = "SELECT M_PriceList_ID, IsTaxIncluded " + + "FROM M_PriceList pl" + + " INNER JOIN M_Product p ON (pl.AD_Client_ID=p.AD_Client_ID) " + + "WHERE M_Product_ID=? " + + "ORDER BY IsDefault DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql); + pstmt.setInt(1, m_M_Product_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + m_M_PriceList_ID = rs.getInt(1); + m_isTaxIncluded = "Y".equals(rs.getString(2)); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "calculatePL (PL)", e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + } + /** **/ + if (m_M_PriceList_ID == 0) + { + log.log(Level.SEVERE, "No PriceList"); + Trace.printStack(); + return false; + } + + // Get Prices for Price List + String sql = "SELECT bomPriceStd(p.M_Product_ID,pv.M_PriceList_Version_ID) AS PriceStd," // 1 + + " bomPriceList(p.M_Product_ID,pv.M_PriceList_Version_ID) AS PriceList," // 2 + + " bomPriceLimit(p.M_Product_ID,pv.M_PriceList_Version_ID) AS PriceLimit," // 3 + + " p.C_UOM_ID,pv.ValidFrom,pl.C_Currency_ID,p.M_Product_Category_ID,pl.EnforcePriceLimit " // 4..8 + + "FROM M_Product p" + + " INNER JOIN M_ProductPrice pp ON (p.M_Product_ID=pp.M_Product_ID)" + + " INNER JOIN M_PriceList_Version pv ON (pp.M_PriceList_Version_ID=pv.M_PriceList_Version_ID)" + + " INNER JOIN M_Pricelist pl ON (pv.M_PriceList_ID=pl.M_PriceList_ID) " + + "WHERE pv.IsActive='Y'" + + " AND p.M_Product_ID=?" // #1 + + " AND pv.M_PriceList_ID=?" // #2 + + "ORDER BY pv.ValidFrom DESC"; + m_calculated = false; + if (m_PriceDate == null) + m_PriceDate = new Timestamp (System.currentTimeMillis()); + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, m_M_Product_ID); + pstmt.setInt(2, m_M_PriceList_ID); + ResultSet rs = pstmt.executeQuery(); + while (!m_calculated && rs.next()) + { + Timestamp plDate = rs.getTimestamp(5); + // we have the price list + // if order date is after or equal PriceList validFrom + if (plDate == null || !m_PriceDate.before(plDate)) + { + // Prices + m_PriceStd = rs.getBigDecimal (1); + if (rs.wasNull ()) + m_PriceStd = Env.ZERO; + m_PriceList = rs.getBigDecimal (2); + if (rs.wasNull ()) + m_PriceList = Env.ZERO; + m_PriceLimit = rs.getBigDecimal (3); + if (rs.wasNull ()) + m_PriceLimit = Env.ZERO; + // + m_C_UOM_ID = rs.getInt (4); + m_C_Currency_ID = rs.getInt (6); + m_M_Product_Category_ID = rs.getInt(7); + m_enforcePriceLimit = "Y".equals(rs.getString(8)); + // + log.fine("M_PriceList_ID=" + m_M_PriceList_ID + + "(" + plDate + ")" + " - " + m_PriceStd); + m_calculated = true; + break; + } + } + rs.close(); + pstmt.close(); + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + m_calculated = false; + } + if (!m_calculated) + log.finer("Not found (PL)"); + return m_calculated; + } // calculatePL + + /** + * Calculate Price based on Base Price List + * @return true if calculated + */ + private boolean calculateBPL() + { + if (m_M_Product_ID == 0 || m_M_PriceList_ID == 0) + return false; + // + String sql = "SELECT bomPriceStd(p.M_Product_ID,pv.M_PriceList_Version_ID) AS PriceStd," // 1 + + " bomPriceList(p.M_Product_ID,pv.M_PriceList_Version_ID) AS PriceList," // 2 + + " bomPriceLimit(p.M_Product_ID,pv.M_PriceList_Version_ID) AS PriceLimit," // 3 + + " p.C_UOM_ID,pv.ValidFrom,pl.C_Currency_ID,p.M_Product_Category_ID," // 4..7 + + " pl.EnforcePriceLimit, pl.IsTaxIncluded " // 8..9 + + "FROM M_Product p" + + " INNER JOIN M_ProductPrice pp ON (p.M_Product_ID=pp.M_Product_ID)" + + " INNER JOIN M_PriceList_Version pv ON (pp.M_PriceList_Version_ID=pv.M_PriceList_Version_ID)" + + " INNER JOIN M_Pricelist bpl ON (pv.M_PriceList_ID=bpl.M_PriceList_ID)" + + " INNER JOIN M_Pricelist pl ON (bpl.M_PriceList_ID=pl.BasePriceList_ID) " + + "WHERE pv.IsActive='Y'" + + " AND p.M_Product_ID=?" // #1 + + " AND pl.M_PriceList_ID=?" // #2 + + "ORDER BY pv.ValidFrom DESC"; + m_calculated = false; + if (m_PriceDate == null) + m_PriceDate = new Timestamp (System.currentTimeMillis()); + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, m_M_Product_ID); + pstmt.setInt(2, m_M_PriceList_ID); + ResultSet rs = pstmt.executeQuery(); + while (!m_calculated && rs.next()) + { + Timestamp plDate = rs.getTimestamp(5); + // we have the price list + // if order date is after or equal PriceList validFrom + if (plDate == null || !m_PriceDate.before(plDate)) + { + // Prices + m_PriceStd = rs.getBigDecimal (1); + if (rs.wasNull ()) + m_PriceStd = Env.ZERO; + m_PriceList = rs.getBigDecimal (2); + if (rs.wasNull ()) + m_PriceList = Env.ZERO; + m_PriceLimit = rs.getBigDecimal (3); + if (rs.wasNull ()) + m_PriceLimit = Env.ZERO; + // + m_C_UOM_ID = rs.getInt (4); + m_C_Currency_ID = rs.getInt (6); + m_M_Product_Category_ID = rs.getInt(7); + m_enforcePriceLimit = "Y".equals(rs.getString(8)); + m_isTaxIncluded = "Y".equals(rs.getString(9)); + // + log.fine("M_PriceList_ID=" + m_M_PriceList_ID + + "(" + plDate + ")" + " - " + m_PriceStd); + m_calculated = true; + break; + } + } + rs.close(); + pstmt.close(); + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + m_calculated = false; + } + if (!m_calculated) + log.finer("Not found (BPL)"); + return m_calculated; + } // calculateBPL + + /** + * Set Base Info (UOM) + */ + private void setBaseInfo() + { + if (m_M_Product_ID == 0) + return; + // + String sql = "SELECT C_UOM_ID, M_Product_Category_ID FROM M_Product WHERE M_Product_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, m_M_Product_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + m_C_UOM_ID = rs.getInt (1); + m_M_Product_Category_ID = rs.getInt(2); + } + rs.close(); + pstmt.close(); + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + } // setBaseInfo + + /** + * Is Tax Included + * @return tax included + */ + public boolean isTaxIncluded() + { + return m_isTaxIncluded; + } // isTaxIncluded + + + /************************************************************************** + * Calculate (Business Partner) Discount + */ + private void calculateDiscount() + { + m_discountSchema = false; + if (m_C_BPartner_ID == 0 || m_M_Product_ID == 0) + return; + + int M_DiscountSchema_ID = 0; + BigDecimal FlatDiscount = null; + String sql = "SELECT COALESCE(p.M_DiscountSchema_ID,g.M_DiscountSchema_ID)," + + " COALESCE(p.PO_DiscountSchema_ID,g.PO_DiscountSchema_ID), p.FlatDiscount " + + "FROM C_BPartner p" + + " INNER JOIN C_BP_Group g ON (p.C_BP_Group_ID=g.C_BP_Group_ID) " + + "WHERE p.C_BPartner_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, m_C_BPartner_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + M_DiscountSchema_ID = rs.getInt(m_isSOTrx ? 1 : 2); + FlatDiscount = rs.getBigDecimal(3); + if (FlatDiscount == null) + FlatDiscount = Env.ZERO; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // No Discount Schema + if (M_DiscountSchema_ID == 0) + return; + + MDiscountSchema sd = MDiscountSchema.get(Env.getCtx(), M_DiscountSchema_ID); // not correct + if (sd.get_ID() == 0) + return; + // + m_discountSchema = true; + m_PriceStd = sd.calculatePrice(m_Qty, m_PriceStd, m_M_Product_ID, + m_M_Product_Category_ID, FlatDiscount); + + } // calculateDiscount + + + /************************************************************************** + * Calculate Discount Percentage based on Standard/List Price + * @return Discount + */ + public BigDecimal getDiscount() + { + BigDecimal Discount = Env.ZERO; + if (m_PriceList.intValue() != 0) + Discount = new BigDecimal ((m_PriceList.doubleValue() - m_PriceStd.doubleValue()) + / m_PriceList.doubleValue() * 100.0); + if (Discount.scale() > 2) + Discount = Discount.setScale(2, BigDecimal.ROUND_HALF_UP); + return Discount; + } // getDiscount + + + + + /************************************************************************** + * Get Product ID + * @return id + */ + public int getM_Product_ID() + { + return m_M_Product_ID; + } + + /** + * Get PriceList ID + * @return pl + */ + public int getM_PriceList_ID() + { + return m_M_PriceList_ID; + } // getM_PriceList_ID + + /** + * Set PriceList + * @param M_PriceList_ID pl + */ + public void setM_PriceList_ID( int M_PriceList_ID) + { + m_M_PriceList_ID = M_PriceList_ID; + m_calculated = false; + } // setM_PriceList_ID + + /** + * Get PriceList Version + * @return plv + */ + public int getM_PriceList_Version_ID() + { + return m_M_PriceList_Version_ID; + } // getM_PriceList_Version_ID + + /** + * Set PriceList Version + * @param M_PriceList_Version_ID plv + */ + public void setM_PriceList_Version_ID (int M_PriceList_Version_ID) + { + m_M_PriceList_Version_ID = M_PriceList_Version_ID; + m_calculated = false; + } // setM_PriceList_Version_ID + + /** + * Get Price Date + * @return date + */ + public Timestamp getPriceDate() + { + return m_PriceDate; + } // getPriceDate + + /** + * Set Price Date + * @param priceDate date + */ + public void setPriceDate(Timestamp priceDate) + { + m_PriceDate = priceDate; + m_calculated = false; + } // setPriceDate + + /** + * Set Precision. + */ + private void setPrecision () + { + if (m_M_PriceList_ID != 0) + m_precision = MPriceList.getPricePrecision(Env.getCtx(), getM_PriceList_ID()); + } // setPrecision + + /** + * Get Precision + * @return precision - -1 = no rounding + */ + public int getPrecision() + { + return m_precision; + } // getPrecision + + /** + * Round + * @param bd number + * @return rounded number + */ + private BigDecimal round (BigDecimal bd) + { + if (m_precision >= 0 // -1 = no rounding + && bd.scale() > m_precision) + return bd.setScale(m_precision, BigDecimal.ROUND_HALF_UP); + return bd; + } // round + + /************************************************************************** + * Get C_UOM_ID + * @return uom + */ + public int getC_UOM_ID() + { + if (!m_calculated) + calculatePrice(); + return m_C_UOM_ID; + } + + /** + * Get Price List + * @return list + */ + public BigDecimal getPriceList() + { + if (!m_calculated) + calculatePrice(); + return round(m_PriceList); + } + /** + * Get Price Std + * @return std + */ + public BigDecimal getPriceStd() + { + if (!m_calculated) + calculatePrice(); + return round(m_PriceStd); + } + /** + * Get Price Limit + * @return limit + */ + public BigDecimal getPriceLimit() + { + if (!m_calculated) + calculatePrice(); + return round(m_PriceLimit); + } + /** + * Get Price List Currency + * @return currency + */ + public int getC_Currency_ID() + { + if (!m_calculated) + calculatePrice(); + return m_C_Currency_ID; + } + /** + * Is Price List enforded? + * @return enforce limit + */ + public boolean isEnforcePriceLimit() + { + if (!m_calculated) + calculatePrice(); + return m_enforcePriceLimit; + } // isEnforcePriceLimit + + /** + * Is a DiscountSchema active? + * @return active Discount Schema + */ + public boolean isDiscountSchema() + { + return m_discountSchema; + } // isDiscountSchema + + /** + * Is the Price Calculated (i.e. found)? + * @return calculated + */ + public boolean isCalculated() + { + return m_calculated; + } // isCalculated + +} // MProductPrice diff --git a/base/src/org/compiere/model/MProject.java b/base/src/org/compiere/model/MProject.java new file mode 100644 index 0000000000..d4e586c15b --- /dev/null +++ b/base/src/org/compiere/model/MProject.java @@ -0,0 +1,515 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Project Model + * + * @author Jorg Janke + * @version $Id: MProject.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MProject extends X_C_Project +{ + /** + * Create new Project by copying + * @param ctx context + * @param C_Project_ID project + * @param dateDoc date of the document date + * @param trxName transaction + * @return Project + */ + public static MProject copyFrom (Properties ctx, int C_Project_ID, Timestamp dateDoc, String trxName) + { + MProject from = new MProject (ctx, C_Project_ID, trxName); + if (from.getC_Project_ID() == 0) + throw new IllegalArgumentException ("From Project not found C_Project_ID=" + C_Project_ID); + // + MProject to = new MProject (ctx, 0, trxName); + PO.copyValues(from, to, from.getAD_Client_ID(), from.getAD_Org_ID()); + to.set_ValueNoCheck ("C_Project_ID", I_ZERO); + // Set Value with Time + String Value = to.getValue() + " "; + String Time = dateDoc.toString(); + int length = Value.length() + Time.length(); + if (length <= 40) + Value += Time; + else + Value += Time.substring (length-40); + to.setValue(Value); + to.setInvoicedAmt(Env.ZERO); + to.setProjectBalanceAmt(Env.ZERO); + to.setProcessed(false); + // + if (!to.save()) + throw new IllegalStateException("Could not create Project"); + + if (to.copyDetailsFrom(from) == 0) + throw new IllegalStateException("Could not create Project Details"); + + return to; + } // copyFrom + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param C_Project_ID id + * @param trxName transaction + */ + public MProject (Properties ctx, int C_Project_ID, String trxName) + { + super (ctx, C_Project_ID, trxName); + if (C_Project_ID == 0) + { + // setC_Project_ID(0); + // setValue (null); + // setC_Currency_ID (0); + setCommittedAmt (Env.ZERO); + setCommittedQty (Env.ZERO); + setInvoicedAmt (Env.ZERO); + setInvoicedQty (Env.ZERO); + setPlannedAmt (Env.ZERO); + setPlannedMarginAmt (Env.ZERO); + setPlannedQty (Env.ZERO); + setProjectBalanceAmt (Env.ZERO); + // setProjectCategory(PROJECTCATEGORY_General); + setProjInvoiceRule(PROJINVOICERULE_None); + setProjectLineLevel(PROJECTLINELEVEL_Project); + setIsCommitCeiling (false); + setIsCommitment (false); + setIsSummary (false); + setProcessed (false); + } + } // MProject + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MProject (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MProject + + /** Cached PL */ + private int m_M_PriceList_ID = 0; + + /** + * Get Project Type as Int (is Button). + * @return C_ProjectType_ID id + */ + public int getC_ProjectType_ID_Int() + { + String pj = super.getC_ProjectType_ID(); + if (pj == null) + return 0; + int C_ProjectType_ID = 0; + try + { + C_ProjectType_ID = Integer.parseInt (pj); + } + catch (Exception ex) + { + log.log(Level.SEVERE, pj, ex); + } + return C_ProjectType_ID; + } // getC_ProjectType_ID_Int + + /** + * Set Project Type (overwrite r/o) + * @param C_ProjectType_ID id + */ + public void setC_ProjectType_ID (int C_ProjectType_ID) + { + if (C_ProjectType_ID == 0) + super.setC_ProjectType_ID (null); + else + super.setC_ProjectType_ID (String.valueOf(C_ProjectType_ID)); + } // setC_ProjectType_ID + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer ("MProject[").append(get_ID()) + .append("-").append(getValue()).append(",ProjectCategory=").append(getProjectCategory()) + .append("]"); + return sb.toString(); + } // toString + + /** + * Get Price List from Price List Version + * @return price list or 0 + */ + public int getM_PriceList_ID() + { + if (getM_PriceList_Version_ID() == 0) + return 0; + if (m_M_PriceList_ID > 0) + return m_M_PriceList_ID; + // + String sql = "SELECT M_PriceList_ID FROM M_PriceList_Version WHERE M_PriceList_Version_ID=?"; + m_M_PriceList_ID = DB.getSQLValue(null, sql, getM_PriceList_Version_ID()); + return m_M_PriceList_ID; + } // getM_PriceList_ID + + /** + * Set PL Version + * @param M_PriceList_Version_ID id + */ + public void setM_PriceList_Version_ID (int M_PriceList_Version_ID) + { + super.setM_PriceList_Version_ID(M_PriceList_Version_ID); + m_M_PriceList_ID = 0; // reset + } // setM_PriceList_Version_ID + + + /************************************************************************** + * Get Project Lines + * @return Array of lines + */ + public MProjectLine[] getLines() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_ProjectLine WHERE C_Project_ID=? ORDER BY Line"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_Project_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MProjectLine (getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close(); + } + catch (SQLException ex1) + { + } + pstmt = null; + // + MProjectLine[] retValue = new MProjectLine[list.size()]; + list.toArray(retValue); + return retValue; + } // getLines + + /** + * Get Project Issues + * @return Array of issues + */ + public MProjectIssue[] getIssues() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_ProjectIssue WHERE C_Project_ID=? ORDER BY Line"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_Project_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MProjectIssue (getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close(); + } + catch (SQLException ex1) + { + } + pstmt = null; + // + MProjectIssue[] retValue = new MProjectIssue[list.size()]; + list.toArray(retValue); + return retValue; + } // getIssues + + /** + * Get Project Phases + * @return Array of phases + */ + public MProjectPhase[] getPhases() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_ProjectPhase WHERE C_Project_ID=? ORDER BY SeqNo"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_Project_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MProjectPhase (getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close(); + } + catch (SQLException ex1) + { + } + pstmt = null; + // + MProjectPhase[] retValue = new MProjectPhase[list.size()]; + list.toArray(retValue); + return retValue; + } // getPhases + + + /************************************************************************** + * Copy Lines/Phase/Task from other Project + * @param project project + * @return number of total lines copied + */ + public int copyDetailsFrom (MProject project) + { + if (isProcessed() || project == null) + return 0; + int count = copyLinesFrom(project) + + copyPhasesFrom(project); + return count; + } // copyDetailsFrom + + /** + * Copy Lines From other Project + * @param project project + * @return number of lines copied + */ + public int copyLinesFrom (MProject project) + { + if (isProcessed() || project == null) + return 0; + int count = 0; + MProjectLine[] fromLines = project.getLines(); + for (int i = 0; i < fromLines.length; i++) + { + MProjectLine line = new MProjectLine (getCtx(), 0, project.get_TrxName()); + PO.copyValues(fromLines[i], line, getAD_Client_ID(), getAD_Org_ID()); + line.setC_Project_ID(getC_Project_ID()); + line.setInvoicedAmt(Env.ZERO); + line.setInvoicedQty(Env.ZERO); + line.setC_OrderPO_ID(0); + line.setC_Order_ID(0); + line.setProcessed(false); + if (line.save()) + count++; + } + if (fromLines.length != count) + log.log(Level.SEVERE, "Lines difference - Project=" + fromLines.length + " <> Saved=" + count); + + return count; + } // copyLinesFrom + + /** + * Copy Phases/Tasks from other Project + * @param fromProject project + * @return number of items copied + */ + public int copyPhasesFrom (MProject fromProject) + { + if (isProcessed() || fromProject == null) + return 0; + int count = 0; + int taskCount = 0; + // Get Phases + MProjectPhase[] myPhases = getPhases(); + MProjectPhase[] fromPhases = fromProject.getPhases(); + // Copy Phases + for (int i = 0; i < fromPhases.length; i++) + { + // Check if Phase already exists + int C_Phase_ID = fromPhases[i].getC_Phase_ID(); + boolean exists = false; + if (C_Phase_ID == 0) + exists = false; + else + { + for (int ii = 0; ii < myPhases.length; ii++) + { + if (myPhases[ii].getC_Phase_ID() == C_Phase_ID) + { + exists = true; + break; + } + } + } + // Phase exist + if (exists) + log.info("Phase already exists here, ignored - " + fromPhases[i]); + else + { + MProjectPhase toPhase = new MProjectPhase (getCtx (), 0, get_TrxName()); + PO.copyValues (fromPhases[i], toPhase, getAD_Client_ID (), getAD_Org_ID ()); + toPhase.setC_Project_ID (getC_Project_ID ()); + toPhase.setC_Order_ID (0); + toPhase.setIsComplete (false); + if (toPhase.save ()) + { + count++; + taskCount += toPhase.copyTasksFrom (fromPhases[i]); + } + } + } + if (fromPhases.length != count) + log.warning("Count difference - Project=" + fromPhases.length + " <> Saved=" + count); + + return count + taskCount; + } // copyPhasesFrom + + + /** + * Set Project Type and Category. + * If Service Project copy Projet Type Phase/Tasks + * @param type project type + */ + public void setProjectType (MProjectType type) + { + if (type == null) + return; + setC_ProjectType_ID(type.getC_ProjectType_ID()); + setProjectCategory(type.getProjectCategory()); + if (PROJECTCATEGORY_ServiceChargeProject.equals(getProjectCategory())) + copyPhasesFrom(type); + } // setProjectType + + /** + * Copy Phases from Type + * @param type Project Type + * @return count + */ + public int copyPhasesFrom (MProjectType type) + { + // create phases + int count = 0; + int taskCount = 0; + MProjectTypePhase[] typePhases = type.getPhases(); + for (int i = 0; i < typePhases.length; i++) + { + MProjectPhase toPhase = new MProjectPhase (this, typePhases[i]); + if (toPhase.save()) + { + count++; + taskCount += toPhase.copyTasksFrom(typePhases[i]); + } + } + log.fine("#" + count + "/" + taskCount + + " - " + type); + if (typePhases.length != count) + log.log(Level.SEVERE, "Count difference - Type=" + typePhases.length + " <> Saved=" + count); + return count; + } // copyPhasesFrom + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getAD_User_ID() == -1) // Summary Project in Dimensions + setAD_User_ID(0); + + // Set Currency + if (is_ValueChanged("M_PriceList_Version_ID") && getM_PriceList_Version_ID() != 0) + { + MPriceList pl = MPriceList.get(getCtx(), getM_PriceList_ID(), null); + if (pl != null && pl.get_ID() != 0) + setC_Currency_ID(pl.getC_Currency_ID()); + } + + return true; + } // beforeSave + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (newRecord & success) + { + insert_Accounting("C_Project_Acct", "C_AcctSchema_Default", null); + insert_Tree(MTree_Base.TREETYPE_Project); + } + + // Value/Name change + if (success && !newRecord + && (is_ValueChanged("Value") || is_ValueChanged("Name"))) + MAccount.updateValueDescription(getCtx(), "C_Project_ID=" + getC_Project_ID(), get_TrxName()); + + return success; + } // afterSave + + /** + * Before Delete + * @return true + */ + protected boolean beforeDelete () + { + return delete_Accounting("C_Project_Acct"); + } // beforeDelete + + /** + * After Delete + * @param success + * @return deleted + */ + protected boolean afterDelete (boolean success) + { + if (success) + delete_Tree(MTree_Base.TREETYPE_Project); + return success; + } // afterDelete + +} // MProject diff --git a/base/src/org/compiere/model/MProjectIssue.java b/base/src/org/compiere/model/MProjectIssue.java new file mode 100644 index 0000000000..800ddf8e85 --- /dev/null +++ b/base/src/org/compiere/model/MProjectIssue.java @@ -0,0 +1,179 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Project Issue Model + * + * @author Jorg Janke + * @version $Id: MProjectIssue.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MProjectIssue extends X_C_ProjectIssue +{ + + /** + * Standard Constructor + * @param ctx context + * @param C_ProjectIssue_ID id + * @param trxName transaction + */ + public MProjectIssue (Properties ctx, int C_ProjectIssue_ID, String trxName) + { + super (ctx, C_ProjectIssue_ID, trxName); + if (C_ProjectIssue_ID == 0) + { + // setC_Project_ID (0); + // setLine (0); + // setM_Locator_ID (0); + // setM_Product_ID (0); + // setMovementDate (new Timestamp(System.currentTimeMillis())); + setMovementQty (Env.ZERO); + setPosted (false); + setProcessed (false); + } + } // MProjectIssue + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MProjectIssue (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MProjectIssue + + /** + * New Parent Constructor + * @param project parent + */ + public MProjectIssue (MProject project) + { + this (project.getCtx(), 0, project.get_TrxName()); + setClientOrg(project.getAD_Client_ID(), project.getAD_Org_ID()); + setC_Project_ID (project.getC_Project_ID()); // Parent + setLine (getNextLine()); + m_parent = project; + // + // setM_Locator_ID (0); + // setM_Product_ID (0); + // + setMovementDate (new Timestamp(System.currentTimeMillis())); + setMovementQty (Env.ZERO); + setPosted (false); + setProcessed (false); + } // MProjectIssue + + /** Parent */ + private MProject m_parent = null; + + /** + * Get the next Line No + * @return next line no + */ + private int getNextLine() + { + return DB.getSQLValue(get_TrxName(), + "SELECT COALESCE(MAX(Line),0)+10 FROM C_ProjectIssue WHERE C_Project_ID=?", getC_Project_ID()); + } // getLineFromProject + + /** + * Set Mandatory Values + * @param M_Locator_ID locator + * @param M_Product_ID product + * @param MovementQty qty + */ + public void setMandatory (int M_Locator_ID, int M_Product_ID, BigDecimal MovementQty) + { + setM_Locator_ID (M_Locator_ID); + setM_Product_ID (M_Product_ID); + setMovementQty (MovementQty); + } // setMandatory + + /** + * Get Parent + * @return project + */ + public MProject getParent() + { + if (m_parent == null && getC_Project_ID() != 0) + m_parent = new MProject (getCtx(), getC_Project_ID(), get_TrxName()); + return m_parent; + } // getParent + + /************************************************************************** + * Process Issue + * @return true if processed + */ + public boolean process() + { + if (!save()) + return false; + if (getM_Product_ID() == 0) + { + log.log(Level.SEVERE, "No Product"); + return false; + } + + MProduct product = MProduct.get (getCtx(), getM_Product_ID()); + + // If not a stocked Item nothing to do + if (!product.isStocked()) + { + setProcessed(true); + return save(); + } + + /** @todo Transaction */ + + // ** Create Material Transactions ** + MTransaction mTrx = new MTransaction (getCtx(), getAD_Org_ID(), + MTransaction.MOVEMENTTYPE_WorkOrderPlus, + getM_Locator_ID(), getM_Product_ID(), getM_AttributeSetInstance_ID(), + getMovementQty().negate(), getMovementDate(), get_TrxName()); + mTrx.setC_ProjectIssue_ID(getC_ProjectIssue_ID()); + // + MLocator loc = MLocator.get(getCtx(), getM_Locator_ID()); + if (MStorage.add(getCtx(), loc.getM_Warehouse_ID(), getM_Locator_ID(), + getM_Product_ID(), getM_AttributeSetInstance_ID(), getM_AttributeSetInstance_ID(), + getMovementQty().negate(), null, null, get_TrxName())) + { + if (mTrx.save(get_TrxName())) + { + setProcessed (true); + if (save()) + return true; + else + log.log(Level.SEVERE, "Issue not saved"); // requires trx !! + } + else + log.log(Level.SEVERE, "Transaction not saved"); // requires trx !! + } + else + log.log(Level.SEVERE, "Storage not updated"); // OK + // + return false; + } // process + +} // MProjectIssue diff --git a/base/src/org/compiere/model/MProjectLine.java b/base/src/org/compiere/model/MProjectLine.java new file mode 100644 index 0000000000..a5c4dd82a8 --- /dev/null +++ b/base/src/org/compiere/model/MProjectLine.java @@ -0,0 +1,272 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Project Line Model + * + * @author Jorg Janke + * @version $Id: MProjectLine.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MProjectLine extends X_C_ProjectLine +{ + /** + * Standard Constructor + * @param ctx context + * @param C_ProjectLine_ID id + * @param trxName transaction + */ + public MProjectLine (Properties ctx, int C_ProjectLine_ID, String trxName) + { + super (ctx, C_ProjectLine_ID, trxName); + if (C_ProjectLine_ID == 0) + { + // setC_Project_ID (0); + // setC_ProjectLine_ID (0); + setLine (0); + setIsPrinted(true); + setProcessed(false); + setInvoicedAmt (Env.ZERO); + setInvoicedQty (Env.ZERO); + // + setPlannedAmt (Env.ZERO); + setPlannedMarginAmt (Env.ZERO); + setPlannedPrice (Env.ZERO); + setPlannedQty (Env.ONE); + } + } // MProjectLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MProjectLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MProjectLine + + /** + * Parent Constructor + * @param project parent + */ + public MProjectLine (MProject project) + { + this (project.getCtx(), 0, project.get_TrxName()); + setClientOrg(project); + setC_Project_ID (project.getC_Project_ID()); // Parent + setLine(); + } // MProjectLine + + /** Parent */ + private MProject m_parent = null; + + /** + * Get the next Line No + */ + private void setLine() + { + setLine(DB.getSQLValue(get_TrxName(), + "SELECT COALESCE(MAX(Line),0)+10 FROM C_ProjectLine WHERE C_Project_ID=?", getC_Project_ID())); + } // setLine + + /** + * Set Product, committed qty, etc. + * @param pi project issue + */ + public void setMProjectIssue (MProjectIssue pi) + { + setC_ProjectIssue_ID(pi.getC_ProjectIssue_ID()); + setM_Product_ID(pi.getM_Product_ID()); + setCommittedQty(pi.getMovementQty()); + if (getDescription() != null) + setDescription(pi.getDescription()); + } // setMProjectIssue + + /** + * Set PO + * @param C_OrderPO_ID po id + */ + public void setC_OrderPO_ID (int C_OrderPO_ID) + { + super.setC_OrderPO_ID(C_OrderPO_ID); + } // setC_OrderPO_ID + + /** + * Get Project + * @return parent + */ + public MProject getProject() + { + if (m_parent == null && getC_Project_ID() != 0) + { + m_parent = new MProject (getCtx(), getC_Project_ID(), get_TrxName()); + if (get_TrxName() != null) + m_parent.load(get_TrxName()); + } + return m_parent; + } // getProject + + /** + * Get Limit Price if exists + * @return limit + */ + public BigDecimal getLimitPrice() + { + BigDecimal limitPrice = getPlannedPrice(); + if (getM_Product_ID() == 0) + return limitPrice; + if (getProject() == null) + return limitPrice; + boolean isSOTrx = true; + MProductPricing pp = new MProductPricing (getM_Product_ID(), + m_parent.getC_BPartner_ID(), getPlannedQty(), isSOTrx); + pp.setM_PriceList_ID(m_parent.getM_PriceList_ID()); + if (pp.calculatePrice()) + limitPrice = pp.getPriceLimit(); + return limitPrice; + } // getLimitPrice + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MProjectLine["); + sb.append (get_ID()).append ("-") + .append (getLine()) + .append(",C_Project_ID=").append(getC_Project_ID()) + .append(",C_ProjectPhase_ID=").append(getC_ProjectPhase_ID()) + .append(",C_ProjectTask_ID=").append(getC_ProjectTask_ID()) + .append(",C_ProjectIssue_ID=").append(getC_ProjectIssue_ID()) + .append(", M_Product_ID=").append(getM_Product_ID()) + .append(", PlannedQty=").append(getPlannedQty()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getLine() == 0) + setLine(); + + // Planned Amount + setPlannedAmt(getPlannedQty().multiply(getPlannedPrice())); + + // Planned Margin + if (is_ValueChanged("M_Product_ID") || is_ValueChanged("M_Product_Category_ID") + || is_ValueChanged("PlannedQty") || is_ValueChanged("PlannedPrice")) + { + if (getM_Product_ID() != 0) + { + BigDecimal marginEach = getPlannedPrice().subtract(getLimitPrice()); + setPlannedMarginAmt(marginEach.multiply(getPlannedQty())); + } + else if (getM_Product_Category_ID() != 0) + { + MProductCategory category = MProductCategory.get(getCtx(), getM_Product_Category_ID()); + BigDecimal marginEach = category.getPlannedMargin(); + setPlannedMarginAmt(marginEach.multiply(getPlannedQty())); + } + } + + // Phase/Task + if (is_ValueChanged("C_ProjectTask_ID") && getC_ProjectTask_ID() != 0) + { + MProjectTask pt = new MProjectTask(getCtx(), getC_ProjectTask_ID(), get_TrxName()); + if (pt == null || pt.get_ID() == 0) + { + log.warning("Project Task Not Found - ID=" + getC_ProjectTask_ID()); + return false; + } + else + setC_ProjectPhase_ID(pt.getC_ProjectPhase_ID()); + } + if (is_ValueChanged("C_ProjectPhase_ID") && getC_ProjectPhase_ID() != 0) + { + MProjectPhase pp = new MProjectPhase(getCtx(), getC_ProjectPhase_ID(), get_TrxName()); + if (pp == null || pp.get_ID() == 0) + { + log.warning("Project Phase Not Found - " + getC_ProjectPhase_ID()); + return false; + } + else + setC_Project_ID(pp.getC_Project_ID()); + } + + return true; + } // beforeSave + + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + updateHeader(); + return success; + } // afterSave + + + /** + * After Delete + * @param success success + * @return success + */ + protected boolean afterDelete (boolean success) + { + updateHeader(); + return success; + } // afterDelete + + /** + * Update Header + */ + private void updateHeader() + { + String sql = "UPDATE C_Project p " + + "SET (PlannedAmt,PlannedQty,PlannedMarginAmt," + + " CommittedAmt,CommittedQty," + + " InvoicedAmt, InvoicedQty) = " + + "(SELECT COALESCE(SUM(pl.PlannedAmt),0),COALESCE(SUM(pl.PlannedQty),0),COALESCE(SUM(pl.PlannedMarginAmt),0)," + + " COALESCE(SUM(pl.CommittedAmt),0),COALESCE(SUM(pl.CommittedQty),0)," + + " COALESCE(SUM(pl.InvoicedAmt),0), COALESCE(SUM(pl.InvoicedQty),0) " + + "FROM C_ProjectLine pl " + + "WHERE pl.C_Project_ID=p.C_Project_ID AND pl.IsActive='Y') " + + "WHERE C_Project_ID=" + getC_Project_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + if (no != 1) + log.log(Level.SEVERE, "updateHeader - #" + no); + } // updateHeader + +} // MProjectLine diff --git a/base/src/org/compiere/model/MProjectPhase.java b/base/src/org/compiere/model/MProjectPhase.java new file mode 100644 index 0000000000..8e8036bf1d --- /dev/null +++ b/base/src/org/compiere/model/MProjectPhase.java @@ -0,0 +1,226 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Project Phase Model + * + * @author Jorg Janke + * @version $Id: MProjectPhase.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MProjectPhase extends X_C_ProjectPhase +{ + /** + * Standard Constructor + * @param ctx context + * @param C_ProjectPhase_ID id + * @param trxName transaction + */ + public MProjectPhase (Properties ctx, int C_ProjectPhase_ID, String trxName) + { + super (ctx, C_ProjectPhase_ID, trxName); + if (C_ProjectPhase_ID == 0) + { + // setC_ProjectPhase_ID (0); // PK + // setC_Project_ID (0); // Parent + // setC_Phase_ID (0); // FK + setCommittedAmt (Env.ZERO); + setIsCommitCeiling (false); + setIsComplete (false); + setSeqNo (0); + // setName (null); + setQty (Env.ZERO); + } + } // MProjectPhase + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MProjectPhase (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MProjectPhase + + /** + * Parent Constructor + * @param project parent + */ + public MProjectPhase (MProject project) + { + this (project.getCtx(), 0, project.get_TrxName()); + setClientOrg(project); + setC_Project_ID(project.getC_Project_ID()); + } // MProjectPhase + + /** + * Copy Constructor + * @param project parent + * @param phase copy + */ + public MProjectPhase (MProject project, MProjectTypePhase phase) + { + this (project); + // + setC_Phase_ID (phase.getC_Phase_ID()); // FK + setName (phase.getName()); + setSeqNo (phase.getSeqNo()); + setDescription(phase.getDescription()); + setHelp(phase.getHelp()); + if (phase.getM_Product_ID() != 0) + setM_Product_ID(phase.getM_Product_ID()); + setQty(phase.getStandardQty()); + } // MProjectPhase + + /** + * Get Project Phase Tasks. + * @return Array of tasks + */ + public MProjectTask[] getTasks() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_ProjectTask WHERE C_ProjectPhase_ID=? ORDER BY SeqNo"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_ProjectPhase_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MProjectTask (getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close(); + } + catch (SQLException ex1) + { + } + pstmt = null; + // + MProjectTask[] retValue = new MProjectTask[list.size()]; + list.toArray(retValue); + return retValue; + } // getTasks + + + /** + * Copy Tasks from other Phase + * @param fromPhase from phase + * @return number of tasks copied + */ + public int copyTasksFrom (MProjectPhase fromPhase) + { + if (fromPhase == null) + return 0; + int count = 0; + // + MProjectTask[] myTasks = getTasks(); + MProjectTask[] fromTasks = fromPhase.getTasks(); + // Copy Project Tasks + for (int i = 0; i < fromTasks.length; i++) + { + // Check if Task already exists + int C_Task_ID = fromTasks[i].getC_Task_ID(); + boolean exists = false; + if (C_Task_ID == 0) + exists = false; + else + { + for (int ii = 0; ii < myTasks.length; ii++) + { + if (myTasks[ii].getC_Task_ID() == C_Task_ID) + { + exists = true; + break; + } + } + } + // Phase exist + if (exists) + log.info("Task already exists here, ignored - " + fromTasks[i]); + else + { + MProjectTask toTask = new MProjectTask (getCtx (), 0, get_TrxName()); + PO.copyValues (fromTasks[i], toTask, getAD_Client_ID (), getAD_Org_ID ()); + toTask.setC_ProjectPhase_ID (getC_ProjectPhase_ID ()); + if (toTask.save ()) + count++; + } + } + if (fromTasks.length != count) + log.warning("Count difference - ProjectPhase=" + fromTasks.length + " <> Saved=" + count); + + return count; + } // copyTasksFrom + + /** + * Copy Tasks from other Phase + * @param fromPhase from phase + * @return number of tasks copied + */ + public int copyTasksFrom (MProjectTypePhase fromPhase) + { + if (fromPhase == null) + return 0; + int count = 0; + // Copy Type Tasks + MProjectTypeTask[] fromTasks = fromPhase.getTasks(); + for (int i = 0; i < fromTasks.length; i++) + { + MProjectTask toTask = new MProjectTask (this, fromTasks[i]); + if (toTask.save()) + count++; + } + log.fine("#" + count + " - " + fromPhase); + if (fromTasks.length != count) + log.log(Level.SEVERE, "Count difference - TypePhase=" + fromTasks.length + " <> Saved=" + count); + + return count; + } // copyTasksFrom + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MProjectPhase["); + sb.append (get_ID()) + .append ("-").append (getSeqNo()) + .append ("-").append (getName()) + .append ("]"); + return sb.toString (); + } // toString + +} // MProjectPhase diff --git a/base/src/org/compiere/model/MProjectTask.java b/base/src/org/compiere/model/MProjectTask.java new file mode 100644 index 0000000000..1a61a8ade6 --- /dev/null +++ b/base/src/org/compiere/model/MProjectTask.java @@ -0,0 +1,106 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Project Phase Task Model + * + * @author Jorg Janke + * @version $Id: MProjectTask.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MProjectTask extends X_C_ProjectTask +{ + /** + * Standard Constructor + * @param ctx context + * @param C_ProjectTask_ID id + * @param trxName transaction + */ + public MProjectTask (Properties ctx, int C_ProjectTask_ID, String trxName) + { + super (ctx, C_ProjectTask_ID, trxName); + if (C_ProjectTask_ID == 0) + { + // setC_ProjectTask_ID (0); // PK + // setC_ProjectPhase_ID (0); // Parent + // setC_Task_ID (0); // FK + setSeqNo (0); + // setName (null); + setQty (Env.ZERO); + } + } // MProjectTask + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MProjectTask (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MProjectTask + + /** + * Parent Constructor + * @param phase parent + */ + public MProjectTask (MProjectPhase phase) + { + this (phase.getCtx(), 0, phase.get_TrxName()); + setClientOrg(phase); + setC_ProjectPhase_ID(phase.getC_ProjectPhase_ID()); + } // MProjectTask + + /** + * Copy Constructor + * @param phase parent + * @param task type copy + */ + public MProjectTask (MProjectPhase phase, MProjectTypeTask task) + { + this (phase); + // + setC_Task_ID (task.getC_Task_ID()); // FK + setSeqNo (task.getSeqNo()); + setName (task.getName()); + setDescription(task.getDescription()); + setHelp(task.getHelp()); + if (task.getM_Product_ID() != 0) + setM_Product_ID(task.getM_Product_ID()); + setQty(task.getStandardQty()); + } // MProjectTask + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MProjectTask["); + sb.append (get_ID()) + .append ("-").append (getSeqNo()) + .append ("-").append (getName()) + .append ("]"); + return sb.toString (); + } // toString + +} // MProjectTask diff --git a/base/src/org/compiere/model/MProjectType.java b/base/src/org/compiere/model/MProjectType.java new file mode 100644 index 0000000000..7b968d6965 --- /dev/null +++ b/base/src/org/compiere/model/MProjectType.java @@ -0,0 +1,305 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Project Type Model + * + * @author Jorg Janke + * @version $Id: MProjectType.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MProjectType extends X_C_ProjectType +{ + /** + * Get MProjectType from Cache + * @param ctx context + * @param C_ProjectType_ID id + * @return MProjectType + */ + public static MProjectType get (Properties ctx, int C_ProjectType_ID) + { + Integer key = new Integer (C_ProjectType_ID); + MProjectType retValue = (MProjectType)s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MProjectType (ctx, C_ProjectType_ID, null); + if (retValue.get_ID() != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache + = new CCache ("C_ProjectType", 20); + + + /************************************************************************** + * Standrad Constructor + * @param ctx context + * @param C_ProjectType_ID id + * @param trxName trx + */ + public MProjectType (Properties ctx, int C_ProjectType_ID, String trxName) + { + super (ctx, C_ProjectType_ID, trxName); + /** + if (C_ProjectType_ID == 0) + { + setC_ProjectType_ID (0); + setName (null); + } + **/ + } // MProjectType + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MProjectType (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MProjectType + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer ("MProjectType[") + .append(get_ID()) + .append("-").append(getName()) + .append("]"); + return sb.toString(); + } // toString + + + /************************************************************************** + * Get Project Type Phases + * @return Array of phases + */ + public MProjectTypePhase[] getPhases() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_Phase WHERE C_ProjectType_ID=? ORDER BY SeqNo"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_ProjectType_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MProjectTypePhase (getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close(); + } + catch (SQLException ex1) + { + } + pstmt = null; + // + MProjectTypePhase[] retValue = new MProjectTypePhase[list.size()]; + list.toArray(retValue); + return retValue; + } // getPhases + + /** + * Get Sql to return single value for the Performance Indicator + * @param restrictions array of goal restrictions + * @param MeasureScope scope of this value + * @param MeasureDataType data type + * @param reportDate optional report date + * @param role role + * @return sql for performance indicator + */ + public String getSqlPI (MGoalRestriction[] restrictions, + String MeasureScope, String MeasureDataType, Timestamp reportDate, MRole role) + { + String dateColumn = "Created"; + String orgColumn = "AD_Org_ID"; + String bpColumn = "C_BPartner_ID"; + String pColumn = null; + // PlannedAmt -> PlannedQty -> Count + StringBuffer sb = new StringBuffer("SELECT COALESCE(SUM(PlannedAmt),COALESCE(SUM(PlannedQty),COUNT(*))) " + + "FROM C_Project WHERE C_ProjectType_ID=" + getC_ProjectType_ID() + + " AND Processed<>'Y')"); + // Date Restriction + + if (MMeasure.MEASUREDATATYPE_QtyAmountInTime.equals(MeasureDataType) + && !MGoal.MEASUREDISPLAY_Total.equals(MeasureScope)) + { + if (reportDate == null) + reportDate = new Timestamp(System.currentTimeMillis()); + String dateString = DB.TO_DATE(reportDate); + String trunc = "D"; + if (MGoal.MEASUREDISPLAY_Year.equals(MeasureScope)) + trunc = "Y"; + else if (MGoal.MEASUREDISPLAY_Quarter.equals(MeasureScope)) + trunc = "Q"; + else if (MGoal.MEASUREDISPLAY_Month.equals(MeasureScope)) + trunc = "MM"; + else if (MGoal.MEASUREDISPLAY_Week.equals(MeasureScope)) + trunc = "W"; + // else if (MGoal.MEASUREDISPLAY_Day.equals(MeasureDisplay)) + // ; + sb.append(" AND TRUNC(") + .append(dateColumn).append(",'").append(trunc).append("')=TRUNC(") + .append(DB.TO_DATE(reportDate)).append(",'").append(trunc).append("')"); + } // date + // + String sql = MMeasureCalc.addRestrictions(sb.toString(), false, restrictions, role, + "C_Project", orgColumn, bpColumn, pColumn); + + log.fine(sql); + return sql; + } // getSql + + /** + * Get Sql to value for the bar chart + * @param restrictions array of goal restrictions + * @param MeasureDisplay scope of this value + * @param MeasureDataType data type + * @param startDate optional report start date + * @param role role + * @return sql for Bar Chart + */ + public String getSqlBarChart (MGoalRestriction[] restrictions, + String MeasureDisplay, String MeasureDataType, + Timestamp startDate, MRole role) + { + String dateColumn = "Created"; + String orgColumn = "AD_Org_ID"; + String bpColumn = "C_BPartner_ID"; + String pColumn = null; + // + StringBuffer sb = new StringBuffer("SELECT COALESCE(SUM(PlannedAmt),COALESCE(SUM(PlannedQty),COUNT(*))), "); + String orderBy = null; + String groupBy = null; + // + if (MMeasure.MEASUREDATATYPE_QtyAmountInTime.equals(MeasureDataType) + && !MGoal.MEASUREDISPLAY_Total.equals(MeasureDisplay)) + { + String trunc = "D"; + if (MGoal.MEASUREDISPLAY_Year.equals(MeasureDisplay)) + trunc = "Y"; + else if (MGoal.MEASUREDISPLAY_Quarter.equals(MeasureDisplay)) + trunc = "Q"; + else if (MGoal.MEASUREDISPLAY_Month.equals(MeasureDisplay)) + trunc = "MM"; + else if (MGoal.MEASUREDISPLAY_Week.equals(MeasureDisplay)) + trunc = "W"; + // else if (MGoal.MEASUREDISPLAY_Day.equals(MeasureDisplay)) + // ; + orderBy = "TRUNC(" + dateColumn + ",'" + trunc + "')"; + groupBy = orderBy + ", 0 "; + sb.append(groupBy) + .append("FROM C_Project "); + } + else + { + orderBy = "p.SeqNo"; + groupBy = "COALESCE(p.Name,TO_NCHAR('-')), p.C_Phase_ID, p.SeqNo "; + sb.append(groupBy) + .append("FROM C_Project LEFT OUTER JOIN C_Phase p ON (C_Project.C_Phase_ID=p.C_Phase_ID) "); + } + // Where + sb.append("WHERE C_Project.C_ProjectType_ID=").append(getC_ProjectType_ID()) + .append(" AND C_Project.Processed<>'Y'"); + // Date Restriction + if (startDate != null + && !MGoal.MEASUREDISPLAY_Total.equals(MeasureDisplay)) + { + String dateString = DB.TO_DATE(startDate); + sb.append(" AND ").append(dateColumn) + .append(">=").append(dateString); + } // date + // + String sql = MMeasureCalc.addRestrictions(sb.toString(), false, restrictions, role, + "C_Project", orgColumn, bpColumn, pColumn); + if (groupBy != null) + sql += " GROUP BY " + groupBy + " ORDER BY " + orderBy; + // + log.fine(sql); + return sql; + } // getSqlBarChart + + /** + * Get Zoom Query + * @param restrictions restrictions + * @param MeasureDisplay display + * @param date date + * @param C_Phase_ID phase + * @param role role + * @return query + */ + public MQuery getQuery(MGoalRestriction[] restrictions, + String MeasureDisplay, Timestamp date, int C_Phase_ID, MRole role) + { + String dateColumn = "Created"; + String orgColumn = "AD_Org_ID"; + String bpColumn = "C_BPartner_ID"; + String pColumn = null; + // + MQuery query = new MQuery("C_Project"); + query.addRangeRestriction("C_ProjectType_ID", "=", getC_ProjectType_ID()); + // + String where = null; + if (C_Phase_ID != 0) + where = "C_Phase_ID=" + C_Phase_ID; + else + { + String trunc = "D"; + if (MGoal.MEASUREDISPLAY_Year.equals(MeasureDisplay)) + trunc = "Y"; + else if (MGoal.MEASUREDISPLAY_Quarter.equals(MeasureDisplay)) + trunc = "Q"; + else if (MGoal.MEASUREDISPLAY_Month.equals(MeasureDisplay)) + trunc = "MM"; + else if (MGoal.MEASUREDISPLAY_Week.equals(MeasureDisplay)) + trunc = "W"; + // else if (MGoal.MEASUREDISPLAY_Day.equals(MeasureDisplay)) + // trunc = "D"; + where = "TRUNC(" + dateColumn + ",'" + trunc + + "')=TRUNC(" + DB.TO_DATE(date) + ",'" + trunc + "')"; + } + String sql = MMeasureCalc.addRestrictions(where + " AND Processed<>'Y' ", + true, restrictions, role, + "C_Project", orgColumn, bpColumn, pColumn); + query.addRestriction(sql); + query.setRecordCount(1); + return query; + } // getQuery + +} // MProjectType diff --git a/base/src/org/compiere/model/MProjectTypePhase.java b/base/src/org/compiere/model/MProjectTypePhase.java new file mode 100644 index 0000000000..13eab5f53b --- /dev/null +++ b/base/src/org/compiere/model/MProjectTypePhase.java @@ -0,0 +1,102 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Project Type Phase Model + * + * @author Jorg Janke + * @version $Id: MProjectTypePhase.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MProjectTypePhase extends X_C_Phase +{ + /** + * Standard Constructor + * @param ctx context + * @param C_Phase_ID id + * @param trxName trx + */ + public MProjectTypePhase (Properties ctx, int C_Phase_ID, String trxName) + { + super (ctx, C_Phase_ID, trxName); + if (C_Phase_ID == 0) + { + // setC_Phase_ID (0); // PK + // setC_ProjectType_ID (0); // Parent + // setName (null); + setSeqNo (0); + setStandardQty (Env.ZERO); + } + } // MProjectTypePhase + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName + */ + public MProjectTypePhase (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MProjectTypePhase + + /** + * Get Project Type Phases + * @return Array of phases + */ + public MProjectTypeTask[] getTasks() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_Task WHERE C_Phase_ID=? ORDER BY SeqNo"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_Phase_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MProjectTypeTask (getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close(); + } + catch (SQLException ex1) + { + } + pstmt = null; + // + MProjectTypeTask[] retValue = new MProjectTypeTask[list.size()]; + list.toArray(retValue); + return retValue; + } // getPhases + +} // MProjectTypePhase diff --git a/base/src/org/compiere/model/MProjectTypeTask.java b/base/src/org/compiere/model/MProjectTypeTask.java new file mode 100644 index 0000000000..37645acc7d --- /dev/null +++ b/base/src/org/compiere/model/MProjectTypeTask.java @@ -0,0 +1,49 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Project Type Phase Task Model + * + * @author Jorg Janke + * @version $Id: MProjectTypeTask.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MProjectTypeTask extends X_C_Task +{ + public MProjectTypeTask (Properties ctx, int C_Task_ID, String trxName) + { + super (ctx, C_Task_ID, trxName); + if (C_Task_ID == 0) + { + // setC_Task_ID (0); // PK + // setC_Phase_ID (0); // Parent + // setName (null); + setSeqNo (0); + setStandardQty (Env.ZERO); + } + } // MProjectTypeTask + + public MProjectTypeTask (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MProjectTypeTask + +} // MProjectTypeTask diff --git a/base/src/org/compiere/model/MRMA.java b/base/src/org/compiere/model/MRMA.java new file mode 100644 index 0000000000..bc8eb5dce6 --- /dev/null +++ b/base/src/org/compiere/model/MRMA.java @@ -0,0 +1,447 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * RMA Model + * + * @author Jorg Janke + * @version $Id: MRMA.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MRMA extends X_M_RMA implements DocAction +{ + /** + * Standard Constructor + * @param ctx context + * @param M_RMA_ID id + * @param trxName transaction + */ + public MRMA (Properties ctx, int M_RMA_ID, String trxName) + { + super (ctx, M_RMA_ID, trxName); + if (M_RMA_ID == 0) + { + // setName (null); + // setSalesRep_ID (0); + // setC_DocType_ID (0); + // setM_InOut_ID (0); + setDocAction (DOCACTION_Complete); // CO + setDocStatus (DOCSTATUS_Drafted); // DR + setIsApproved(false); + setProcessed (false); + } + } // MRMA + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MRMA (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRMA + + /** Lines */ + private MRMALine[] m_lines = null; + /** The Shipment */ + private MInOut m_inout = null; + + /** + * Get Lines + * @param requery requary + * @return lines + */ + public MRMALine[] getLines (boolean requery) + { + if (m_lines != null && !requery) + return m_lines; + ArrayList list = new ArrayList(); + + String sql = "SELECT * FROM M_RMALine WHERE M_RMA_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getM_RMA_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MRMALine(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + m_lines = new MRMALine[list.size ()]; + list.toArray (m_lines); + return m_lines; + } // getLines + + /** + * Get Shipment + * @return shipment + */ + public MInOut getShipment() + { + if (m_inout == null && getM_InOut_ID() != 0) + m_inout = new MInOut (getCtx(), getM_InOut_ID(), get_TrxName()); + return m_inout; + } // getShipment + + + /** + * Set M_InOut_ID + * @param M_InOut_ID id + */ + public void setM_InOut_ID (int M_InOut_ID) + { + super.setM_InOut_ID (M_InOut_ID); + setC_Currency_ID(0); + setAmt(Env.ZERO); + setC_BPartner_ID(0); + m_inout = null; + } // setM_InOut_ID + + + /** + * Get Document Info + * @return document info (untranslated) + */ + public String getDocumentInfo() + { + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + return dt.getName() + " " + getDocumentNo(); + } // getDocumentInfo + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + // ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.INVOICE, getC_Invoice_ID()); + // if (re == null) + return null; + // return re.getPDF(file); + } // createPDF + + + /** + * Before Save + * Set BPartner, Currency + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Set BPartner + if (getC_BPartner_ID() == 0) + { + getShipment(); + if (m_inout != null) + setC_BPartner_ID(m_inout.getC_BPartner_ID()); + } + // Set Currency + if (getC_Currency_ID() == 0) + { + getShipment(); + if (m_inout != null) + { + if (m_inout.getC_Order_ID() != 0) + { + MOrder order = new MOrder (getCtx(), m_inout.getC_Order_ID(), get_TrxName()); + setC_Currency_ID(order.getC_Currency_ID()); + } + else if (m_inout.getC_Invoice_ID() != 0) + { + MInvoice invoice = new MInvoice (getCtx(), m_inout.getC_Invoice_ID(), get_TrxName()); + setC_Currency_ID(invoice.getC_Currency_ID()); + } + } + } + return true; + } // beforeSave + + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // process + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info("unlockIt - " + toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info("invalidateIt - " + toString()); + return true; + } // invalidateIt + + /** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + MRMALine[] lines = getLines(false); + if (lines.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + // Check Lines + BigDecimal amt = Env.ZERO; + for (int i = 0; i < lines.length; i++) + { + MRMALine line = lines[i]; + amt = amt.add(line.getAmt()); + } + setAmt(amt); + + m_justPrepared = true; + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info("approveIt - " + toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info("rejectIt - " + toString()); + setIsApproved(false); + return true; + } // rejectIt + + /** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + // Implicit Approval + if (!isApproved()) + approveIt(); + log.info("completeIt - " + toString()); + // + if (true) + { + m_processMsg = "Need to code creating the credit memo"; + return DocAction.STATUS_InProgress; + } + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + m_processMsg = valid; + return DocAction.STATUS_Invalid; + } + // + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + /** + * Void Document. + * @return true if success + */ + public boolean voidIt() + { + log.info("voidIt - " + toString()); + // Revoke Credit + return false; + } // voidIt + + /** + * Close Document. + * Cancel not delivered Qunatities + * @return true if success + */ + public boolean closeIt() + { + log.info("closeIt - " + toString()); + return true; + } // closeIt + + /** + * Reverse Correction + * @return true if success + */ + public boolean reverseCorrectIt() + { + log.info("reverseCorrectIt - " + toString()); + return false; + } // reverseCorrectionIt + + /** + * Reverse Accrual - none + * @return true if success + */ + public boolean reverseAccrualIt() + { + log.info("reverseAccrualIt - " + toString()); + return false; + } // reverseAccrualIt + + /** + * Re-activate + * @return true if success + */ + public boolean reActivateIt() + { + log.info("reActivateIt - " + toString()); + return false; + } // reActivateIt + + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getDocumentNo()); + // : Total Lines = 123.00 (#1) + sb.append(": "). + append(Msg.translate(getCtx(),"Amt")).append("=").append(getAmt()) + .append(" (#").append(getLines(false).length).append(")"); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner (Responsible) + * @return AD_User_ID + */ + public int getDoc_User_ID() + { + return getSalesRep_ID(); + } // getDoc_User_ID + + /** + * Get Document Approval Amount + * @return amount + */ + public BigDecimal getApprovalAmt() + { + return getAmt(); + } // getApprovalAmt + +} // MRMA diff --git a/base/src/org/compiere/model/MRMALine.java b/base/src/org/compiere/model/MRMALine.java new file mode 100644 index 0000000000..c73530db54 --- /dev/null +++ b/base/src/org/compiere/model/MRMALine.java @@ -0,0 +1,106 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + + +/** + * RMA Line Model + * + * @author Jorg Janke + * @version $Id: MRMALine.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MRMALine extends X_M_RMALine +{ + + /** + * Standard Constructor + * @param ctx context + * @param M_RMALine_ID id + * @param trxName transaction + */ + public MRMALine (Properties ctx, int M_RMALine_ID, String trxName) + { + super (ctx, M_RMALine_ID, trxName); + if (M_RMALine_ID == 0) + { + setQty(Env.ONE); + } + } // MRMALine + + /** + * Load Cosntructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MRMALine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRMALine + + /** Shipment Line */ + private MInOutLine m_ioLine = null; + + + /** + * Set M_InOutLine_ID + * @param M_InOutLine_ID + */ + public void setM_InOutLine_ID (int M_InOutLine_ID) + { + super.setM_InOutLine_ID (M_InOutLine_ID); + m_ioLine = null; + } // setM_InOutLine_ID + + /** + * Get Ship Line + * @return ship line + */ + public MInOutLine getShipLine() + { + if (m_ioLine == null && getM_InOutLine_ID() != 0) + m_ioLine = new MInOutLine (getCtx(), getM_InOutLine_ID(), get_TrxName()); + return m_ioLine; + } // getShipLine + + /** + * Get Total Amt + * @return amt + */ + public BigDecimal getAmt() + { + BigDecimal amt = Env.ZERO; + getShipLine(); + if (m_ioLine != null) + { + if (m_ioLine.getC_OrderLine_ID() != 0) + { + MOrderLine ol = new MOrderLine (getCtx(), m_ioLine.getC_OrderLine_ID(), get_TrxName()); + amt = ol.getPriceActual(); + } + } + // + return amt.multiply(getQty()); + } // getAmt + + +} // MRMALine diff --git a/base/src/org/compiere/model/MRecurring.java b/base/src/org/compiere/model/MRecurring.java new file mode 100644 index 0000000000..f4ccec0db4 --- /dev/null +++ b/base/src/org/compiere/model/MRecurring.java @@ -0,0 +1,207 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Recurring Model + * + * @author Jorg Janke + * @version $Id: MRecurring.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MRecurring extends X_C_Recurring +{ + public MRecurring (Properties ctx, int C_Recurring_ID, String trxName) + { + super (ctx, C_Recurring_ID, trxName); + if (C_Recurring_ID == 0) + { + // setC_Recurring_ID (0); // PK + setDateNextRun (new Timestamp(System.currentTimeMillis())); + setFrequencyType (FREQUENCYTYPE_Monthly); + setFrequency(1); + // setName (null); + // setRecurringType (null); + setRunsMax (1); + setRunsRemaining (0); + } + } // MRecurring + + public MRecurring (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRecurring + + /** + * String representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer ("MRecurring[") + .append(get_ID()).append(",").append(getName()); + if (getRecurringType().equals(MRecurring.RECURRINGTYPE_Order)) + sb.append(",C_Order_ID=").append(getC_Order_ID()); + else if (getRecurringType().equals(MRecurring.RECURRINGTYPE_Invoice)) + sb.append(",C_Invoice_ID=").append(getC_Invoice_ID()); + else if (getRecurringType().equals(MRecurring.RECURRINGTYPE_Project)) + sb.append(",C_Project_ID=").append(getC_Project_ID()); + else if (getRecurringType().equals(MRecurring.RECURRINGTYPE_GLJournal)) + sb.append(",GL_JournalBatch_ID=").append(getGL_JournalBatch_ID()); + sb.append(",Fequency=").append(getFrequencyType()).append("*").append(getFrequency()); + sb.append("]"); + return sb.toString(); + } // toString + + + /************************************************************************** + * Execute Run. + * @return clear text info + */ + public String executeRun() + { + Timestamp dateDoc = getDateNextRun(); + if (!calculateRuns()) + throw new IllegalStateException ("No Runs Left"); + + // log + MRecurringRun run = new MRecurringRun (getCtx(), this); + String msg = "@Created@ "; + + + // Copy + if (getRecurringType().equals(MRecurring.RECURRINGTYPE_Order)) + { + MOrder from = new MOrder (getCtx(), getC_Order_ID(), get_TrxName()); + MOrder order = MOrder.copyFrom (from, dateDoc, + from.getC_DocType_ID(), from.isSOTrx(), false, false, get_TrxName()); + run.setC_Order_ID(order.getC_Order_ID()); + msg += order.getDocumentNo(); + } + else if (getRecurringType().equals(MRecurring.RECURRINGTYPE_Invoice)) + { + MInvoice from = new MInvoice (getCtx(), getC_Invoice_ID(), get_TrxName()); + MInvoice invoice = MInvoice.copyFrom (from, dateDoc, + from.getC_DocType_ID(), from.isSOTrx(), false, get_TrxName(), false); + run.setC_Invoice_ID(invoice.getC_Invoice_ID()); + msg += invoice.getDocumentNo(); + } + else if (getRecurringType().equals(MRecurring.RECURRINGTYPE_Project)) + { + MProject project = MProject.copyFrom (getCtx(), getC_Project_ID(), dateDoc, get_TrxName()); + run.setC_Project_ID(project.getC_Project_ID()); + msg += project.getValue(); + } + else if (getRecurringType().equals(MRecurring.RECURRINGTYPE_GLJournal)) + { + MJournalBatch journal = MJournalBatch.copyFrom (getCtx(), getGL_JournalBatch_ID(), dateDoc, get_TrxName()); + run.setGL_JournalBatch_ID(journal.getGL_JournalBatch_ID()); + msg += journal.getDocumentNo(); + } + else + return "Invalid @RecurringType@ = " + getRecurringType(); + run.save(get_TrxName()); + + // + setDateLastRun (run.getUpdated()); + setRunsRemaining (getRunsRemaining()-1); + setDateNextRun(); + save(get_TrxName()); + return msg; + } // execureRun + + /** + * Calculate & set remaining Runs + * @return true if runs left + */ + private boolean calculateRuns() + { + String sql = "SELECT COUNT(*) FROM C_Recurring_Run WHERE C_Recurring_ID=?"; + int current = DB.getSQLValue(get_TrxName(), sql, getC_Recurring_ID()); + int remaining = getRunsMax() - current; + setRunsRemaining(remaining); + save(); + return remaining > 0; + } // calculateRuns + + /** + * Calculate next run date + */ + private void setDateNextRun() + { + if (getFrequency() < 1) + setFrequency(1); + int frequency = getFrequency(); + Calendar cal = Calendar.getInstance(); + cal.setTime(getDateNextRun()); + // + if (getFrequencyType().equals(FREQUENCYTYPE_Daily)) + cal.add(Calendar.DAY_OF_YEAR, frequency); + else if (getFrequencyType().equals(FREQUENCYTYPE_Weekly)) + cal.add(Calendar.WEEK_OF_YEAR, frequency); + else if (getFrequencyType().equals(FREQUENCYTYPE_Monthly)) + cal.add(Calendar.MONTH, frequency); + else if (getFrequencyType().equals(FREQUENCYTYPE_Quarterly)) + cal.add(Calendar.MONTH, 3*frequency); + Timestamp next = new Timestamp (cal.getTimeInMillis()); + setDateNextRun(next); + } // setDateNextRun + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + String rt = getRecurringType(); + if (rt == null) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "RecurringType")); + return false; + } + if (rt.equals(MRecurring.RECURRINGTYPE_Order) + && getC_Order_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "C_Order_ID")); + return false; + } + if (rt.equals(MRecurring.RECURRINGTYPE_Invoice) + && getC_Invoice_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "C_Invoice_ID")); + return false; + } + if (rt.equals(MRecurring.RECURRINGTYPE_GLJournal) + && getGL_JournalBatch_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "GL_JournalBatch_ID")); + return false; + } + if (rt.equals(MRecurring.RECURRINGTYPE_Project) + && getC_Project_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "C_Project_ID")); + return false; + } + return true; + } // beforeSave + +} // MRecurring diff --git a/base/src/org/compiere/model/MRecurringRun.java b/base/src/org/compiere/model/MRecurringRun.java new file mode 100644 index 0000000000..75d67a3df3 --- /dev/null +++ b/base/src/org/compiere/model/MRecurringRun.java @@ -0,0 +1,53 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Recurring Run Model + * + * @author Jorg Janke + * @version $Id: MRecurringRun.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MRecurringRun extends X_C_Recurring_Run +{ + + public MRecurringRun (Properties ctx, int C_Recurring_Run_ID, String trxName) + { + super (ctx, C_Recurring_Run_ID, trxName); + } // MRecurringRun + + public MRecurringRun (Properties ctx, MRecurring recurring) + { + super(ctx, 0, recurring.get_TrxName()); + if (recurring != null) + { + setAD_Client_ID(recurring.getAD_Client_ID()); + setAD_Org_ID(recurring.getAD_Org_ID()); + setC_Recurring_ID (recurring.getC_Recurring_ID ()); + setDateDoc(recurring.getDateNextRun()); + } + } // MRecurringRun + + public MRecurringRun (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRecurringRun + +} // MRecurringRun diff --git a/base/src/org/compiere/model/MRefTable.java b/base/src/org/compiere/model/MRefTable.java new file mode 100644 index 0000000000..207ad46eb0 --- /dev/null +++ b/base/src/org/compiere/model/MRefTable.java @@ -0,0 +1,55 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +public class MRefTable extends X_AD_Ref_Table +{ + /** + * Standard Constructor + * @param ctx context + * @param AD_Reference_ID id + * @param trxName trx + */ + public MRefTable (Properties ctx, int AD_Reference_ID, String trxName) + { + super (ctx, AD_Reference_ID, trxName); + if (AD_Reference_ID == 0) + { + // setAD_Table_ID (0); + // setAD_Display (0); + // setAD_Key (0); + setEntityType (ENTITYTYPE_UserMaintained); // U + setIsValueDisplayed (false); + } + } // MRefTable + + /** + * Load Cosntructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MRefTable (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MRefTable + +} // MRefTable diff --git a/base/src/org/compiere/model/MRegistration.java b/base/src/org/compiere/model/MRegistration.java new file mode 100644 index 0000000000..12ad633401 --- /dev/null +++ b/base/src/org/compiere/model/MRegistration.java @@ -0,0 +1,253 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import javax.servlet.http.*; + +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Asset Registration Model + * + * @author Jorg Janke + * @version $Id: MRegistration.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MRegistration extends X_A_Registration +{ + /** + * Standard Constructor + * @param ctx context + * @param A_Registration_ID id + */ + public MRegistration(Properties ctx, int A_Registration_ID, String trxName) + { + super(ctx, A_Registration_ID, trxName); + if (A_Registration_ID == 0) + setIsRegistered (true); + } // MRegistration + + /** + * New Constructor + * @param ctx context + * @param Name name + * @param IsAllowPublish allow publication + * @param IsInProduction production + * @param AssetServiceDate start date + * @param trxName trx + */ + public MRegistration (Properties ctx, String Name, boolean IsAllowPublish, + boolean IsInProduction, Timestamp AssetServiceDate, String trxName) + { + this (ctx, 0, trxName); + setName (Name); + setIsAllowPublish (IsAllowPublish); + setIsInProduction (IsInProduction); + setAssetServiceDate (AssetServiceDate); + } // MRegistration + + + /** + * Load Constructor + * @param ctx context + * @param rs result set + */ + public MRegistration(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRegistration + + /** All Attributes */ + private MRegistrationAttribute[] m_allAttributes = null; + + /** + * Get All Attributes + * @return Registration Attributes + */ + public MRegistrationAttribute[] getAttributes() + { + if (m_allAttributes == null) + m_allAttributes = MRegistrationAttribute.getAll(getCtx()); + return m_allAttributes; + } // getAttributes + + /** + * Get All active Self Service Attribute Values + * @return Registration Attribute Values + */ + public MRegistrationValue[] getValues() + { + return getValues (true); + } // getValues + + /** + * Get All Attribute Values + * @param onlySelfService only Active Self Service + * @return sorted Registration Attribute Values + */ + public MRegistrationValue[] getValues (boolean onlySelfService) + { + createMissingValues(); + // + String sql = "SELECT * FROM A_RegistrationValue rv " + + "WHERE A_Registration_ID=?"; + if (onlySelfService) + sql += " AND EXISTS (SELECT * FROM A_RegistrationAttribute ra WHERE rv.A_RegistrationAttribute_ID=ra.A_RegistrationAttribute_ID" + + " AND ra.IsActive='Y' AND ra.IsSelfService='Y')"; + // sql += " ORDER BY A_RegistrationAttribute_ID"; + + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getA_Registration_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MRegistrationValue(getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // Convert and Sort + MRegistrationValue[] retValue = new MRegistrationValue[list.size()]; + list.toArray(retValue); + Arrays.sort(retValue); + return retValue; + } // getValues + + /** + * Create Missing Attribute Values + */ + private void createMissingValues() + { + String sql = "SELECT ra.A_RegistrationAttribute_ID " + + "FROM A_RegistrationAttribute ra" + + " LEFT OUTER JOIN A_RegistrationProduct rp ON (rp.A_RegistrationAttribute_ID=ra.A_RegistrationAttribute_ID)" + + " LEFT OUTER JOIN A_Registration r ON (r.M_Product_ID=rp.M_Product_ID) " + + "WHERE r.A_Registration_ID=?" + // Not in Registration + + " AND NOT EXISTS (SELECT A_RegistrationAttribute_ID FROM A_RegistrationValue v " + + "WHERE ra.A_RegistrationAttribute_ID=v.A_RegistrationAttribute_ID AND r.A_Registration_ID=v.A_Registration_ID)"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getA_Registration_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + MRegistrationValue v = new MRegistrationValue (this, rs.getInt(1), "?"); + v.save(); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, null, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + } // createMissingValues + + /** + * Load Attributes from Request + * @param request request + * @return number of attributes read + */ + public int loadAttributeValues (HttpServletRequest request) + { + // save if not saved + if (get_ID() == 0) + save(); + int count = 0; + // read values for all attributes + MRegistrationAttribute[] attributes = getAttributes(); + for (int i = 0; i < attributes.length; i++) + { + MRegistrationAttribute attribute = attributes[i]; + String value = WebUtil.getParameter (request, attribute.getName()); + if (value == null) + continue; + MRegistrationValue regValue = new MRegistrationValue (this, + attribute.getA_RegistrationAttribute_ID(), value); + if (regValue.save()) + count++; + } + log.fine("loadAttributeValues - #" + count + " (of " + attributes.length + ")"); + return count; + } // loadAttrubuteValues + + /** + * Update Attributes from Request + * @param request request + * @return number of attributes read + */ + public int updateAttributeValues (HttpServletRequest request) + { + // save if not saved + if (get_ID() == 0) + save(); + int count = 0; + + // Get All Values + MRegistrationValue[] regValues = getValues(false); + for (int i = 0; i < regValues.length; i++) + { + MRegistrationValue regValue = regValues[i]; + String attributeName = regValue.getRegistrationAttribute(); + // + String dataValue = WebUtil.getParameter (request, attributeName); + if (dataValue == null) + continue; + regValue.setDescription("Previous=" + regValue.getName()); + regValue.setName(dataValue); + if (regValue.save()) + count++; + } + log.fine("updateAttributeValues - #" + count + " (of " + regValues.length + ")"); + return count; + } // updateAttrubuteValues + +} // MRegistration diff --git a/base/src/org/compiere/model/MRegistrationAttribute.java b/base/src/org/compiere/model/MRegistrationAttribute.java new file mode 100644 index 0000000000..be659d2d2e --- /dev/null +++ b/base/src/org/compiere/model/MRegistrationAttribute.java @@ -0,0 +1,128 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Asset Registration Attribute + * + * @author Jorg Janke + * @version $Id: MRegistrationAttribute.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MRegistrationAttribute extends X_A_RegistrationAttribute +{ + /** + * Get All Asset Registration Attributes (not cached). + * Refreshes Cache for direct addess + * @param ctx context + * @return array of Registration Attributes + */ + public static MRegistrationAttribute[] getAll (Properties ctx) + { + // Store/Refresh Cache and add to List + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM A_RegistrationAttribute " + + "WHERE AD_Client_ID=? " + + "ORDER BY SeqNo"; + int AD_Client_ID = Env.getAD_Client_ID(ctx); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Client_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + MRegistrationAttribute value = new MRegistrationAttribute(ctx, rs, null); + Integer key = new Integer(value.getA_RegistrationAttribute_ID()); + s_cache.put(key, value); + list.add(value); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + MRegistrationAttribute[] retValue = new MRegistrationAttribute[list.size()]; + list.toArray(retValue); + return retValue; + } // getAll + + /** + * Get Registration Attribute (cached) + * @param ctx context + * @param A_RegistrationAttribute_ID id + * @return Registration Attribute + */ + public static MRegistrationAttribute get (Properties ctx, int A_RegistrationAttribute_ID, String trxName) + { + Integer key = new Integer(A_RegistrationAttribute_ID); + MRegistrationAttribute retValue = (MRegistrationAttribute)s_cache.get(key); + if (retValue == null) + { + retValue = new MRegistrationAttribute (ctx, A_RegistrationAttribute_ID, trxName); + s_cache.put(key, retValue); + } + return retValue; + } // getAll + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger(MRegistrationAttribute.class); + /** Cache */ + private static CCache s_cache + = new CCache("A_RegistrationAttribute", 20); + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param A_RegistrationAttribute_ID id + */ + public MRegistrationAttribute (Properties ctx, int A_RegistrationAttribute_ID, String trxName) + { + super(ctx, A_RegistrationAttribute_ID, trxName); + } // MRegistrationAttribute + + /** + * Load Constructor + * @param ctx context + * @param rs result set + */ + public MRegistrationAttribute (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRegistrationAttribute + +} // MRegistrationAttribute diff --git a/base/src/org/compiere/model/MRegistrationValue.java b/base/src/org/compiere/model/MRegistrationValue.java new file mode 100644 index 0000000000..55ebeb763f --- /dev/null +++ b/base/src/org/compiere/model/MRegistrationValue.java @@ -0,0 +1,143 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.ResultSet; +import java.util.Properties; + +/** + * Asset Registration Attribute Value + * + * @author Jorg Janke + * @version $Id: MRegistrationValue.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MRegistrationValue extends X_A_RegistrationValue + implements Comparable +{ + /** + * Persistency Constructor + * @param ctx context + * @param ignored ignored + */ + public MRegistrationValue (Properties ctx, int ignored, String trxName) + { + super(ctx, 0, trxName); + if (ignored != 0) + throw new IllegalArgumentException("Multi-Key"); + } // MRegistrationValue + + /** + * Load Constructor + * @param ctx context + * @param rs result set + */ + public MRegistrationValue(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRegistrationValue + + /** + * Parent Constructor + * @param registration parent + * @param A_RegistrationAttribute_ID attribute + * @param Name value + */ + public MRegistrationValue (MRegistration registration, + int A_RegistrationAttribute_ID, String Name) + { + super(registration.getCtx(), 0, registration.get_TrxName()); + setClientOrg (registration); + setA_Registration_ID (registration.getA_Registration_ID()); + // + setA_RegistrationAttribute_ID (A_RegistrationAttribute_ID); + setName (Name); + } // MRegistrationValue + + /** Cached Attribute Name */ + private String m_registrationAttribute = null; + /** Cached Attribute Description */ + private String m_registrationAttributeDescription = null; + /** Cached Attribute Sequence */ + private int m_seqNo = -1; + + /** + * Get Registration Attribute + * @return name of registration attribute + */ + public String getRegistrationAttribute() + { + if (m_registrationAttribute == null) + { + int A_RegistrationAttribute_ID = getA_RegistrationAttribute_ID(); + MRegistrationAttribute att = MRegistrationAttribute.get (getCtx(), A_RegistrationAttribute_ID, get_TrxName()); + m_registrationAttribute = att.getName(); + m_registrationAttributeDescription = att.getDescription(); + m_seqNo = att.getSeqNo(); + } + return m_registrationAttribute; + } // getRegistrationAttribute + + /** + * Get Registration Attribute Description + * @return Description of registration attribute + */ + public String getRegistrationAttributeDescription() + { + if (m_registrationAttributeDescription == null) + getRegistrationAttribute(); + return m_registrationAttributeDescription; + } // getRegistrationAttributeDescription + + /** + * Get Attribute SeqNo + * @return seq no + */ + public int getSeqNo() + { + if (m_seqNo == -1) + getRegistrationAttribute(); + return m_seqNo; + } // getSeqNo + + /** + * Compare To + * @param o the Object to be compared. + * @return a negative integer, zero, or a positive integer as this object + * is less than, equal to, or greater than the specified object. + */ + public int compareTo (Object o) + { + if (o == null) + return 0; + MRegistrationValue oo = (MRegistrationValue)o; + int compare = getSeqNo() - oo.getSeqNo(); + return compare; + } // compareTo + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer(); + sb.append(getSeqNo()).append(": ") + .append(getRegistrationAttribute()).append("=").append(getName()); + return sb.toString(); + } // toString + +} // MRegistrationValue diff --git a/base/src/org/compiere/model/MReplication.java b/base/src/org/compiere/model/MReplication.java new file mode 100644 index 0000000000..0ee170fba7 --- /dev/null +++ b/base/src/org/compiere/model/MReplication.java @@ -0,0 +1,49 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.util.*; +import java.sql.*; + +/** + * Replication Model + * + * @author Jorg Janke + * @version $Id: MReplication.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MReplication extends X_AD_Replication +{ + /** + * Load Constructor + * @param ctx context + * @param AD_Replication_ID id + */ + public MReplication (Properties ctx, int AD_Replication_ID, String trxName) + { + super (ctx, AD_Replication_ID, trxName); + } // MReplication + + /** + * Public Access + * @param DateLastRun date last run + */ + public void setDateLastRun (Timestamp DateLastRun) + { + super.setDateLastRun (DateLastRun); + } // setDateLastRun + +} // MReplication diff --git a/base/src/org/compiere/model/MReplicationLog.java b/base/src/org/compiere/model/MReplicationLog.java new file mode 100644 index 0000000000..9dfca15a0d --- /dev/null +++ b/base/src/org/compiere/model/MReplicationLog.java @@ -0,0 +1,46 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.util.*; + +/** + * Replication Log Model + * + * @author Jorg Janke + * @version $Id: MReplicationLog.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MReplicationLog extends X_AD_Replication_Log +{ + + /** + * Create new Log + * @param ctx context + * @param AD_Replication_Run_ID id + * @param AD_ReplicationTable_ID id + * @param P_Msg msg + */ + public MReplicationLog(Properties ctx, int AD_Replication_Run_ID, int AD_ReplicationTable_ID, String P_Msg, String trxName) + { + super(ctx, 0, trxName); + setAD_Replication_Run_ID(AD_Replication_Run_ID); + setAD_ReplicationTable_ID(AD_ReplicationTable_ID); + setIsReplicated(false); + setP_Msg(P_Msg); + } // MReplicationLog + +} // MReplicationLog diff --git a/base/src/org/compiere/model/MReplicationRun.java b/base/src/org/compiere/model/MReplicationRun.java new file mode 100644 index 0000000000..786094e29c --- /dev/null +++ b/base/src/org/compiere/model/MReplicationRun.java @@ -0,0 +1,53 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.util.*; +import java.sql.*; + +/** + * Replication Run Model + * + * @author Jorg Janke + * @version $Id: MReplicationRun.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MReplicationRun extends X_AD_Replication_Run +{ + /** + * Create new Run + * @param ctx context + * @param AD_Replication_ID id + * @param dateRun date + */ + public MReplicationRun (Properties ctx, int AD_Replication_ID, Timestamp dateRun, String trxName) + { + super(ctx, 0, trxName); + setAD_Replication_ID (AD_Replication_ID); + setName (dateRun.toString()); + super.setIsReplicated (false); + } // MReplicationRun + + /** + * Set Replication Flag + * @param IsReplicated replicated + */ + public void setIsReplicated (boolean IsReplicated) + { + super.setIsReplicated(IsReplicated); + } // setIsReplicated + +} // MReplicationRun diff --git a/base/src/org/compiere/model/MRequest.java b/base/src/org/compiere/model/MRequest.java new file mode 100644 index 0000000000..8f9fe88d97 --- /dev/null +++ b/base/src/org/compiere/model/MRequest.java @@ -0,0 +1,1357 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.sql.*; +import java.util.*; + +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Request Model + * + * @author Jorg Janke + * @version $Id: MRequest.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MRequest extends X_R_Request +{ + /** + * Get Request ID from mail text + * @param mailText mail text + * @return ID if it contains request tag otherwise 0 + */ + public static int getR_Request_ID (String mailText) + { + if (mailText == null) + return 0; + int indexStart = mailText.indexOf(TAG_START); + if (indexStart == -1) + return 0; + int indexEnd = mailText.indexOf(TAG_END, indexStart); + if (indexEnd == -1) + return 0; + // + indexStart += 5; + String idString = mailText.substring(indexStart, indexEnd); + int R_Request_ID = 0; + try + { + R_Request_ID = Integer.parseInt(idString); + } + catch (Exception e) + { + s_log.severe ("Cannot parse " + idString); + } + return R_Request_ID; + } // getR_Request_ID + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MRequest.class); + /** Request Tag Start */ + private static final String TAG_START = "[Req#"; + /** Request Tag End */ + private static final String TAG_END = "#ID]"; + + + /************************************************************************** + * Constructor + * @param ctx context + * @param R_Request_ID request or 0 for new + * @param trxName transaction + */ + public MRequest(Properties ctx, int R_Request_ID, String trxName) + { + super (ctx, R_Request_ID, trxName); + if (R_Request_ID == 0) + { + setDueType (DUETYPE_Due); + // setSalesRep_ID (0); + // setDocumentNo (null); + setConfidentialType (CONFIDENTIALTYPE_PublicInformation); // A + setConfidentialTypeEntry (CONFIDENTIALTYPEENTRY_PublicInformation); // A + setProcessed (false); + setRequestAmt (Env.ZERO); + setPriorityUser (PRIORITY_Low); + // setR_RequestType_ID (0); + // setSummary (null); + setIsEscalated (false); + setIsSelfService (false); + setIsInvoiced (false); + } + } // MRequest + + /** + * SelfService Constructor + * @param ctx context + * @param SalesRep_ID SalesRep + * @param R_RequestType_ID request type + * @param Summary summary + * @param isSelfService self service + * @param trxName transaction + */ + public MRequest (Properties ctx, int SalesRep_ID, + int R_RequestType_ID, String Summary, boolean isSelfService, String trxName) + { + this(ctx, 0, trxName); + set_Value ("SalesRep_ID", new Integer(SalesRep_ID)); // could be 0 + set_Value ("R_RequestType_ID", new Integer(R_RequestType_ID)); + setSummary (Summary); + setIsSelfService(isSelfService); + getRequestType(); + if (m_requestType != null) + { + String ct = m_requestType.getConfidentialType(); + if (ct != null) + { + setConfidentialType (ct); + setConfidentialTypeEntry (ct); + } + } + } // MRequest + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MRequest (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRequest + + /** Request Type */ + private MRequestType m_requestType = null; + /** Changed */ + private boolean m_changed = false; + /** BPartner */ + private MBPartner m_partner = null; + /** User/Contact */ + private MUser m_user = null; + /** List of EMail Notices */ + private StringBuffer m_emailTo = new StringBuffer(); + + /** Separator line */ + public static final String SEPARATOR = + "\n---------.----------.----------.----------.----------.----------\n"; + + /************************************************************************** + * Set Default Request Type. + */ + public void setR_RequestType_ID () + { + m_requestType = MRequestType.getDefault(getCtx()); + if (m_requestType == null) + log.warning("No default found"); + else + super.setR_RequestType_ID(m_requestType.getR_RequestType_ID()); + } // setR_RequestType_ID + + /** + * Set Default Request Status. + */ + public void setR_Status_ID () + { + MStatus status = MStatus.getDefault(getCtx(), getR_RequestType_ID()); + if (status == null) + { + log.warning("No default found"); + if (getR_Status_ID() != 0) + setR_Status_ID(0); + } + else + setR_Status_ID(status.getR_Status_ID()); + } // setR_Status_ID + + /** + * Add To Result + * @param Result + */ + public void addToResult (String Result) + { + String oldResult = getResult(); + if (Result == null || Result.length() == 0) + ; + else if (oldResult == null || oldResult.length() == 0) + setResult (Result); + else + setResult (oldResult + "\n-\n" + Result); + } // addToResult + + /** + * Set DueType based on Date Next Action + */ + public void setDueType() + { + Timestamp due = getDateNextAction(); + if (due == null) + return; + // + Timestamp overdue = TimeUtil.addDays(due, getRequestType().getDueDateTolerance()); + Timestamp now = new Timestamp (System.currentTimeMillis()); + // + String DueType = DUETYPE_Due; + if (now.before(due)) + DueType = DUETYPE_Scheduled; + else if (now.after(overdue)) + DueType = DUETYPE_Overdue; + super.setDueType(DueType); + } // setDueType + + + /************************************************************************** + * Get Action History + * @return array of actions + */ + public MRequestAction[] getActions() + { + String sql = "SELECT * FROM R_RequestAction " + + "WHERE R_Request_ID=? " + + "ORDER BY Created DESC"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getR_Request_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MRequestAction(getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + MRequestAction[] retValue = new MRequestAction[list.size()]; + list.toArray(retValue); + return retValue; + } // getActions + + /** + * Get Updates + * @param confidentialType maximum confidential type - null = all + * @return updates + */ + public MRequestUpdate[] getUpdates(String confidentialType) + { + String sql = "SELECT * FROM R_RequestUpdate " + + "WHERE R_Request_ID=? " + + "ORDER BY Created DESC"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getR_Request_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + MRequestUpdate ru = new MRequestUpdate(getCtx(), rs, get_TrxName()); + if (confidentialType != null) + { + // Private only if private + if (ru.getConfidentialTypeEntry().equals(CONFIDENTIALTYPEENTRY_PrivateInformation) + && !confidentialType.equals(CONFIDENTIALTYPEENTRY_PrivateInformation)) + continue; + // Internal not if Customer/Public + if (ru.getConfidentialTypeEntry().equals(CONFIDENTIALTYPEENTRY_Internal) + && (confidentialType.equals(CONFIDENTIALTYPEENTRY_PartnerConfidential) + || confidentialType.equals(CONFIDENTIALTYPEENTRY_PublicInformation))) + continue; + // No Customer if public + if (ru.getConfidentialTypeEntry().equals(CONFIDENTIALTYPEENTRY_PartnerConfidential) + && confidentialType.equals(CONFIDENTIALTYPEENTRY_PublicInformation)) + continue; + } + list.add(ru); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + MRequestUpdate[] retValue = new MRequestUpdate[list.size()]; + list.toArray(retValue); + return retValue; + } // getUpdates + + /** + * Get Public Updates + * @return public updates + */ + public MRequestUpdate[] getUpdatesPublic() + { + return getUpdates(CONFIDENTIALTYPE_PublicInformation); + } // getUpdatesPublic + + /** + * Get Customer Updates + * @return customer updates + */ + public MRequestUpdate[] getUpdatesCustomer() + { + return getUpdates(CONFIDENTIALTYPE_PartnerConfidential); + } // getUpdatesCustomer + + /** + * Get Internal Updates + * @return internal updates + */ + public MRequestUpdate[] getUpdatesInternal() + { + return getUpdates(CONFIDENTIALTYPE_Internal); + } // getUpdatesInternal + + /** + * Get Request Type + * @return Request Type + */ + public MRequestType getRequestType() + { + if (m_requestType == null) + { + int R_RequestType_ID = getR_RequestType_ID(); + if (R_RequestType_ID == 0) + { + setR_RequestType_ID(); + R_RequestType_ID = getR_RequestType_ID(); + } + m_requestType = MRequestType.get (getCtx(), R_RequestType_ID); + } + return m_requestType; + } // getRequestType + + + /** + * Get Request Type Text (for jsp) + * @return Request Type Text + */ + public String getRequestTypeName() + { + if (m_requestType == null) + getRequestType(); + if (m_requestType == null) + return "??"; + return m_requestType.getName(); + } // getRequestTypeText + + /** + * Get Request Category + * @return category + */ + public MRequestCategory getCategory() + { + if (getR_Category_ID() == 0) + return null; + return MRequestCategory.get(getCtx(), getR_Category_ID()); + } // getCategory + + /** + * Get Request Category Name + * @return name + */ + public String getCategoryName() + { + MRequestCategory cat = getCategory(); + if (cat == null) + return ""; + return cat.getName(); + } // getCategoryName + + /** + * Get Request Group + * @return group + */ + public MGroup getGroup() + { + if (getR_Group_ID() == 0) + return null; + return MGroup.get(getCtx(), getR_Group_ID()); + } // getGroup + + /** + * Get Request Group Name + * @return name + */ + public String getGroupName() + { + MGroup grp = getGroup(); + if (grp == null) + return ""; + return grp.getName(); + } // getGroupName + + /** + * Get Status + * @return status + */ + public MStatus getStatus() + { + if (getR_Status_ID() == 0) + return null; + return MStatus.get(getCtx(), getR_Status_ID()); + } // getStatus + + /** + * Get Request Status Name + * @return name + */ + public String getStatusName() + { + MStatus sta = getStatus(); + if (sta == null) + return "?"; + return sta.getName(); + } // getStatusName + + /** + * Get Request Resolution + * @return resolution + */ + public MResolution getResolution() + { + if (getR_Resolution_ID() == 0) + return null; + return MResolution.get(getCtx(), getR_Resolution_ID()); + } // getResolution + + /** + * Get Request Resolution Name + * @return name + */ + public String getResolutionName() + { + MResolution res = getResolution(); + if (res == null) + return ""; + return res.getName(); + } // getResolutionName + + /** + * Is Overdue + * @return true if overdue + */ + public boolean isOverdue() + { + return DUETYPE_Overdue.equals(getDueType()); + } // isOverdue + + /** + * Is due + * @return true if due + */ + public boolean isDue() + { + return DUETYPE_Due.equals(getDueType()); + } // isDue + + /** + * Get DueType Text (for jsp) + * @return text + */ + public String getDueTypeText() + { + return MRefList.getListName(getCtx(), DUETYPE_AD_Reference_ID, getDueType()); + } // getDueTypeText + + /** + * Get Priority Text (for jsp) + * @return text + */ + public String getPriorityText() + { + return MRefList.getListName(getCtx(), PRIORITY_AD_Reference_ID, getPriority()); + } // getPriorityText + + /** + * Get Importance Text (for jsp) + * @return text + */ + public String getPriorityUserText() + { + return MRefList.getListName(getCtx(), PRIORITYUSER_AD_Reference_ID, getPriorityUser()); + } // getPriorityUserText + + /** + * Get Confidential Text (for jsp) + * @return text + */ + public String getConfidentialText() + { + return MRefList.getListName(getCtx(), CONFIDENTIALTYPE_AD_Reference_ID, getConfidentialType()); + } // getConfidentialText + + /** + * Get Confidential Entry Text (for jsp) + * @return text + */ + public String getConfidentialEntryText() + { + return MRefList.getListName(getCtx(), CONFIDENTIALTYPEENTRY_AD_Reference_ID, getConfidentialTypeEntry()); + } // getConfidentialTextEntry + + /** + * Set Date Last Alert to today + */ + public void setDateLastAlert () + { + super.setDateLastAlert (new Timestamp(System.currentTimeMillis())); + } // setDateLastAlert + + /** + * Get Sales Rep + * @return Sales Rep User + */ + public MUser getSalesRep() + { + if (getSalesRep_ID() == 0) + return null; + return MUser.get(getCtx(), getSalesRep_ID()); + } // getSalesRep + + /** + * Get Sales Rep Name + * @return Sales Rep User + */ + public String getSalesRepName() + { + MUser sr = getSalesRep(); + if (sr == null) + return "n/a"; + return sr.getName(); + } // getSalesRepName + + /** + * Get Name of creator + * @return name + */ + public String getCreatedByName() + { + MUser user = MUser.get(getCtx(), getCreatedBy()); + return user.getName(); + } // getCreatedByName + + /** + * Get Contact (may be not defined) + * @return Sales Rep User + */ + public MUser getUser() + { + if (getAD_User_ID() == 0) + return null; + if (m_user != null && m_user.getAD_User_ID() != getAD_User_ID()) + m_user = null; + if (m_user == null) + m_user = new MUser (getCtx(), getAD_User_ID(), get_TrxName()); + return m_user; + } // getUser + + /** + * Get BPartner (may be not defined) + * @return Sales Rep User + */ + public MBPartner getBPartner() + { + if (getC_BPartner_ID() == 0) + return null; + if (m_partner != null && m_partner.getC_BPartner_ID() != getC_BPartner_ID()) + m_partner = null; + if (m_partner == null) + m_partner = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName()); + return m_partner; + } // getBPartner + + /** + * Web Can Update Request + * @return true if Web can update + */ + public boolean isWebCanUpdate() + { + if (isProcessed()) + return false; + if (getR_Status_ID() == 0) + setR_Status_ID(); + if (getR_Status_ID() == 0) + return false; + MStatus status = MStatus.get(getCtx(), getR_Status_ID()); + if (status == null) + return false; + return status.isWebCanUpdate(); + } // isWebCanUpdate + + + /** + * Set Priority + */ + private void setPriority() + { + if (getPriorityUser() == null) + setPriorityUser(PRIORITYUSER_Low); + // + if (getBPartner() != null) + { + MBPGroup bpg = MBPGroup.get(getCtx(), getBPartner().getC_BP_Group_ID()); + String prioBase = bpg.getPriorityBase(); + if (prioBase != null && !prioBase.equals(X_C_BP_Group.PRIORITYBASE_Same)) + { + char targetPrio = getPriorityUser().charAt(0); + if (prioBase.equals(X_C_BP_Group.PRIORITYBASE_Lower)) + targetPrio += 2; + else + targetPrio -= 2; + if (targetPrio < PRIORITY_High.charAt(0)) // 1 + targetPrio = PRIORITY_High.charAt(0); + if (targetPrio > PRIORITY_Low.charAt(0)) // 9 + targetPrio = PRIORITY_Low.charAt(0); + if (getPriority() == null) + setPriority(String.valueOf(targetPrio)); + else // previous priority + { + if (targetPrio < getPriority().charAt(0)) + setPriority(String.valueOf(targetPrio)); + } + } + } + // Same if nothing else + if (getPriority() == null) + setPriority(getPriorityUser()); + } // setPriority + + /** + * Set Confidential Type Entry + * @param ConfidentialTypeEntry confidentiality + */ + public void setConfidentialTypeEntry (String ConfidentialTypeEntry) + { + if (ConfidentialTypeEntry == null) + ConfidentialTypeEntry = getConfidentialType(); + // + if (CONFIDENTIALTYPE_Internal.equals(getConfidentialType())) + super.setConfidentialTypeEntry (CONFIDENTIALTYPE_Internal); + else if (CONFIDENTIALTYPE_PrivateInformation.equals(getConfidentialType())) + { + if (CONFIDENTIALTYPE_Internal.equals(ConfidentialTypeEntry) + || CONFIDENTIALTYPE_PrivateInformation.equals(ConfidentialTypeEntry)) + super.setConfidentialTypeEntry (ConfidentialTypeEntry); + else + super.setConfidentialTypeEntry (CONFIDENTIALTYPE_PrivateInformation); + } + else if (CONFIDENTIALTYPE_PartnerConfidential.equals(getConfidentialType())) + { + if (CONFIDENTIALTYPE_Internal.equals(ConfidentialTypeEntry) + || CONFIDENTIALTYPE_PrivateInformation.equals(ConfidentialTypeEntry) + || CONFIDENTIALTYPE_PartnerConfidential.equals(ConfidentialTypeEntry)) + super.setConfidentialTypeEntry (ConfidentialTypeEntry); + else + super.setConfidentialTypeEntry (CONFIDENTIALTYPE_PartnerConfidential); + } + else if (CONFIDENTIALTYPE_PublicInformation.equals(getConfidentialType())) + super.setConfidentialTypeEntry (ConfidentialTypeEntry); + } // setConfidentialTypeEntry + + /** + * Web Update + * @param result result + * @return true if updated + */ + public boolean webUpdate (String result) + { + MStatus status = MStatus.get(getCtx(), getR_Status_ID()); + if (!status.isWebCanUpdate()) + return false; + if (status.getUpdate_Status_ID() > 0) + setR_Status_ID(status.getUpdate_Status_ID()); + setResult(result); + return true; + } // webUpdate + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MRequest["); + sb.append (get_ID()).append ("-").append(getDocumentNo()).append ("]"); + return sb.toString (); + } // toString + + /** + * Create PDF + * @return pdf or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + // ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.INVOICE, getC_Invoice_ID()); + // if (re == null) + return null; + // return re.getPDF(file); + } // createPDF + + /************************************************************************** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Request Type + getRequestType(); + if (newRecord || is_ValueChanged("R_RequestType_ID")) + { + if (m_requestType != null) + { + if (isInvoiced() != m_requestType.isInvoiced()) + setIsInvoiced(m_requestType.isInvoiced()); + if (getDateNextAction() == null && m_requestType.getAutoDueDateDays() > 0) + setDateNextAction(TimeUtil.addDays(new Timestamp(System.currentTimeMillis()), + m_requestType.getAutoDueDateDays())); + } + // Is Status Valid + if (getR_Status_ID() != 0) + { + MStatus sta = MStatus.get(getCtx(), getR_Status_ID()); + MRequestType rt = MRequestType.get(getCtx(), getR_RequestType_ID()); + if (sta.getR_StatusCategory_ID() != rt.getR_StatusCategory_ID()) + setR_Status_ID(); // set to default + } + } + + // Request Status + if (getR_Status_ID() == 0) + setR_Status_ID(); + // Validate/Update Due Type + setDueType(); + MStatus status = MStatus.get(getCtx(), getR_Status_ID()); + // Close/Open + if (status != null) + { + if (status.isOpen()) + { + if (getStartDate() == null) + setStartDate (new Timestamp(System.currentTimeMillis())); + if (getCloseDate() != null) + setCloseDate(null); + } + if (status.isClosed() + && getCloseDate() == null) + setCloseDate(new Timestamp(System.currentTimeMillis())); + if (status.isFinalClose()) + setProcessed(true); + } + + // Confidential Info + if (getConfidentialType() == null) + { + getRequestType(); + if (m_requestType != null) + { + String ct = m_requestType.getConfidentialType(); + if (ct != null) + setConfidentialType (ct); + } + if (getConfidentialType() == null) + setConfidentialType(CONFIDENTIALTYPEENTRY_PublicInformation); + } + if (getConfidentialTypeEntry() == null) + setConfidentialTypeEntry(getConfidentialType()); + else + setConfidentialTypeEntry(getConfidentialTypeEntry()); + + // Importance / Priority + setPriority(); + + // New + if (newRecord) + return true; + + // Change Log + m_changed = false; + ArrayList sendInfo = new ArrayList(); + MRequestAction ra = new MRequestAction(this, false); + // + if (checkChange(ra, "R_RequestType_ID")) + sendInfo.add("R_RequestType_ID"); + if (checkChange(ra, "R_Group_ID")) + sendInfo.add("R_Group_ID"); + if (checkChange(ra, "R_Category_ID")) + sendInfo.add("R_Category_ID"); + if (checkChange(ra, "R_Status_ID")) + sendInfo.add("R_Status_ID"); + if (checkChange(ra, "R_Resolution_ID")) + sendInfo.add("R_Resolution_ID"); + // + if (checkChange(ra, "SalesRep_ID")) + { + // Sender + int AD_User_ID = Env.getContextAsInt(p_ctx, "#AD_User_ID"); + if (AD_User_ID == 0) + AD_User_ID = getUpdatedBy(); + // Old + Object oo = get_ValueOld("SalesRep_ID"); + int oldSalesRep_ID = 0; + if (oo instanceof Integer) + oldSalesRep_ID = ((Integer)oo).intValue(); + if (oldSalesRep_ID != 0) + { + // RequestActionTransfer - Request {0} was transfered by {1} from {2} to {3} + Object[] args = new Object[] {getDocumentNo(), + MUser.getNameOfUser(AD_User_ID), + MUser.getNameOfUser(oldSalesRep_ID), + MUser.getNameOfUser(getSalesRep_ID()) + }; + String msg = Msg.getMsg(getCtx(), "RequestActionTransfer", args); + addToResult(msg); + sendInfo.add("SalesRep_ID"); + } + } + checkChange(ra, "AD_Role_ID"); + // + checkChange(ra, "Priority"); + if (checkChange(ra, "PriorityUser")) + sendInfo.add("PriorityUser"); + if (checkChange(ra, "IsEscalated")) + sendInfo.add("IsEscalated"); + // + checkChange(ra, "ConfidentialType"); + checkChange(ra, "Summary"); + checkChange(ra, "IsSelfService"); + checkChange(ra, "C_BPartner_ID"); + checkChange(ra, "AD_User_ID"); + checkChange(ra, "C_Project_ID"); + checkChange(ra, "A_Asset_ID"); + checkChange(ra, "C_Order_ID"); + checkChange(ra, "C_Invoice_ID"); + checkChange(ra, "M_Product_ID"); + checkChange(ra, "C_Payment_ID"); + checkChange(ra, "M_InOut_ID"); + checkChange(ra, "M_RMA_ID"); + // checkChange(ra, "C_Campaign_ID"); + // checkChange(ra, "RequestAmt"); + checkChange(ra, "IsInvoiced"); + checkChange(ra, "C_Activity_ID"); + checkChange(ra, "DateNextAction"); + checkChange(ra, "M_ProductSpent_ID"); + checkChange(ra, "QtySpent"); + checkChange(ra, "QtyInvoiced"); + checkChange(ra, "StartDate"); + checkChange(ra, "CloseDate"); + checkChange(ra, "TaskStatus"); + checkChange(ra, "DateStartPlan"); + checkChange(ra, "DateCompletePlan"); + // + if (m_changed) + ra.save(); + + // Current Info + MRequestUpdate update = new MRequestUpdate(this); + if (update.isNewInfo()) + update.save(); + else + update = null; + // + m_emailTo = new StringBuffer(); + if (update != null || sendInfo.size() > 0) + { + sendNotices(sendInfo); + + // Update + setDateLastAction(getUpdated()); + setLastResult(getResult()); + setDueType(); + // Reset + setConfidentialTypeEntry (getConfidentialType()); + setStartDate(null); + setEndTime(null); + setR_StandardResponse_ID(0); + setR_MailText_ID(0); + setResult(null); + // setQtySpent(null); + // setQtyInvoiced(null); + } + return true; + } // beforeSave + + /** + * Check for changes + * @param ra request action + * @param columnName column + * @return true if changes + */ + private boolean checkChange (MRequestAction ra, String columnName) + { + if (is_ValueChanged(columnName)) + { + Object value = get_ValueOld(columnName); + if (value == null) + ra.addNullColumn(columnName); + else + ra.set_ValueNoCheck(columnName, value); + m_changed = true; + return true; + } + return false; + } // checkChange + + /** + * Check the ability to send email. + * @return AD_Message or null if no error + */ + private String checkEMail() + { + // Mail Host + MClient client = MClient.get(getCtx()); + if (client == null + || client.getSMTPHost() == null + || client.getSMTPHost().length() == 0) + return "RequestActionEMailNoSMTP"; + + // Mail To + MUser to = new MUser (getCtx(), getAD_User_ID(), get_TrxName()); + if (to == null + || to.getEMail() == null + || to.getEMail().length() == 0) + return "RequestActionEMailNoTo"; + + // Mail From real user + MUser from = MUser.get(getCtx(), Env.getAD_User_ID(getCtx())); + if (from == null + || from.getEMail() == null + || from.getEMail().length() == 0) + return "RequestActionEMailNoFrom"; + + // Check that UI user is Request User +// int realSalesRep_ID = Env.getContextAsInt (getCtx(), "#AD_User_ID"); +// if (realSalesRep_ID != getSalesRep_ID()) +// setSalesRep_ID(realSalesRep_ID); + + // RequestActionEMailInfo - EMail from {0} to {1} +// Object[] args = new Object[] {emailFrom, emailTo}; +// String msg = Msg.getMsg(getCtx(), "RequestActionEMailInfo", args); +// setLastResult(msg); + // + + return null; + } // checkEMail + + /** + * Set SalesRep_ID + * @param SalesRep_ID id + */ + public void setSalesRep_ID (int SalesRep_ID) + { + if (SalesRep_ID != 0) + super.setSalesRep_ID (SalesRep_ID); + else if (getSalesRep_ID() != 0) + log.warning("Ignored - Tried to set SalesRep_ID to 0 from " + getSalesRep_ID()); + } // setSalesRep_ID + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + + // Create Update + if (newRecord && getResult() != null) + { + MRequestUpdate update = new MRequestUpdate(this); + update.save(); + } + // Initial Mail + if (newRecord) + sendNotices(new ArrayList()); + + // ChangeRequest - created in Request Processor + if (getM_ChangeRequest_ID() != 0 + && is_ValueChanged("R_Group_ID")) // different ECN assignment? + { + int oldID = get_ValueOldAsInt("R_Group_ID"); + if (getR_Group_ID() == 0) + setM_ChangeRequest_ID(0); // not effective as in afterSave + else + { + MGroup oldG = MGroup.get(getCtx(), oldID); + MGroup newG = MGroup.get(getCtx(), getR_Group_ID()); + if (oldG.getM_BOM_ID() != newG.getM_BOM_ID() + || oldG.getM_ChangeNotice_ID() != newG.getM_ChangeNotice_ID()) + { + MChangeRequest ecr = new MChangeRequest(getCtx(), getM_ChangeRequest_ID(), get_TrxName()); + if (!ecr.isProcessed() + || ecr.getM_FixChangeNotice_ID() == 0) + { + ecr.setM_BOM_ID(newG.getM_BOM_ID()); + ecr.setM_ChangeNotice_ID(newG.getM_ChangeNotice_ID()); + ecr.save(); + } + } + } + } + + if (m_emailTo.length() > 0) + log.saveInfo ("RequestActionEMailOK", m_emailTo.toString()); + + return success; + } // afterSave + + /** + * Send transfer Message + */ + private void sendTransferMessage () + { + // Sender + int AD_User_ID = Env.getContextAsInt(p_ctx, "#AD_User_ID"); + if (AD_User_ID == 0) + AD_User_ID = getUpdatedBy(); + // Old + Object oo = get_ValueOld("SalesRep_ID"); + int oldSalesRep_ID = 0; + if (oo instanceof Integer) + oldSalesRep_ID = ((Integer)oo).intValue(); + + // RequestActionTransfer - Request {0} was transfered by {1} from {2} to {3} + Object[] args = new Object[] {getDocumentNo(), + MUser.getNameOfUser(AD_User_ID), + MUser.getNameOfUser(oldSalesRep_ID), + MUser.getNameOfUser(getSalesRep_ID()) + }; + String subject = Msg.getMsg(getCtx(), "RequestActionTransfer", args); + String message = subject + "\n" + getSummary(); + MClient client = MClient.get(getCtx()); + MUser from = MUser.get (getCtx(), AD_User_ID); + MUser to = MUser.get (getCtx(), getSalesRep_ID()); + // + client.sendEMail(from, to, subject, message, createPDF()); + } // afterSaveTransfer + + + /** + * Send Update EMail/Notices + * @param list list of changes + */ + public void sendNotices(ArrayList list) + { + // Subject + String subject = Msg.translate(getCtx(), "R_Request_ID") + + " " + Msg.getMsg(getCtx(), "Updated") + ": " + getDocumentNo(); + // Message + StringBuffer message = new StringBuffer(); + // UpdatedBy: Joe + int UpdatedBy = Env.getAD_User_ID(getCtx()); + MUser from = MUser.get(getCtx(), UpdatedBy); + if (from != null) + message.append(Msg.translate(getCtx(), "UpdatedBy")).append(": ") + .append(from.getName()); + // LastAction/Created: ... + if (getDateLastAction() != null) + message.append("\n").append(Msg.translate(getCtx(), "DateLastAction")) + .append(": ").append(getDateLastAction()); + else + message.append("\n").append(Msg.translate(getCtx(), "Created")) + .append(": ").append(getCreated()); + // Changes + for (int i = 0; i < list.size(); i++) + { + String columnName = (String)list.get(i); + message.append("\n").append(Msg.getElement(getCtx(), columnName)) + .append(": ").append(get_DisplayValue(columnName, false)) + .append(" -> ").append(get_DisplayValue(columnName, true)); + } + // NextAction + if (getDateNextAction() != null) + message.append("\n").append(Msg.translate(getCtx(), "DateNextAction")) + .append(": ").append(getDateNextAction()); + message.append(SEPARATOR) + .append(getSummary()); + if (getResult() != null) + message.append("\n----------\n").append(getResult()); + message.append(getMailTrailer(null)); + File pdf = createPDF(); + log.finer(message.toString()); + + // Prepare sending Notice/Mail + MClient client = MClient.get(getCtx()); + // Reset from if external + if (from.getEMailUser() == null || from.getEMailUserPW() == null) + from = null; + int success = 0; + int failure = 0; + int notices = 0; + // + ArrayList userList = new ArrayList(); + String sql = "SELECT u.AD_User_ID, u.NotificationType, u.EMail, u.Name, MAX(r.AD_Role_ID) " + + "FROM RV_RequestUpdates_Only ru" + + " INNER JOIN AD_User u ON (ru.AD_User_ID=u.AD_User_ID)" + + " LEFT OUTER JOIN AD_User_Roles r ON (u.AD_User_ID=r.AD_User_ID) " + + "WHERE ru.R_Request_ID=? " + + "GROUP BY u.AD_User_ID, u.NotificationType, u.EMail, u.Name"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getR_Request_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + int AD_User_ID = rs.getInt(1); + String NotificationType = rs.getString(2); + if (NotificationType == null) + NotificationType = X_AD_User.NOTIFICATIONTYPE_EMail; + String email = rs.getString(3); + String Name = rs.getString(4); + // Role + int AD_Role_ID = rs.getInt(5); + if (rs.wasNull()) + AD_Role_ID = -1; + + // Don't send mail to oneself + // if (AD_User_ID == UpdatedBy) + // continue; + + // No confidential to externals + if (AD_Role_ID == -1 + && (getConfidentialTypeEntry().equals(CONFIDENTIALTYPE_Internal) + || getConfidentialTypeEntry().equals(CONFIDENTIALTYPE_PrivateInformation))) + continue; + + if (X_AD_User.NOTIFICATIONTYPE_None.equals(NotificationType)) + { + log.config("Opt out: " + Name); + continue; + } + if ((X_AD_User.NOTIFICATIONTYPE_EMail.equals(NotificationType) + || X_AD_User.NOTIFICATIONTYPE_EMailPlusNotice.equals(NotificationType)) + && (email == null || email.length() == 0)) + { + if (AD_Role_ID >= 0) + NotificationType = X_AD_User.NOTIFICATIONTYPE_Notice; + else + { + log.config("No EMail: " + Name); + continue; + } + } + if (X_AD_User.NOTIFICATIONTYPE_Notice.equals(NotificationType) + && AD_Role_ID >= 0) + { + log.config("No internal User: " + Name); + continue; + } + + // Check duplicate receivers + Integer ii = new Integer (AD_User_ID); + if (userList.contains(ii)) + continue; + userList.add(ii); + // + MUser to = MUser.get (getCtx(), AD_User_ID); + // Send Mail + if (X_AD_User.NOTIFICATIONTYPE_EMail.equals(NotificationType) + || X_AD_User.NOTIFICATIONTYPE_EMailPlusNotice.equals(NotificationType)) + { + if (client.sendEMail(from, to, subject, message.toString(), pdf)) + { + success++; + if (m_emailTo.length() > 0) + m_emailTo.append(", "); + m_emailTo.append(to.getEMail()); + } + else + { + log.warning("Failed: " + Name); + failure++; + NotificationType = X_AD_User.NOTIFICATIONTYPE_Notice; + } + } + // Send Note + if (X_AD_User.NOTIFICATIONTYPE_Notice.equals(NotificationType) + || X_AD_User.NOTIFICATIONTYPE_EMailPlusNotice.equals(NotificationType)) + { + int AD_Message_ID = 834; + MNote note = new MNote(getCtx(), AD_Message_ID, AD_User_ID, + X_R_Request.Table_ID, getR_Request_ID(), + subject, message.toString(), get_TrxName()); + if (note.save()) + notices++; + } + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + log.info("EMail Success=" + success + ", Failure=" + failure + + " - Notices=" + notices); + } // sendNotice + + /************************************************************************** + * Get MailID + * @param serverAddress server address + * @return Mail Trailer + */ + public String getMailTrailer(String serverAddress) + { + StringBuffer sb = new StringBuffer("\n").append(SEPARATOR) + .append(Msg.translate(getCtx(), "R_Request_ID")) + .append(": ").append(getDocumentNo()) + .append(" ").append(getMailTag()) + .append("\nSent by AdempiereMail"); + if (serverAddress != null) + sb.append(" from ").append(serverAddress); + return sb.toString(); + } // getMailTrailer + + /** + * Get Mail Tag + * @return [Req@{id}@] + */ + public String getMailTag() + { + return TAG_START + get_ID() + TAG_END; + } // getMailTag + + /** + * (Soft) Close request. + * Must be called after webUpdate + */ + public void doClose() + { + MStatus status = MStatus.get(getCtx(), getR_Status_ID()); + if (!status.isClosed()) + { + MStatus[] closed = MStatus.getClosed(getCtx()); + MStatus newStatus = null; + for (int i = 0; i < closed.length; i++) + { + if (!closed[i].isFinalClose()) + { + newStatus = closed[i]; + break; + } + } + if (newStatus == null && closed.length > 0) + newStatus = closed[0]; + if (newStatus != null) + setR_Status_ID(newStatus.getR_Status_ID()); + } + } // doClose + + /** + * Escalate request + * @param user true if user escalated - otherwise system + */ + public void doEscalate(boolean user) + { + if (user) + { + String Importance = getPriorityUser(); + if (PRIORITYUSER_Urgent.equals(Importance)) + ; // high as it goes + else if (PRIORITYUSER_High.equals(Importance)) + setPriorityUser(PRIORITYUSER_Urgent); + else if (PRIORITYUSER_Medium.equals(Importance)) + setPriorityUser(PRIORITYUSER_High); + else if (PRIORITYUSER_Low.equals(Importance)) + setPriorityUser(PRIORITYUSER_Medium); + else if (PRIORITYUSER_Minor.equals(Importance)) + setPriorityUser(PRIORITYUSER_Low); + } + else + { + String Importance = getPriority(); + if (PRIORITY_Urgent.equals(Importance)) + ; // high as it goes + else if (PRIORITY_High.equals(Importance)) + setPriority(PRIORITY_Urgent); + else if (PRIORITY_Medium.equals(Importance)) + setPriority(PRIORITY_High); + else if (PRIORITY_Low.equals(Importance)) + setPriority(PRIORITY_Medium); + else if (PRIORITY_Minor.equals(Importance)) + setPriority(PRIORITY_Low); + } + } // doEscalate + +} // MRequest diff --git a/base/src/org/compiere/model/MRequestAction.java b/base/src/org/compiere/model/MRequestAction.java new file mode 100644 index 0000000000..6f231d0950 --- /dev/null +++ b/base/src/org/compiere/model/MRequestAction.java @@ -0,0 +1,178 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.ResultSet; +import java.util.Properties; + +import org.compiere.util.*; + +/** + * Request History Model + * + * @author Jorg Janke + * @version $Id: MRequestAction.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MRequestAction extends X_R_RequestAction +{ + /** + * Persistency Constructor + * @param ctx context + * @param R_RequestAction_ID id + */ + public MRequestAction (Properties ctx, int R_RequestAction_ID, String trxName) + { + super (ctx, R_RequestAction_ID, trxName); + } // MRequestAction + + /** + * Load Construtor + * @param ctx context + * @param rs result set + */ + public MRequestAction(Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MRequestAction + + /** + * Parent Action Constructor + * @param request parent + * @param newRecord new (copy all) + */ + public MRequestAction (MRequest request, boolean newRecord) + { + this (request.getCtx(), 0, request.get_TrxName()); + setClientOrg(request); + setR_Request_ID (request.getR_Request_ID()); + } // MRequestAction + + /** + * Add Null Column + * @param columnName + */ + public void addNullColumn (String columnName) + { + String nc = getNullColumns(); + if (nc == null) + setNullColumns(columnName); + else + setNullColumns(nc + ";" + columnName); + } // addNullColumn + + + /** + * Get Name of creator + * @return name + */ + public String getCreatedByName() + { + MUser user = MUser.get(getCtx(), getCreatedBy()); + return user.getName(); + } // getCreatedByName + + /** + * Get Changes as HTML string + * @return changes + */ + public String getChangesHTML() + { + StringBuffer sb = new StringBuffer(); + getChangeHTML(sb, "Priority"); + getChangeHTML(sb, "PriorityUser"); + getChangeHTML(sb, "R_Category_ID"); + getChangeHTML(sb, "R_Group_ID"); + getChangeHTML(sb, "R_RequestType_ID"); + getChangeHTML(sb, "R_Resolution_ID"); + getChangeHTML(sb, "R_Status_ID"); + getChangeHTML(sb, "SalesRep_ID"); + getChangeHTML(sb, "Summary"); + // + // getChangeHTML(sb, "AD_Org_ID"); // always stored + getChangeHTML(sb, "AD_Role_ID"); + getChangeHTML(sb, "AD_User_ID"); + getChangeHTML(sb, "C_Activity_ID"); + getChangeHTML(sb, "C_BPartner_ID"); + getChangeHTML(sb, "C_Invoice_ID"); + getChangeHTML(sb, "C_Order_ID"); + getChangeHTML(sb, "C_Payment_ID"); + getChangeHTML(sb, "C_Project_ID"); + getChangeHTML(sb, "DateNextAction"); + getChangeHTML(sb, "IsEscalated"); + getChangeHTML(sb, "IsInvoiced"); + getChangeHTML(sb, "IsSelfService"); + getChangeHTML(sb, "M_InOut_ID"); + getChangeHTML(sb, "M_Product_ID"); + getChangeHTML(sb, "M_RMA_ID"); + getChangeHTML(sb, "A_Asset_ID"); + + if (sb.length() == 0) + sb.append("./."); + // Unicode check + char[] chars = sb.toString().toCharArray(); + sb = new StringBuffer(chars.length); + for (int i = 0; i < chars.length; i++) + { + char c = chars[i]; + int ii = (int)c; + if (ii > 255) + sb.append("&#").append(ii).append(";"); + else + sb.append(c); + } + return sb.toString(); + } // getChangesHTML + + /** + * Get individual Change HTML + * @param sb string to append to + * @param columnName column name + */ + private void getChangeHTML (StringBuffer sb, String columnName) + { + if (get_Value(columnName) != null) + { + if (sb.length() > 0) + sb.append("
"); + sb.append(Msg.getElement(getCtx(), columnName)) + .append(": ").append(get_DisplayValue(columnName, true)); + } + else + { + String nc = getNullColumns(); + if (nc != null && nc.indexOf(columnName) != -1) + { + if (sb.length() > 0) + sb.append("
"); + sb.append("(") + .append(Msg.getElement(getCtx(), columnName)) + .append(")"); + } + } + } // getChangeHTML + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + return true; + } // beforeSave +} // MRequestAction diff --git a/base/src/org/compiere/model/MRequestCategory.java b/base/src/org/compiere/model/MRequestCategory.java new file mode 100644 index 0000000000..8552c43128 --- /dev/null +++ b/base/src/org/compiere/model/MRequestCategory.java @@ -0,0 +1,76 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import org.compiere.util.*; + +/** + * Request Category Model + * @author Jorg Janke + * @version $Id: MRequestCategory.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MRequestCategory extends X_R_Category +{ + /** + * Get MCategory from Cache + * @param ctx context + * @param R_Category_ID id + * @return MCategory + */ + public static MRequestCategory get (Properties ctx, int R_Category_ID) + { + Integer key = new Integer (R_Category_ID); + MRequestCategory retValue = (MRequestCategory) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MRequestCategory (ctx, R_Category_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache + = new CCache("R_Category", 20); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param R_Category_ID id + * @param trxName trx + */ + public MRequestCategory (Properties ctx, int R_Category_ID, String trxName) + { + super (ctx, R_Category_ID, trxName); + } // MCategory + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MRequestCategory (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MCategory + +} // MCategory diff --git a/base/src/org/compiere/model/MRequestProcessor.java b/base/src/org/compiere/model/MRequestProcessor.java new file mode 100644 index 0000000000..d334169a4c --- /dev/null +++ b/base/src/org/compiere/model/MRequestProcessor.java @@ -0,0 +1,247 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Request Processor Model + * + * @author Jorg Janke + * @version $Id: MRequestProcessor.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MRequestProcessor extends X_R_RequestProcessor + implements AdempiereProcessor +{ + /** + * Get Active Request Processors + * @param ctx context + * @return array of Request + */ + public static MRequestProcessor[] getActive (Properties ctx) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM R_RequestProcessor WHERE IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MRequestProcessor (ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MRequestProcessor[] retValue = new MRequestProcessor[list.size ()]; + list.toArray (retValue); + return retValue; + } // getActive + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MRequestProcessor.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param R_RequestProcessor_ID id + */ + public MRequestProcessor (Properties ctx, int R_RequestProcessor_ID, String trxName) + { + super (ctx, R_RequestProcessor_ID, trxName); + if (R_RequestProcessor_ID == 0) + { + // setName (null); + setFrequencyType (FREQUENCYTYPE_Day); + setFrequency (0); + setKeepLogDays (7); + setOverdueAlertDays (0); + setOverdueAssignDays (0); + setRemindDays (0); + // setSupervisor_ID (0); + } + } // MRequestProcessor + + /** + * Load Constructor + * @param ctx context + * @param rs result set + */ + public MRequestProcessor (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRequestProcessor + + /** + * Parent Constructor + * @param parent parent + * @param Supervisor_ID Supervisor + */ + public MRequestProcessor (MClient parent, int Supervisor_ID) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setName (parent.getName() + " - " + + Msg.translate(getCtx(), "R_RequestProcessor_ID")); + setSupervisor_ID (Supervisor_ID); + } // MRequestProcessor + + + /** The Lines */ + private MRequestProcessorRoute[] m_routes = null; + + /** + * Get Routes + * @param reload reload data + * @return array of routes + */ + public MRequestProcessorRoute[] getRoutes (boolean reload) + { + if (m_routes != null && !reload) + return m_routes; + + String sql = "SELECT * FROM R_RequestProcessor_Route WHERE R_RequestProcessor_ID=? ORDER BY SeqNo"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getR_RequestProcessor_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MRequestProcessorRoute (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + m_routes = new MRequestProcessorRoute[list.size ()]; + list.toArray (m_routes); + return m_routes; + } // getRoutes + + /** + * Get Logs + * @return Array of Logs + */ + public AdempiereProcessorLog[] getLogs() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * " + + "FROM R_RequestProcessorLog " + + "WHERE R_RequestProcessor_ID=? " + + "ORDER BY Created DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getR_RequestProcessor_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MRequestProcessorLog (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MRequestProcessorLog[] retValue = new MRequestProcessorLog[list.size ()]; + list.toArray (retValue); + return retValue; + } // getLogs + + /** + * Delete old Request Log + * @return number of records + */ + public int deleteLog() + { + if (getKeepLogDays() < 1) + return 0; + String sql = "DELETE R_RequestProcessorLog " + + "WHERE R_RequestProcessor_ID=" + getR_RequestProcessor_ID() + + " AND (Created+" + getKeepLogDays() + ") < SysDate"; + int no = DB.executeUpdate(sql, get_TrxName()); + return 0; + } // deleteLog + + /** + * Get the date Next run + * @param requery requery database + * @return date next run + */ + public Timestamp getDateNextRun (boolean requery) + { + if (requery) + load(get_TrxName()); + return getDateNextRun(); + } // getDateNextRun + + /** + * Get Unique ID + * @return Unique ID + */ + public String getServerID() + { + return "RequestProcessor" + get_ID(); + } // getServerID + +} // MRequestProcessor diff --git a/base/src/org/compiere/model/MRequestProcessorLog.java b/base/src/org/compiere/model/MRequestProcessorLog.java new file mode 100644 index 0000000000..cc6f267da0 --- /dev/null +++ b/base/src/org/compiere/model/MRequestProcessorLog.java @@ -0,0 +1,70 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Request Processor Log + * + * @author Jorg Janke + * @version $Id: MRequestProcessorLog.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MRequestProcessorLog extends X_R_RequestProcessorLog + implements AdempiereProcessorLog +{ + /** + * Standard Constructor + * @param ctx context + * @param R_RequestProcessorLog_ID id + */ + public MRequestProcessorLog (Properties ctx, int R_RequestProcessorLog_ID, String trxName) + { + super (ctx, R_RequestProcessorLog_ID, trxName); + if (R_RequestProcessorLog_ID == 0) + { + setIsError (false); + } + } // MRequestProcessorLog + + /** + * Load Constructor + * @param ctx context + * @param rs result set + */ + public MRequestProcessorLog (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRequestProcessorLog + + /** + * Parent Constructor + * @param parent parent + * @param summary summary + */ + public MRequestProcessorLog (MRequestProcessor parent, String summary) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setR_RequestProcessor_ID(parent.getR_RequestProcessor_ID()); + setSummary(summary); + } // MRequestProcessorLog + + +} // MRequestProcessorLog diff --git a/base/src/org/compiere/model/MRequestProcessorRoute.java b/base/src/org/compiere/model/MRequestProcessorRoute.java new file mode 100644 index 0000000000..a9f52f19de --- /dev/null +++ b/base/src/org/compiere/model/MRequestProcessorRoute.java @@ -0,0 +1,51 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Request Processor Route + * + * @author Jorg Janke + * @version $Id: MRequestProcessorRoute.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MRequestProcessorRoute extends X_R_RequestProcessor_Route +{ + /** + * Standard Constructor + * @param ctx context + * @param R_RequestProcessor_Route_ID id + */ + public MRequestProcessorRoute (Properties ctx, int R_RequestProcessor_Route_ID, String trxName) + { + super (ctx, R_RequestProcessor_Route_ID, trxName); + } // MRequestProcessorRoute + + /** + * Load Constructor + * @param ctx context + * @param rs result set + */ + public MRequestProcessorRoute (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRequestProcessorRoute + +} // MRequestProcessorRoute diff --git a/base/src/org/compiere/model/MRequestType.java b/base/src/org/compiere/model/MRequestType.java new file mode 100644 index 0000000000..9475acfd8d --- /dev/null +++ b/base/src/org/compiere/model/MRequestType.java @@ -0,0 +1,518 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Request Type Model + * + * @author Jorg Janke + * @version $Id: MRequestType.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MRequestType extends X_R_RequestType +{ + /** + * Get Request Type (cached) + * @param ctx context + * @param R_RequestType_ID id + * @return Request Type + */ + public static MRequestType get (Properties ctx, int R_RequestType_ID) + { + Integer key = new Integer (R_RequestType_ID); + MRequestType retValue = (MRequestType)s_cache.get(key); + if (retValue == null) + { + retValue = new MRequestType (ctx, R_RequestType_ID, null); + s_cache.put(key, retValue); + } + return retValue; + } // get + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger(MRequestType.class); + /** Cache */ + static private CCache s_cache = new CCache("R_RequestType", 10); + + /** + * Get Default Request Type + * @param ctx context + * @return Request Type + */ + public static MRequestType getDefault (Properties ctx) + { + MRequestType retValue = null; + int AD_Client_ID = Env.getAD_Client_ID(ctx); + String sql = "SELECT * FROM R_RequestType " + + "WHERE AD_Client_ID IN (0,11) " + + "ORDER BY IsDefault DESC, AD_Client_ID DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + retValue = new MRequestType (ctx, rs, null); + if (!retValue.isDefault()) + retValue = null; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (SQLException ex) + { + s_log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + return retValue; + } // get + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param R_RequestType_ID id + * @param trxName transaction + */ + public MRequestType (Properties ctx, int R_RequestType_ID, String trxName) + { + super(ctx, R_RequestType_ID, trxName); + if (R_RequestType_ID == 0) + { + // setR_RequestType_ID (0); + // setName (null); + setDueDateTolerance (7); + setIsDefault (false); + setIsEMailWhenDue (false); + setIsEMailWhenOverdue (false); + setIsSelfService (true); // Y + setAutoDueDateDays(0); + setConfidentialType(CONFIDENTIALTYPE_PublicInformation); + setIsAutoChangeRequest(false); + setIsConfidentialInfo(false); + setIsIndexed(true); + setIsInvoiced(false); + } + } // MRequestType + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MRequestType(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRequestType + + /** Next time stats to be created */ + private long m_nextStats = 0; + + private int m_openNo = 0; + private int m_totalNo = 0; + private int m_new30No = 0; + private int m_closed30No = 0; + + /** + * Update Statistics + */ + private synchronized void updateStatistics() + { + if (System.currentTimeMillis() < m_nextStats) + return; + + String sql = "SELECT " + + "(SELECT COUNT(*) FROM R_Request r" + + " INNER JOIN R_Status s ON (r.R_Status_ID=s.R_Status_ID AND s.IsOpen='Y') " + + "WHERE r.R_RequestType_ID=x.R_RequestType_ID) AS OpenNo, " + + "(SELECT COUNT(*) FROM R_Request r " + + "WHERE r.R_RequestType_ID=x.R_RequestType_ID) AS TotalNo, " + + "(SELECT COUNT(*) FROM R_Request r " + + "WHERE r.R_RequestType_ID=x.R_RequestType_ID AND Created>SysDate-30) AS New30No, " + + "(SELECT COUNT(*) FROM R_Request r" + + " INNER JOIN R_Status s ON (r.R_Status_ID=s.R_Status_ID AND s.IsClosed='Y') " + + "WHERE r.R_RequestType_ID=x.R_RequestType_ID AND r.Updated>SysDate-30) AS Closed30No " + // + + "FROM R_RequestType x WHERE R_RequestType_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getR_RequestType_ID()); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + m_openNo = rs.getInt(1); + m_totalNo = rs.getInt(2); + m_new30No = rs.getInt(3); + m_closed30No = rs.getInt(4); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + m_nextStats = System.currentTimeMillis() + 3600000; // every hour + } // updateStatistics + + /** + * Get Total No of requests of type + * @return no + */ + public int getTotalNo() + { + updateStatistics(); + return m_totalNo; + } + + /** + * Get Open No of requests of type + * @return no + */ + public int getOpenNo() + { + updateStatistics(); + return m_openNo; + } + + /** + * Get Closed in last 30 days of type + * @return no + */ + public int getClosed30No() + { + updateStatistics(); + return m_closed30No; + } + + /** + * Get New in the last 30 days of type + * @return no + */ + public int getNew30No() + { + updateStatistics(); + return m_new30No; + } + + /** + * Get Requests of Type + * @param selfService self service + * @param C_BPartner_ID id or 0 for public + * @return array of requests + */ + public MRequest[] getRequests (boolean selfService, int C_BPartner_ID) + { + String sql = "SELECT * FROM R_Request WHERE R_RequestType_ID=?"; + if (selfService) + sql += " AND IsSelfService='Y'"; + if (C_BPartner_ID == 0) + sql += " AND ConfidentialType='A'"; + else + sql += " AND (ConfidentialType='A' OR C_BPartner_ID=" + C_BPartner_ID + ")"; + sql += " ORDER BY DocumentNo DESC"; + // + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getR_RequestType_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MRequest (getCtx(), rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + MRequest[] retValue = new MRequest[list.size ()]; + list.toArray (retValue); + return retValue; + } // getRequests + + /** + * Get public Requests of Type + * @return array of requests + */ + public MRequest[] getRequests () + { + return getRequests(true, 0); + } // getRequests + + /** + * Get Default R_Status_ID for Type + * @return status or 0 + */ + public int getDefaultR_Status_ID() + { + if (getR_StatusCategory_ID() == 0) + { + MStatusCategory sc = MStatusCategory.getDefault(getCtx()); + if (sc == null) + sc = MStatusCategory.createDefault(getCtx()); + if (sc != null && sc.getR_StatusCategory_ID() != 0) + setR_StatusCategory_ID(sc.getR_StatusCategory_ID()); + } + if (getR_StatusCategory_ID() != 0) + { + MStatusCategory sc = MStatusCategory.get(getCtx(), getR_StatusCategory_ID()); + return sc.getDefaultR_Status_ID(); + } + return 0; + } // getDefaultR_Status_ID + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getR_StatusCategory_ID() == 0) + { + MStatusCategory sc = MStatusCategory.getDefault(getCtx()); + if (sc != null && sc.getR_StatusCategory_ID() != 0) + setR_StatusCategory_ID(sc.getR_StatusCategory_ID()); + } + return true; + } // beforeSave + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MRequestType["); + sb.append(get_ID()).append("-").append(getName()) + .append ("]"); + return sb.toString(); + } // toString + + /** + * Get Sql to return single value for the Performance Indicator + * @param restrictions array of goal restrictions + * @param MeasureScope scope of this value + * @param MeasureDataType data type + * @param reportDate optional report date + * @param role role + * @return sql for performance indicator + */ + public String getSqlPI (MGoalRestriction[] restrictions, + String MeasureScope, String MeasureDataType, Timestamp reportDate, MRole role) + { + String dateColumn = "Created"; + String orgColumn = "AD_Org_ID"; + String bpColumn = "C_BPartner_ID"; + String pColumn = "M_Product_ID"; + // PlannedAmt -> PlannedQty -> Count + StringBuffer sb = new StringBuffer("SELECT COUNT(*) " + + "FROM R_Request WHERE R_RequestType_ID=" + getR_RequestType_ID() + + " AND Processed<>'Y'"); + // Date Restriction + + if (MMeasure.MEASUREDATATYPE_QtyAmountInTime.equals(MeasureDataType) + && !MGoal.MEASUREDISPLAY_Total.equals(MeasureScope)) + { + if (reportDate == null) + reportDate = new Timestamp(System.currentTimeMillis()); + String dateString = DB.TO_DATE(reportDate); + String trunc = "D"; + if (MGoal.MEASUREDISPLAY_Year.equals(MeasureScope)) + trunc = "Y"; + else if (MGoal.MEASUREDISPLAY_Quarter.equals(MeasureScope)) + trunc = "Q"; + else if (MGoal.MEASUREDISPLAY_Month.equals(MeasureScope)) + trunc = "MM"; + else if (MGoal.MEASUREDISPLAY_Week.equals(MeasureScope)) + trunc = "W"; + // else if (MGoal.MEASUREDISPLAY_Day.equals(MeasureDisplay)) + // ; + sb.append(" AND TRUNC(") + .append(dateColumn).append(",'").append(trunc).append("')=TRUNC(") + .append(DB.TO_DATE(reportDate)).append(",'").append(trunc).append("')"); + } // date + // + String sql = MMeasureCalc.addRestrictions(sb.toString(), false, restrictions, role, + "R_Request", orgColumn, bpColumn, pColumn); + + log.fine(sql); + return sql; + } // getSqlPI + + /** + * Get Sql to value for the bar chart + * @param restrictions array of goal restrictions + * @param MeasureDisplay scope of this value + * @param MeasureDataType data type + * @param startDate optional report start date + * @param role role + * @return sql for Bar Chart + */ + public String getSqlBarChart (MGoalRestriction[] restrictions, + String MeasureDisplay, String MeasureDataType, + Timestamp startDate, MRole role) + { + String dateColumn = "Created"; + String orgColumn = "AD_Org_ID"; + String bpColumn = "C_BPartner_ID"; + String pColumn = "M_Product_ID"; + // + StringBuffer sb = new StringBuffer("SELECT COUNT(*), "); + String groupBy = null; + String orderBy = null; + // + if (MMeasure.MEASUREDATATYPE_QtyAmountInTime.equals(MeasureDataType) + && !MGoal.MEASUREDISPLAY_Total.equals(MeasureDisplay)) + { + String trunc = "D"; + if (MGoal.MEASUREDISPLAY_Year.equals(MeasureDisplay)) + trunc = "Y"; + else if (MGoal.MEASUREDISPLAY_Quarter.equals(MeasureDisplay)) + trunc = "Q"; + else if (MGoal.MEASUREDISPLAY_Month.equals(MeasureDisplay)) + trunc = "MM"; + else if (MGoal.MEASUREDISPLAY_Week.equals(MeasureDisplay)) + trunc = "W"; + // else if (MGoal.MEASUREDISPLAY_Day.equals(MeasureDisplay)) + // ; + orderBy = "TRUNC(" + dateColumn + ",'" + trunc + "')"; + groupBy = orderBy + ", 0 "; + sb.append(groupBy) + .append("FROM R_Request "); + } + else + { + orderBy = "s.SeqNo"; + groupBy = "COALESCE(s.Name,TO_NCHAR('-')), s.R_Status_ID, s.SeqNo "; + sb.append(groupBy) + .append("FROM R_Request LEFT OUTER JOIN R_Status s ON (R_Request.R_Status_ID=s.R_Status_ID) "); + } + // Where + sb.append("WHERE R_Request.R_RequestType_ID=").append(getR_RequestType_ID()) + .append(" AND R_Request.Processed<>'Y'"); + // Date Restriction + if (startDate != null + && !MGoal.MEASUREDISPLAY_Total.equals(MeasureDisplay)) + { + String dateString = DB.TO_DATE(startDate); + sb.append(" AND ").append(dateColumn) + .append(">=").append(dateString); + } // date + // + String sql = MMeasureCalc.addRestrictions(sb.toString(), false, restrictions, role, + "R_Request", orgColumn, bpColumn, pColumn); + if (groupBy != null) + sql += " GROUP BY " + groupBy + " ORDER BY " + orderBy; + // + log.fine(sql); + return sql; + } // getSqlBarChart + + /** + * Get Zoom Query + * @param restrictions array of restrictions + * @param MeasureDisplay display + * @param date date + * @param R_Status_ID status + * @param role role + * @return query + */ + public MQuery getQuery(MGoalRestriction[] restrictions, + String MeasureDisplay, Timestamp date, int R_Status_ID, MRole role) + { + String dateColumn = "Created"; + String orgColumn = "AD_Org_ID"; + String bpColumn = "C_BPartner_ID"; + String pColumn = "M_Product_ID"; + // + MQuery query = new MQuery("R_Request"); + query.addRestriction("R_RequestType_ID", "=", getR_RequestType_ID()); + // + String where = null; + if (R_Status_ID != 0) + where = "R_Status_ID=" + R_Status_ID; + else + { + String trunc = "D"; + if (MGoal.MEASUREDISPLAY_Year.equals(MeasureDisplay)) + trunc = "Y"; + else if (MGoal.MEASUREDISPLAY_Quarter.equals(MeasureDisplay)) + trunc = "Q"; + else if (MGoal.MEASUREDISPLAY_Month.equals(MeasureDisplay)) + trunc = "MM"; + else if (MGoal.MEASUREDISPLAY_Week.equals(MeasureDisplay)) + trunc = "W"; + // else if (MGoal.MEASUREDISPLAY_Day.equals(MeasureDisplay)) + // trunc = "D"; + where = "TRUNC(" + dateColumn + ",'" + trunc + + "')=TRUNC(" + DB.TO_DATE(date) + ",'" + trunc + "')"; + } + String whereRestriction = MMeasureCalc.addRestrictions(where + " AND Processed<>'Y' ", + true, restrictions, role, + "R_Request", orgColumn, bpColumn, pColumn); + query.addRestriction(whereRestriction); + query.setRecordCount(1); + return query; + } // getQuery + +} // MRequestType diff --git a/base/src/org/compiere/model/MRequestUpdate.java b/base/src/org/compiere/model/MRequestUpdate.java new file mode 100644 index 0000000000..5c07c7f17c --- /dev/null +++ b/base/src/org/compiere/model/MRequestUpdate.java @@ -0,0 +1,111 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Request Update Model + * @author Jorg Janke + * @version $Id: MRequestUpdate.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MRequestUpdate extends X_R_RequestUpdate +{ + /** + * Standard Constructor + * @param ctx context + * @param R_RequestUpdate_ID id + * @param trxName trx + */ + public MRequestUpdate (Properties ctx, int R_RequestUpdate_ID, + String trxName) + { + super (ctx, R_RequestUpdate_ID, trxName); + } // MRequestUpdate + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MRequestUpdate (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MRequestUpdate + + /** + * Parent Constructor + * @param parent request + */ + public MRequestUpdate (MRequest parent) + { + super (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setR_Request_ID (parent.getR_Request_ID()); + // + setStartTime(parent.getStartTime()); + setEndTime(parent.getEndTime()); + setResult(parent.getResult()); + setQtySpent(parent.getQtySpent()); + setQtyInvoiced(parent.getQtyInvoiced()); + setM_ProductSpent_ID(parent.getM_ProductSpent_ID()); + setConfidentialTypeEntry(parent.getConfidentialTypeEntry()); + } // MRequestUpdate + + /** + * Do we have new info + * @return true if new info + */ + public boolean isNewInfo() + { + return getResult() != null; + } // isNewInfo + + /** + * Get Name of creator + * @return name + */ + public String getCreatedByName() + { + MUser user = MUser.get(getCtx(), getCreatedBy()); + return user.getName(); + } // getCreatedByName + + /** + * Get Confidential Entry Text (for jsp) + * @return text + */ + public String getConfidentialEntryText() + { + return MRefList.getListName(getCtx(), CONFIDENTIALTYPEENTRY_AD_Reference_ID, getConfidentialTypeEntry()); + } // getConfidentialTextEntry + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getConfidentialTypeEntry() == null) + setConfidentialTypeEntry(CONFIDENTIALTYPEENTRY_PublicInformation); + return true; + } // beforeSave + +} // MRequestUpdate diff --git a/base/src/org/compiere/model/MRequisition.java b/base/src/org/compiere/model/MRequisition.java new file mode 100644 index 0000000000..8909eda5b9 --- /dev/null +++ b/base/src/org/compiere/model/MRequisition.java @@ -0,0 +1,489 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Requisition Model + * + * @author Jorg Janke + * @version $Id: MRequisition.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MRequisition extends X_M_Requisition implements DocAction +{ + /** + * Standard Constructor + * @param ctx context + * @param M_Requisition_ID id + */ + public MRequisition (Properties ctx, int M_Requisition_ID, String trxName) + { + super (ctx, M_Requisition_ID, trxName); + if (M_Requisition_ID == 0) + { + // setDocumentNo (null); + // setAD_User_ID (0); + // setM_PriceList_ID (0); + // setM_Warehouse_ID(0); + setDateDoc(new Timestamp(System.currentTimeMillis())); + setDateRequired (new Timestamp(System.currentTimeMillis())); + setDocAction (DocAction.ACTION_Complete); // CO + setDocStatus (DocAction.STATUS_Drafted); // DR + setPriorityRule (PRIORITYRULE_Medium); // 5 + setTotalLines (Env.ZERO); + setIsApproved (false); + setPosted (false); + setProcessed (false); + } + } // MRequisition + + /** + * Load Constructor + * @param ctx context + * @param rs result set + */ + public MRequisition (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRequisition + + /** Lines */ + private MRequisitionLine[] m_lines = null; + + /** + * Get Lines + * @return array of lines + */ + public MRequisitionLine[] getLines() + { + if (m_lines != null) + return m_lines; + + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_RequisitionLine WHERE M_Requisition_ID=? ORDER BY Line"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getM_Requisition_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MRequisitionLine (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getLines", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_lines = new MRequisitionLine[list.size ()]; + list.toArray (m_lines); + return m_lines; + } // getLines + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MRequisition["); + sb.append(get_ID()).append("-").append(getDocumentNo()) + .append(",Status=").append(getDocStatus()).append(",Action=").append(getDocAction()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Get Document Info + * @return document info + */ + public String getDocumentInfo() + { + return Msg.getElement(getCtx(), "M_Requisition_ID") + " " + getDocumentNo(); + } // getDocumentInfo + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + // ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.INVOICE, getC_Invoice_ID()); + // if (re == null) + return null; + // return re.getPDF(file); + } // createPDF + + /** + * Set default PriceList + */ + public void setM_PriceList_ID() + { + MPriceList defaultPL = MPriceList.getDefault(getCtx(), false); + if (defaultPL == null) + defaultPL = MPriceList.getDefault(getCtx(), true); + if (defaultPL != null) + setM_PriceList_ID(defaultPL.getM_PriceList_ID()); + } // setM_PriceList_ID() + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getM_PriceList_ID() == 0) + setM_PriceList_ID(); + return true; + } // beforeSave + + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // process + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info("unlockIt - " + toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info("invalidateIt - " + toString()); + return true; + } // invalidateIt + + /** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + MRequisitionLine[] lines = getLines(); + + // Invalid + if (getAD_User_ID() == 0 + || getM_PriceList_ID() == 0 + || getM_Warehouse_ID() == 0 + || lines.length == 0) + return DocAction.STATUS_Invalid; + + // Std Period open? + if (!MPeriod.isOpen(getCtx(), getDateDoc(), MDocType.DOCBASETYPE_PurchaseRequisition)) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + + // Add up Amounts + int precision = MPriceList.getStandardPrecision(getCtx(), getM_PriceList_ID()); + BigDecimal totalLines = Env.ZERO; + for (int i = 0; i < lines.length; i++) + { + MRequisitionLine line = lines[i]; + BigDecimal lineNet = line.getQty().multiply(line.getPriceActual()); + lineNet = lineNet.setScale(precision, BigDecimal.ROUND_HALF_UP); + if (lineNet.compareTo(line.getLineNetAmt()) != 0) + { + line.setLineNetAmt(lineNet); + line.save(); + } + totalLines = totalLines.add (line.getLineNetAmt()); + } + if (totalLines.compareTo(getTotalLines()) != 0) + { + setTotalLines(totalLines); + save(); + } + m_justPrepared = true; + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info("approveIt - " + toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info("rejectIt - " + toString()); + setIsApproved(false); + return true; + } // rejectIt + + /** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + // Implicit Approval + if (!isApproved()) + approveIt(); + log.info(toString()); + + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + m_processMsg = valid; + return DocAction.STATUS_Invalid; + } + // + setProcessed(true); + setDocAction(ACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + /** + * Void Document. + * Same as Close. + * @return true if success + */ + public boolean voidIt() + { + log.info("voidIt - " + toString()); + return closeIt(); + } // voidIt + + /** + * Close Document. + * Cancel not delivered Qunatities + * @return true if success + */ + public boolean closeIt() + { + log.info("closeIt - " + toString()); + // Close Not delivered Qty + MRequisitionLine[] lines = getLines(); + BigDecimal totalLines = Env.ZERO; + for (int i = 0; i < lines.length; i++) + { + MRequisitionLine line = lines[i]; + BigDecimal finalQty = line.getQty(); + if (line.getC_OrderLine_ID() == 0) + finalQty = Env.ZERO; + else + { + MOrderLine ol = new MOrderLine (getCtx(), line.getC_OrderLine_ID(), get_TrxName()); + finalQty = ol.getQtyOrdered(); + } + // final qty is not line qty + if (finalQty.compareTo(line.getQty()) != 0) + { + String description = line.getDescription(); + if (description == null) + description = ""; + description += " [" + line.getQty() + "]"; + line.setDescription(description); + line.setQty(finalQty); + line.setLineNetAmt(); + line.save(); + } + totalLines = totalLines.add (line.getLineNetAmt()); + } + if (totalLines.compareTo(getTotalLines()) != 0) + { + setTotalLines(totalLines); + save(); + } + return true; + } // closeIt + + /** + * Reverse Correction + * @return true if success + */ + public boolean reverseCorrectIt() + { + log.info("reverseCorrectIt - " + toString()); + return false; + } // reverseCorrectionIt + + /** + * Reverse Accrual - none + * @return true if success + */ + public boolean reverseAccrualIt() + { + log.info("reverseAccrualIt - " + toString()); + return false; + } // reverseAccrualIt + + /** + * Re-activate + * @return true if success + */ + public boolean reActivateIt() + { + log.info("reActivateIt - " + toString()); + // setProcessed(false); + if (reverseCorrectIt()) + return true; + return false; + } // reActivateIt + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getDocumentNo()); + // - User + sb.append(" - ").append(getUserName()); + // : Total Lines = 123.00 (#1) + sb.append(": "). + append(Msg.translate(getCtx(),"TotalLines")).append("=").append(getTotalLines()) + .append(" (#").append(getLines().length).append(")"); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner + * @return AD_User_ID + */ + public int getDoc_User_ID() + { + return getAD_User_ID(); + } + + /** + * Get Document Currency + * @return C_Currency_ID + */ + public int getC_Currency_ID() + { + MPriceList pl = MPriceList.get(getCtx(), getM_PriceList_ID(), get_TrxName()); + return pl.getC_Currency_ID(); + } + + /** + * Get Document Approval Amount + * @return amount + */ + public BigDecimal getApprovalAmt() + { + return getTotalLines(); + } + + /** + * Get User Name + * @return user name + */ + public String getUserName() + { + return MUser.get(getCtx(), getAD_User_ID()).getName(); + } // getUserName + +} // MRequisition diff --git a/base/src/org/compiere/model/MRequisitionLine.java b/base/src/org/compiere/model/MRequisitionLine.java new file mode 100644 index 0000000000..313bac143a --- /dev/null +++ b/base/src/org/compiere/model/MRequisitionLine.java @@ -0,0 +1,232 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; +/** + * Requisition Line Model + * + * @author Jorg Janke + * @version $Id: MRequisitionLine.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MRequisitionLine extends X_M_RequisitionLine +{ + /** + * Standard Constructor + * @param ctx context + * @param M_RequisitionLine_ID id + * @param trxName transaction + */ + public MRequisitionLine (Properties ctx, int M_RequisitionLine_ID, String trxName) + { + super (ctx, M_RequisitionLine_ID, trxName); + if (M_RequisitionLine_ID == 0) + { + // setM_Requisition_ID (0); + setLine (0); // @SQL=SELECT COALESCE(MAX(Line),0)+10 AS DefaultValue FROM M_RequisitionLine WHERE M_Requisition_ID=@M_Requisition_ID@ + setLineNetAmt (Env.ZERO); + setPriceActual (Env.ZERO); + setQty (Env.ONE); // 1 + } + + } // MRequisitionLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MRequisitionLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRequisitionLine + + /** + * Parent Constructor + * @param req requisition + */ + public MRequisitionLine (MRequisition req) + { + this (req.getCtx(), 0, req.get_TrxName()); + setClientOrg(req); + setM_Requisition_ID(req.getM_Requisition_ID()); + m_M_PriceList_ID = req.getM_PriceList_ID(); + m_parent = req; + } // MRequisitionLine + + /** Parent */ + private MRequisition m_parent = null; + + /** PriceList */ + private int m_M_PriceList_ID = 0; + /** Temp BPartner */ + private int m_C_BPartner_ID = 0; + + /** + * @return Returns the c_BPartner_ID. + */ + public int getC_BPartner_ID () + { + return m_C_BPartner_ID; + } + /** + * @param partner_ID The c_BPartner_ID to set. + */ + public void setC_BPartner_ID (int partner_ID) + { + m_C_BPartner_ID = partner_ID; + } + + /** + * Get Parent + * @return parent + */ + public MRequisition getParent() + { + if (m_parent == null) + m_parent = new MRequisition (getCtx(), getM_Requisition_ID(), get_TrxName()); + return m_parent; + } // getParent + + /** + * Set Price + */ + public void setPrice() + { + if (getC_Charge_ID() != 0) + { + MCharge charge = MCharge.get(getCtx(), getC_Charge_ID()); + setPriceActual(charge.getChargeAmt()); + } + if (getM_Product_ID() == 0) + return; + if (m_M_PriceList_ID == 0) + m_M_PriceList_ID = getParent().getM_PriceList_ID(); + if (m_M_PriceList_ID == 0) + { + log.log(Level.SEVERE, "PriceList unknown!"); + return; + } + setPrice (m_M_PriceList_ID); + } // setPrice + + /** + * Set Price for Product and PriceList + * @param M_PriceList_ID price list + */ + public void setPrice (int M_PriceList_ID) + { + if (getM_Product_ID() == 0) + return; + // + log.fine("M_PriceList_ID=" + M_PriceList_ID); + boolean isSOTrx = false; + MProductPricing pp = new MProductPricing (getM_Product_ID(), + getC_BPartner_ID(), getQty(), isSOTrx); + pp.setM_PriceList_ID(M_PriceList_ID); + // pp.setPriceDate(getDateOrdered()); + // + setPriceActual (pp.getPriceStd()); + } // setPrice + + /** + * Calculate Line Net Amt + */ + public void setLineNetAmt () + { + BigDecimal lineNetAmt = getQty().multiply(getPriceActual()); + super.setLineNetAmt (lineNetAmt); + } // setLineNetAmt + + + /************************************************************************** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getLine() == 0) + { + String sql = "SELECT COALESCE(MAX(Line),0)+10 FROM M_RequisitionLine WHERE M_Requisition_ID=?"; + int ii = DB.getSQLValue (get_TrxName(), sql, getM_Requisition_ID()); + setLine (ii); + } + // Product & ASI - Charge + if (getM_Product_ID() != 0 && getC_Charge_ID() != 0) + setC_Charge_ID(0); + if (getM_AttributeSetInstance_ID() != 0 && getC_Charge_ID() != 0) + setM_AttributeSetInstance_ID(0); + // + if (getPriceActual().compareTo(Env.ZERO) == 0) + setPrice(); + setLineNetAmt(); + return true; + } // beforeSave + + /** + * After Save. + * Update Total on Header + * @param newRecord if new record + * @param success save was success + * @return true if saved + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + return updateHeader(); + } // afterSave + + + /** + * After Delete + * @param success + * @return true/false + */ + protected boolean afterDelete (boolean success) + { + if (!success) + return success; + return updateHeader(); + } // afterDelete + + /** + * Update Header + * @return header updated + */ + private boolean updateHeader() + { + log.fine(""); + String sql = "UPDATE M_Requisition r" + + " SET TotalLines=" + + "(SELECT COALESCE(SUM(LineNetAmt),0) FROM M_RequisitionLine rl " + + "WHERE r.M_Requisition_ID=rl.M_Requisition_ID) " + + "WHERE M_Requisition_ID=" + getM_Requisition_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + if (no != 1) + log.log(Level.SEVERE, "Header update #" + no); + m_parent = null; + return no == 1; + } // updateHeader + +} // MRequisitionLine diff --git a/base/src/org/compiere/model/MResolution.java b/base/src/org/compiere/model/MResolution.java new file mode 100644 index 0000000000..e365cc0964 --- /dev/null +++ b/base/src/org/compiere/model/MResolution.java @@ -0,0 +1,76 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import org.compiere.util.*; + +/** + * Request Resolution Model + * @author Jorg Janke + * @version $Id: MResolution.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MResolution extends X_R_Resolution +{ + /** + * Get MResolution from Cache + * @param ctx context + * @param R_Resolution_ID id + * @return MResolution + */ + public static MResolution get (Properties ctx, int R_Resolution_ID) + { + Integer key = new Integer (R_Resolution_ID); + MResolution retValue = (MResolution) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MResolution (ctx, R_Resolution_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("R_Resolution", 10); + + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param R_Resolution_ID id + * @param trxName + */ + public MResolution (Properties ctx, int R_Resolution_ID, String trxName) + { + super (ctx, R_Resolution_ID, trxName); + } // MResolution + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MResolution (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MResolution + +} // MResolution diff --git a/base/src/org/compiere/model/MResource.java b/base/src/org/compiere/model/MResource.java new file mode 100644 index 0000000000..8ded37a6c4 --- /dev/null +++ b/base/src/org/compiere/model/MResource.java @@ -0,0 +1,120 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Resource Model + * + * @author Jorg Janke + * @version $Id: MResource.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MResource extends X_S_Resource +{ + + /** + * Standard Constructor + * @param ctx context + * @param S_Resource_ID id + */ + public MResource (Properties ctx, int S_Resource_ID, String trxName) + { + super (ctx, S_Resource_ID, trxName); + } // MResource + + /** + * Load Constructor + * @param ctx context + * @param rs result set + */ + public MResource (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MResource + + + /** Cached Resource Type */ + private MResourceType m_resourceType = null; + /** Cached Product */ + private MProduct m_product = null; + + + /** + * Get cached Resource Type + * @return Resource Type + */ + public MResourceType getResourceType() + { + if (m_resourceType == null && getS_ResourceType_ID() != 0) + m_resourceType = new MResourceType (getCtx(), getS_ResourceType_ID(), get_TrxName()); + return m_resourceType; + } // getResourceType + + /** + * Get Product + * @return product + */ + public MProduct getProduct() + { + if (m_product == null) + { + MProduct[] products = MProduct.get(getCtx(), "S_Resource_ID=" + getS_Resource_ID(), get_TrxName()); + if (products.length > 0) + m_product = products[0]; + } + return m_product; + } // getProduct + + /** + * Before Save + * @param newRecord new + * @return true if it can be saved + */ + protected boolean beforeSave (boolean newRecord) + { + if (newRecord) + { + if (getValue() == null || getValue().length() == 0) + setValue(getName()); + m_product = new MProduct(this, getResourceType()); + return m_product.save(get_TrxName()); + } + return true; + } // beforeSave + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + + MProduct prod = getProduct(); + if (prod.setResource(this)) + prod.save(get_TrxName()); + + return success; + } // afterSave + +} // MResource diff --git a/base/src/org/compiere/model/MResourceAssignment.java b/base/src/org/compiere/model/MResourceAssignment.java new file mode 100644 index 0000000000..d9fe861114 --- /dev/null +++ b/base/src/org/compiere/model/MResourceAssignment.java @@ -0,0 +1,129 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; + + +/** + * Resource Assignment Model + * + * @author Jorg Janke + * @version $Id: MResourceAssignment.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MResourceAssignment extends X_S_ResourceAssignment +{ + /** + * Stnadard Constructor + * @param ctx + * @param S_ResourceAssignment_ID + */ + public MResourceAssignment (Properties ctx, int S_ResourceAssignment_ID, String trxName) + { + super (ctx, S_ResourceAssignment_ID, trxName); + p_info.setUpdateable(true); // default table is not updateable + // Default values + if (S_ResourceAssignment_ID == 0) + { + setAssignDateFrom(new Timestamp(System.currentTimeMillis())); + setQty(new BigDecimal(1.0)); + setName("."); + setIsConfirmed(false); + } + } // MResourceAssignment + + /** + * Load Contsructor + * @param ctx context + * @param rs result set + */ + public MResourceAssignment (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MResourceAssignment + + + /** + * After Save + * @param newRecord new + * @param success success + * @return true + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + /* + v_Description := :new.Name; + IF (:new.Description IS NOT NULL AND LENGTH(:new.Description) > 0) THEN + v_Description := v_Description || ' (' || :new.Description || ')'; + END IF; + + -- Update Expense Line + UPDATE S_TimeExpenseLine + SET Description = v_Description, + Qty = :new.Qty + WHERE S_ResourceAssignment_ID = :new.S_ResourceAssignment_ID + AND (Description <> v_Description OR Qty <> :new.Qty); + + -- Update Order Line + UPDATE C_OrderLine + SET Description = v_Description, + QtyOrdered = :new.Qty + WHERE S_ResourceAssignment_ID = :new.S_ResourceAssignment_ID + AND (Description <> v_Description OR QtyOrdered <> :new.Qty); + + -- Update Invoice Line + UPDATE C_InvoiceLine + SET Description = v_Description, + QtyInvoiced = :new.Qty + WHERE S_ResourceAssignment_ID = :new.S_ResourceAssignment_ID + AND (Description <> v_Description OR QtyInvoiced <> :new.Qty); + */ + return success; + } // afterSave + + /** + * String Representation + * @return string + */ + public String toString() + { + StringBuffer sb = new StringBuffer ("MResourceAssignment[ID="); + sb.append(get_ID()) + .append(",S_Resource_ID=").append(getS_Resource_ID()) + .append(",From=").append(getAssignDateFrom()) + .append(",To=").append(getAssignDateTo()) + .append(",Qty=").append(getQty()) + .append("]"); + return sb.toString(); + } // toString + + /** + * Before Delete + * @return true if not confirmed + */ + protected boolean beforeDelete () + { + // allow to delete, when not confirmed + if (isConfirmed()) + return false; + + return true; + } // beforeDelete + +} // MResourceAssignment diff --git a/base/src/org/compiere/model/MResourceType.java b/base/src/org/compiere/model/MResourceType.java new file mode 100644 index 0000000000..846a0ff9d8 --- /dev/null +++ b/base/src/org/compiere/model/MResourceType.java @@ -0,0 +1,80 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Resource Type Model + * + * @author Jorg Janke + * @version $Id: MResourceType.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MResourceType extends X_S_ResourceType +{ + /** + * Standard Constructor + * @param ctx context + * @param S_ResourceType_ID id + */ + public MResourceType (Properties ctx, int S_ResourceType_ID, String trxName) + { + super (ctx, S_ResourceType_ID, trxName); + } // MResourceType + + /** + * Load Constructor + * @param ctx context + * @param rs result set + */ + public MResourceType (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MResourceType + + + /** + * After Save + * @param newRecord new + * @param success success + * @return true + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + + // Update Products + if (!newRecord) + { + MProduct[] products = MProduct.get(getCtx(), "S_Resource_ID IN " + + "(SELECT S_Resource_ID FROM S_Resource WHERE S_ResourceType_ID=" + + getS_ResourceType_ID() + ")", get_TrxName()); + for (int i = 0; i < products.length; i++) + { + MProduct product = products[i]; + if (product.setResource(this)) + product.save(get_TrxName()); + } + } + + return success; + } // afterSave + +} // MResourceType diff --git a/base/src/org/compiere/model/MResourceUnAvailable.java b/base/src/org/compiere/model/MResourceUnAvailable.java new file mode 100644 index 0000000000..b0d625e700 --- /dev/null +++ b/base/src/org/compiere/model/MResourceUnAvailable.java @@ -0,0 +1,72 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + + +/** + * Resource Unavailable + * + * @author Jorg Janke + * @version $Id: MResourceUnAvailable.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MResourceUnAvailable extends X_S_ResourceUnAvailable +{ + + /** + * Standard Constructor + * @param ctx context + * @param S_ResourceUnAvailable_ID id + * @param trxName trx + */ + public MResourceUnAvailable (Properties ctx, int S_ResourceUnAvailable_ID, String trxName) + { + super (ctx, S_ResourceUnAvailable_ID, trxName); + } // MResourceUnAvailable + + /** + * MResourceUnAvailable + * @param ctx context + * @param rs result set + */ + public MResourceUnAvailable (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MResourceUnAvailable + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getDateTo() == null) + setDateTo(getDateFrom()); + if (getDateFrom().after(getDateTo())) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@DateTo@ > @DateFrom@")); + return false; + } + return true; + } // beforeSave + +} // MResourceUnAvailable diff --git a/base/src/org/compiere/model/MRevenueRecognition.java b/base/src/org/compiere/model/MRevenueRecognition.java new file mode 100644 index 0000000000..6456f21b9b --- /dev/null +++ b/base/src/org/compiere/model/MRevenueRecognition.java @@ -0,0 +1,52 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Revenue Recognition Model + * + * @author Jorg Janke + * @version $Id: MRevenueRecognition.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MRevenueRecognition extends X_C_RevenueRecognition +{ + + /** + * Standard Constructor + * @param ctx context + * @param C_RevenueRecognition_ID id + */ + public MRevenueRecognition (Properties ctx, int C_RevenueRecognition_ID, String trxName) + { + super (ctx, C_RevenueRecognition_ID, trxName); + } // MRevenueRecognition + + /** + * Load Constructor + * @param ctx context + * @param rs result set + */ + public MRevenueRecognition (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRevenueRecognition + +} // MRevenueRecognition diff --git a/base/src/org/compiere/model/MRevenueRecognitionPlan.java b/base/src/org/compiere/model/MRevenueRecognitionPlan.java new file mode 100644 index 0000000000..55554288cf --- /dev/null +++ b/base/src/org/compiere/model/MRevenueRecognitionPlan.java @@ -0,0 +1,99 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Revenue Recognition Plan + * + * @author Jorg Janke + * @version $Id: MRevenueRecognitionPlan.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MRevenueRecognitionPlan extends X_C_RevenueRecognition_Plan +{ + /** + * Standard Constructor + * @param ctx context + * @param C_RevenueRecognition_Plan_ID id + */ + public MRevenueRecognitionPlan (Properties ctx, int C_RevenueRecognition_Plan_ID, String trxName) + { + super (ctx, C_RevenueRecognition_Plan_ID, trxName); + if (C_RevenueRecognition_Plan_ID == 0) + { + // setC_AcctSchema_ID (0); + // setC_Currency_ID (0); + // setC_InvoiceLine_ID (0); + // setC_RevenueRecognition_ID (0); + // setC_RevenueRecognition_Plan_ID (0); + // setP_Revenue_Acct (0); + // setUnEarnedRevenue_Acct (0); + setTotalAmt (Env.ZERO); + setRecognizedAmt (Env.ZERO); + } + } // MRevenueRecognitionPlan + + /** + * Load Constructor + * @param ctx context + * @param rs result set + */ + public MRevenueRecognitionPlan (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRevenueRecognitionPlan + + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (newRecord) + { + MRevenueRecognition rr = new MRevenueRecognition(getCtx(), getC_RevenueRecognition_ID(), get_TrxName()); + if (rr.isTimeBased()) + { + /** Get InvoiveQty + SELECT QtyInvoiced, M_Product_ID + INTO v_Qty, v_M_Product_ID + FROM C_InvoiceLine + WHERE C_InvoiceLine_ID=:new.C_InvoiceLine_ID; + -- Insert + AD_Sequence_Next ('C_ServiceLevel', :new.AD_Client_ID, v_NextNo); + INSERT INTO C_ServiceLevel + (C_ServiceLevel_ID, C_RevenueRecognition_Plan_ID, + AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy, + M_Product_ID, Description, ServiceLevelInvoiced, ServiceLevelProvided, + Processing,Processed) + VALUES + (v_NextNo, :new.C_RevenueRecognition_Plan_ID, + :new.AD_Client_ID,:new.AD_Org_ID,'Y',SysDate,:new.CreatedBy,SysDate,:new.UpdatedBy, + v_M_Product_ID, NULL, v_Qty, 0, + 'N', 'N'); + **/ + } + } + return success; + } // afterSave +} // MRevenueRecognitionPlan diff --git a/base/src/org/compiere/model/MRfQ.java b/base/src/org/compiere/model/MRfQ.java new file mode 100644 index 0000000000..c6b786b295 --- /dev/null +++ b/base/src/org/compiere/model/MRfQ.java @@ -0,0 +1,270 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import java.util.logging.*; +import org.compiere.util.*; + +/** + * RfQ Model + * + * @author Jorg Janke + * @version $Id: MRfQ.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MRfQ extends X_C_RfQ +{ + /** + * Get MRfQ from Cache + * @param ctx context + * @param C_RfQ_ID id + * @param trxName transaction + * @return MRfQ + */ + public static MRfQ get (Properties ctx, int C_RfQ_ID, String trxName) + { + Integer key = new Integer (C_RfQ_ID); + MRfQ retValue = (MRfQ) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MRfQ (ctx, C_RfQ_ID, trxName); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("C_RfQ", 10); + + + /** + * Standard Constructor + * @param ctx context + * @param C_RfQ_ID id + * @param trxName transaction + */ + public MRfQ (Properties ctx, int C_RfQ_ID, String trxName) + { + super (ctx, C_RfQ_ID, trxName); + if (C_RfQ_ID == 0) + { + // setC_RfQ_Topic_ID (0); + // setName (null); + // setC_Currency_ID (0); // @$C_Currency_ID @ + // setSalesRep_ID (0); + // + setDateResponse (new Timestamp(System.currentTimeMillis())); + setDateWorkStart (new Timestamp(System.currentTimeMillis())); + setIsInvitedVendorsOnly (false); + setQuoteType (QUOTETYPE_QuoteSelectedLines); + setIsQuoteAllQty (false); + setIsQuoteTotalAmt (false); + setIsRfQResponseAccepted (true); + setIsSelfService (true); + setProcessed (false); + } + } // MRfQ + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MRfQ (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRfQ + + /** + * Get active Lines + * @return array of lines + */ + public MRfQLine[] getLines() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_RfQLine " + + "WHERE C_RfQ_ID=? AND IsActive='Y' " + + "ORDER BY Line"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_RfQ_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MRfQLine (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MRfQLine[] retValue = new MRfQLine[list.size ()]; + list.toArray (retValue); + return retValue; + } // getLines + + /** + * Get RfQ Responses + * @param activeOnly active responses only + * @param completedOnly complete responses only + * @return array of lines + */ + public MRfQResponse[] getResponses (boolean activeOnly, boolean completedOnly) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_RfQResponse " + + "WHERE C_RfQ_ID=?"; + if (activeOnly) + sql += " AND IsActive='Y'"; + if (completedOnly) + sql += " AND IsComplete='Y'"; + sql += " ORDER BY Price"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_RfQ_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MRfQResponse (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MRfQResponse[] retValue = new MRfQResponse[list.size ()]; + list.toArray (retValue); + return retValue; + } // getResponses + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MRfQ["); + sb.append(get_ID()).append(",Name=").append(getName()) + .append(",QuoteType=").append(getQuoteType()) + .append("]"); + return sb.toString (); + } // toString + + + /************************************************************************** + * Is Quote Total Amt Only + * @return true if total amout only + */ + public boolean isQuoteTotalAmtOnly() + { + return QUOTETYPE_QuoteTotalOnly.equals(getQuoteType()); + } // isQuoteTotalAmtOnly + + /** + * Is Quote Selected Lines + * @return true if quote selected lines + */ + public boolean isQuoteSelectedLines() + { + return QUOTETYPE_QuoteSelectedLines.equals(getQuoteType()); + } // isQuoteSelectedLines + + /** + * Is Quote All Lines + * @return true if quote selected lines + */ + public boolean isQuoteAllLines() + { + return QUOTETYPE_QuoteAllLines.equals(getQuoteType()); + } // isQuoteAllLines + + /** + * Is "Quote Total Amt Only" Valid + * @return null or error message + */ + public String checkQuoteTotalAmtOnly() + { + if (!isQuoteTotalAmtOnly()) + return null; + // Need to check Line Qty + MRfQLine[] lines = getLines(); + for (int i = 0; i < lines.length; i++) + { + MRfQLine line = lines[i]; + MRfQLineQty[] qtys = line.getQtys(); + if (qtys.length > 1) + { + log.warning("isQuoteTotalAmtOnlyValid - #" + qtys.length + " - " + line); + String msg = "@Line@ " + line.getLine() + + ": #@C_RfQLineQty@=" + qtys.length + " - @IsQuoteTotalAmt@"; + return msg; + } + } + return null; + } // checkQuoteTotalAmtOnly + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Calculate Complete Date (also used to verify) + if (getDateWorkStart() != null && getDeliveryDays() != 0) + setDateWorkComplete (TimeUtil.addDays(getDateWorkStart(), getDeliveryDays())); + // Calculate Delivery Days + else if (getDateWorkStart() != null && getDeliveryDays() == 0 && getDateWorkComplete() != null) + setDeliveryDays (TimeUtil.getDaysBetween(getDateWorkStart(), getDateWorkComplete())); + // Calculate Start Date + else if (getDateWorkStart() == null && getDeliveryDays() != 0 && getDateWorkComplete() != null) + setDateWorkStart (TimeUtil.addDays(getDateWorkComplete(), getDeliveryDays() * -1)); + + return true; + } // beforeSave + +} // MRfQ diff --git a/base/src/org/compiere/model/MRfQLine.java b/base/src/org/compiere/model/MRfQLine.java new file mode 100644 index 0000000000..c891361b98 --- /dev/null +++ b/base/src/org/compiere/model/MRfQLine.java @@ -0,0 +1,206 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import java.util.logging.*; +import org.compiere.util.*; + +/** + * RfQ Line + * + * @author Jorg Janke + * @version $Id: MRfQLine.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MRfQLine extends X_C_RfQLine +{ + /** + * Get MRfQLine from Cache + * @param ctx context + * @param C_RfQLine_ID id + * @param trxName transaction + * @return MRfQLine + */ + public static MRfQLine get (Properties ctx, int C_RfQLine_ID, String trxName) + { + Integer key = new Integer (C_RfQLine_ID); + MRfQLine retValue = (MRfQLine) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MRfQLine (ctx, C_RfQLine_ID, trxName); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("C_RfQLine", 20); + + /** + * Standard Constructor + * @param ctx context + * @param C_RfQLine_ID id + * @param trxName transaction + */ + public MRfQLine (Properties ctx, int C_RfQLine_ID, String trxName) + { + super (ctx, C_RfQLine_ID, trxName); + if (C_RfQLine_ID == 0) + { + setLine (0); + } + } // MRfQLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MRfQLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + if (get_ID() > 0) + s_cache.put(new Integer(get_ID()), this); + } // MRfQLine + + /** + * Parent Constructor + * @param rfq RfQ + */ + public MRfQLine (MRfQ rfq) + { + this (rfq.getCtx(), 0, rfq.get_TrxName()); + setClientOrg(rfq); + setC_RfQ_ID(rfq.getC_RfQ_ID()); + } // MRfQLine + + /** Qyantities */ + private MRfQLineQty[] m_qtys = null; + + /** + * Get Quantities + * @return array of quantities + */ + public MRfQLineQty[] getQtys () + { + return getQtys (false); + } // getQtys + + /** + * Get Quantities + * @param requery requery + * @return array of quantities + */ + public MRfQLineQty[] getQtys (boolean requery) + { + if (m_qtys != null && !requery) + return m_qtys; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_RfQLineQty " + + "WHERE C_RfQLine_ID=? AND IsActive='Y' " + + "ORDER BY Qty"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_RfQLine_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MRfQLineQty (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // Create Default (1) + if (list.size() == 0) + { + MRfQLineQty qty = new MRfQLineQty(this); + qty.save(); + list.add(qty); + } + + m_qtys = new MRfQLineQty[list.size ()]; + list.toArray (m_qtys); + return m_qtys; + } // getQtys + + /** + * Get Product Details + * @return Product Name, etc. + */ + public String getProductDetailHTML() + { + if (getM_Product_ID() == 0) + return ""; + StringBuffer sb = new StringBuffer(); + MProduct product = MProduct.get (getCtx(), getM_Product_ID()); + sb.append(product.getName()); + if (product.getDescription() != null && product.getDescription().length() > 0) + sb.append("
").append(product.getDescription()).append(""); + return sb.toString(); + } // getProductDetails + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MRfQLine["); + sb.append(get_ID()).append(",").append(getLine()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Calculate Complete Date (also used to verify) + if (getDateWorkStart() != null && getDeliveryDays() != 0) + setDateWorkComplete (TimeUtil.addDays(getDateWorkStart(), getDeliveryDays())); + // Calculate Delivery Days + else if (getDateWorkStart() != null && getDeliveryDays() == 0 && getDateWorkComplete() != null) + setDeliveryDays (TimeUtil.getDaysBetween(getDateWorkStart(), getDateWorkComplete())); + // Calculate Start Date + else if (getDateWorkStart() == null && getDeliveryDays() != 0 && getDateWorkComplete() != null) + setDateWorkStart (TimeUtil.addDays(getDateWorkComplete(), getDeliveryDays() * -1)); + + return true; + } // beforeSave + +} // MRfQLine diff --git a/base/src/org/compiere/model/MRfQLineQty.java b/base/src/org/compiere/model/MRfQLineQty.java new file mode 100644 index 0000000000..e1976a5d22 --- /dev/null +++ b/base/src/org/compiere/model/MRfQLineQty.java @@ -0,0 +1,172 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import java.util.logging.*; +import org.compiere.util.*; + +/** + * RfQ Line Qty Model + * + * @author Jorg Janke + * @version $Id: MRfQLineQty.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MRfQLineQty extends X_C_RfQLineQty +{ + /** + * Get MRfQLineQty from Cache + * @param ctx context + * @param C_RfQLineQty_ID id + * @param trxName transaction + * @return MRfQLineQty + */ + public static MRfQLineQty get (Properties ctx, int C_RfQLineQty_ID, String trxName) + { + Integer key = new Integer (C_RfQLineQty_ID); + MRfQLineQty retValue = (MRfQLineQty) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MRfQLineQty (ctx, C_RfQLineQty_ID, trxName); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("C_RfQLineQty", 20); + + /** + * Standard Constructor + * @param ctx context + * @param C_RfQLineQty_ID id + * @param trxName transaction + */ + public MRfQLineQty (Properties ctx, int C_RfQLineQty_ID, String trxName) + { + super (ctx, C_RfQLineQty_ID, trxName); + if (C_RfQLineQty_ID == 0) + { + // setC_RfQLine_ID (0); + // setC_UOM_ID (0); + setIsOfferQty (false); + setIsPurchaseQty (false); + setQty (Env.ONE); // 1 + } + } // MRfQLineQty + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MRfQLineQty (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + if (get_ID() > 0) + s_cache.put (new Integer (get_ID()), this); + } // MRfQLineQty + + /** + * Parent Constructor + * @param line RfQ line + */ + public MRfQLineQty (MRfQLine line) + { + this (line.getCtx(), 0, line.get_TrxName()); + setClientOrg(line); + setC_RfQLine_ID (line.getC_RfQLine_ID()); + } // MRfQLineQty + + /** Unit of Measure */ + private MUOM m_uom = null; + + /** + * Get Uom Name + * @return UOM + */ + public String getUomName() + { + if (m_uom == null) + m_uom = MUOM.get(getCtx(), getC_UOM_ID()); + return m_uom.getName(); + } // getUomText + + /** + * Get active Response Qtys of this RfQ Qty + * @param onlyValidAmounts only valid amounts + * @return array of response line qtys + */ + public MRfQResponseLineQty[] getResponseQtys (boolean onlyValidAmounts) + { + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + String sql = "SELECT * FROM C_RfQResponseLineQty WHERE C_RfQLineQty_ID=? AND IsActive='Y'"; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_RfQLineQty_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MRfQResponseLineQty qty = new MRfQResponseLineQty(getCtx(), rs, get_TrxName()); + if (onlyValidAmounts && !qty.isValidAmt()) + ; + else + list.add (qty); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MRfQResponseLineQty[] retValue = new MRfQResponseLineQty[list.size ()]; + list.toArray (retValue); + return retValue; + } // getResponseQtys + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MRfQLineQty["); + sb.append(get_ID()).append(",Qty=").append(getQty()) + .append(",Offer=").append(isOfferQty()) + .append(",Purchase=").append(isPurchaseQty()) + .append ("]"); + return sb.toString (); + } // toString + +} // MRfQLineQty diff --git a/base/src/org/compiere/model/MRfQResponse.java b/base/src/org/compiere/model/MRfQResponse.java new file mode 100644 index 0000000000..82a7b6f297 --- /dev/null +++ b/base/src/org/compiere/model/MRfQResponse.java @@ -0,0 +1,390 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; + +import org.compiere.print.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * RfQ Response Model + * + * @author Jorg Janke + * @version $Id: MRfQResponse.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MRfQResponse extends X_C_RfQResponse +{ + /** + * Standard Constructor + * @param ctx context + * @param C_RfQResponse_ID id + * @param trxName transaction + */ + public MRfQResponse (Properties ctx, int C_RfQResponse_ID, String trxName) + { + super (ctx, C_RfQResponse_ID, trxName); + if (C_RfQResponse_ID == 0) + { + setIsComplete (false); + setIsSelectedWinner (false); + setIsSelfService (false); + setPrice (Env.ZERO); + setProcessed(false); + setProcessing(false); + } + } // MRfQResponse + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MRfQResponse (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRfQResponse + + /** + * Parent Constructor + * @param rfq rfq + * @param subscriber subscriber + */ + public MRfQResponse (MRfQ rfq, MRfQTopicSubscriber subscriber) + { + this (rfq, subscriber, + subscriber.getC_BPartner_ID(), + subscriber.getC_BPartner_Location_ID(), + subscriber.getAD_User_ID()); + } // MRfQResponse + + /** + * Parent Constructor + * @param rfq rfq + * @param partner web response + */ + public MRfQResponse (MRfQ rfq, MBPartner partner) + { + this (rfq, null, + partner.getC_BPartner_ID(), + partner.getPrimaryC_BPartner_Location_ID(), + partner.getPrimaryAD_User_ID()); + } // MRfQResponse + + /** + * Parent Constructor. + * Automatically saved if lines were created + * Saved automatically + * @param rfq rfq + * @param subscriber optional subscriber + * @param C_BPartner_ID bpartner + * @param C_BPartner_Location_ID bpartner location + * @param AD_User_ID bpartner user + */ + public MRfQResponse (MRfQ rfq, MRfQTopicSubscriber subscriber, + int C_BPartner_ID, int C_BPartner_Location_ID, int AD_User_ID) + { + this (rfq.getCtx(), 0, rfq.get_TrxName()); + setClientOrg(rfq); + setC_RfQ_ID(rfq.getC_RfQ_ID()); + setC_Currency_ID (rfq.getC_Currency_ID()); + setName (rfq.getName()); + m_rfq = rfq; + // Subscriber info + setC_BPartner_ID (C_BPartner_ID); + setC_BPartner_Location_ID (C_BPartner_Location_ID); + setAD_User_ID(AD_User_ID); + + // Create Lines + MRfQLine[] lines = rfq.getLines(); + for (int i = 0; i < lines.length; i++) + { + if (!lines[i].isActive()) + continue; + + // Product on "Only" list + if (subscriber != null + && !subscriber.isIncluded(lines[i].getM_Product_ID() )) + continue; + // + if (get_ID() == 0) // save Response + save(); + + MRfQResponseLine line = new MRfQResponseLine (this, lines[i]); + // line is not saved (dumped) if there are no Qtys + } + } // MRfQResponse + + /** underlying RfQ */ + private MRfQ m_rfq = null; + /** Lines */ + private MRfQResponseLine[] m_lines = null; + + + /************************************************************************** + * Get Response Lines + * @param requery requery + * @return array of Response Lines + */ + public MRfQResponseLine[] getLines(boolean requery) + { + if (m_lines != null && !requery) + return m_lines; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_RfQResponseLine " + + "WHERE C_RfQResponse_ID=? AND IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_RfQResponse_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MRfQResponseLine(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getLines", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + m_lines = new MRfQResponseLine[list.size ()]; + list.toArray (m_lines); + return m_lines; + } // getLines + + /** + * Get Response Lines (no requery) + * @return array of Response Lines + */ + public MRfQResponseLine[] getLines () + { + return getLines (false); + } // getLines + + + /** + * Get RfQ + * @return rfq + */ + public MRfQ getRfQ() + { + if (m_rfq == null) + m_rfq = MRfQ.get (getCtx(), getC_RfQ_ID(), get_TrxName()); + return m_rfq; + } // getRfQ + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MRfQResponse["); + sb.append(get_ID()) + .append(",Complete=").append(isComplete()) + .append(",Winner=").append(isSelectedWinner()) + .append ("]"); + return sb.toString (); + } // toString + + + /************************************************************************** + * Send RfQ + * @return true if RfQ is sent per email. + */ + public boolean sendRfQ() + { + MUser to = MUser.get(getCtx(), getAD_User_ID()); + if (to.get_ID() == 0 || to.getEMail() == null || to.getEMail().length() == 0) + { + log.log(Level.SEVERE, "No User or no EMail - " + to); + return false; + } + MClient client = MClient.get(getCtx()); + // + String message = getDescription(); + if (message == null || message.length() == 0) + message = getHelp(); + else if (getHelp() != null) + message += "\n" + getHelp(); + if (message == null) + message = getName(); + // + EMail email = client.createEMail(to.getEMail(), "RfQ: " + getName(), message); + email.addAttachment(createPDF()); + if (EMail.SENT_OK.equals(email.send())) + { + setDateInvited(new Timestamp (System.currentTimeMillis())); + save(); + return true; + } + return false; + } // sendRfQ + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + return createPDF (null); + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return File or null + */ + public File createPDF (File file) + { + ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.RFQ, getC_RfQResponse_ID()); + if (re == null) + return null; + return re.getPDF(file); + } // getPDF + + + /************************************************************************** + * Check if Response is Complete + * @return null if complere - error message otherwise + */ + public String checkComplete() + { + if (isComplete()) + setIsComplete(false); + MRfQ rfq = getRfQ(); + + // Is RfQ Total valid + String error = rfq.checkQuoteTotalAmtOnly(); + if (error != null && error.length() > 0) + return error; + + // Do we have Total Amount ? + if (rfq.isQuoteTotalAmt() || rfq.isQuoteTotalAmtOnly()) + { + BigDecimal amt = getPrice(); + if (amt == null || Env.ZERO.compareTo(amt) >= 0) + return "No Total Amount"; + } + + // Do we have an amount/qty for all lines + if (rfq.isQuoteAllLines()) + { + MRfQResponseLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MRfQResponseLine line = lines[i]; + if (!line.isActive()) + return "Line " + line.getRfQLine().getLine() + + ": Not Active"; + boolean validAmt = false; + MRfQResponseLineQty[] qtys = line.getQtys(false); + for (int j = 0; j < qtys.length; j++) + { + MRfQResponseLineQty qty = qtys[j]; + if (!qty.isActive()) + continue; + BigDecimal amt = qty.getNetAmt(); + if (amt != null && Env.ZERO.compareTo(amt) < 0) + { + validAmt = true; + break; + } + } + if (!validAmt) + return "Line " + line.getRfQLine().getLine() + + ": No Amount"; + } + } + + // Do we have an amount for all line qtys + if (rfq.isQuoteAllQty()) + { + MRfQResponseLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MRfQResponseLine line = lines[i]; + MRfQResponseLineQty[] qtys = line.getQtys(false); + for (int j = 0; j < qtys.length; j++) + { + MRfQResponseLineQty qty = qtys[j]; + if (!qty.isActive()) + return "Line " + line.getRfQLine().getLine() + + " Qty=" + qty.getRfQLineQty().getQty() + + ": Not Active"; + BigDecimal amt = qty.getNetAmt(); + if (amt == null || Env.ZERO.compareTo(amt) >= 0) + return "Line " + line.getRfQLine().getLine() + + " Qty=" + qty.getRfQLineQty().getQty() + + ": No Amount"; + } + } + } + + setIsComplete(true); + return null; + } // checkComplete + + /** + * Is Quote Total Amt Only + * @return true if only Total + */ + public boolean isQuoteTotalAmtOnly() + { + return getRfQ().isQuoteTotalAmtOnly(); + } // isQuoteTotalAmtOnly + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Calculate Complete Date (also used to verify) + if (getDateWorkStart() != null && getDeliveryDays() != 0) + setDateWorkComplete (TimeUtil.addDays(getDateWorkStart(), getDeliveryDays())); + // Calculate Delivery Days + else if (getDateWorkStart() != null && getDeliveryDays() == 0 && getDateWorkComplete() != null) + setDeliveryDays (TimeUtil.getDaysBetween(getDateWorkStart(), getDateWorkComplete())); + // Calculate Start Date + else if (getDateWorkStart() == null && getDeliveryDays() != 0 && getDateWorkComplete() != null) + setDateWorkStart (TimeUtil.addDays(getDateWorkComplete(), getDeliveryDays() * -1)); + + + return true; + } // beforeSave + +} // MRfQResponse diff --git a/base/src/org/compiere/model/MRfQResponseLine.java b/base/src/org/compiere/model/MRfQResponseLine.java new file mode 100644 index 0000000000..87c4eed471 --- /dev/null +++ b/base/src/org/compiere/model/MRfQResponseLine.java @@ -0,0 +1,218 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import java.util.logging.*; +import org.compiere.util.*; + +/** + * RfQ Response Line Model + * + * @author Jorg Janke + * @version $Id: MRfQResponseLine.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MRfQResponseLine extends X_C_RfQResponseLine +{ + /** + * Persistency Constructor + * @param ctx context + * @param ignored ignored + * @param trxName transaction + */ + public MRfQResponseLine (Properties ctx, int ignored, String trxName) + { + super(ctx, 0, trxName); + if (ignored != 0) + throw new IllegalArgumentException("Multi-Key"); + } // MRfQResponseLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MRfQResponseLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRfQResponseLine + + /** + * Parent Constructor. + * Also creates qtys if RfQ Qty + * Is saved if there are qtys(!) + * @param response response + * @param line line + */ + public MRfQResponseLine (MRfQResponse response, MRfQLine line) + { + super (response.getCtx(), 0, response.get_TrxName()); + setClientOrg(response); + setC_RfQResponse_ID (response.getC_RfQResponse_ID()); + // + setC_RfQLine_ID (line.getC_RfQLine_ID()); + // + setIsSelectedWinner (false); + setIsSelfService (false); + // + MRfQLineQty[] qtys = line.getQtys(); + for (int i = 0; i < qtys.length; i++) + { + if (qtys[i].isActive() && qtys[i].isRfQQty()) + { + if (get_ID() == 0) // save this line + save(); + MRfQResponseLineQty qty = new MRfQResponseLineQty (this, qtys[i]); + qty.save(); + } + } + } // MRfQResponseLine + + /** RfQ Line */ + private MRfQLine m_rfqLine = null; + /** Quantities */ + private MRfQResponseLineQty[] m_qtys = null; + + /** + * Get Quantities + * @return array of quantities + */ + public MRfQResponseLineQty[] getQtys () + { + return getQtys (false); + } // getQtys + + /** + * Get Quantities + * @param requery requery + * @return array of quantities + */ + public MRfQResponseLineQty[] getQtys (boolean requery) + { + if (m_qtys != null && !requery) + return m_qtys; + + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_RfQResponseLineQty " + + "WHERE C_RfQResponseLine_ID=? AND IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_RfQResponseLine_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MRfQResponseLineQty(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + m_qtys = new MRfQResponseLineQty[list.size ()]; + list.toArray (m_qtys); + return m_qtys; + } // getQtys + + /** + * Get RfQ Line + * @return rfq line + */ + public MRfQLine getRfQLine() + { + if (m_rfqLine == null) + m_rfqLine = MRfQLine.get(getCtx(), getC_RfQLine_ID(), get_TrxName()); + return m_rfqLine; + } // getRfQLine + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MRfQResponseLine["); + sb.append(get_ID()).append(",Winner=").append(isSelectedWinner()) + .append ("]"); + return sb.toString (); + } // toString + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Calculate Complete Date (also used to verify) + if (getDateWorkStart() != null && getDeliveryDays() != 0) + setDateWorkComplete (TimeUtil.addDays(getDateWorkStart(), getDeliveryDays())); + // Calculate Delivery Days + else if (getDateWorkStart() != null && getDeliveryDays() == 0 && getDateWorkComplete() != null) + setDeliveryDays (TimeUtil.getDaysBetween(getDateWorkStart(), getDateWorkComplete())); + // Calculate Start Date + else if (getDateWorkStart() == null && getDeliveryDays() != 0 && getDateWorkComplete() != null) + setDateWorkStart (TimeUtil.addDays(getDateWorkComplete(), getDeliveryDays() * -1)); + + if (!isActive()) + setIsSelectedWinner(false); + return true; + } // beforeSave + + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!isActive()) + { + getQtys (false); + for (int i = 0; i < m_qtys.length; i++) + { + MRfQResponseLineQty qty = m_qtys[i]; + if (qty.isActive()) + { + qty.setIsActive(false); + qty.save(); + } + } + } + return success; + } // success + +} // MRfQResponseLine diff --git a/base/src/org/compiere/model/MRfQResponseLineQty.java b/base/src/org/compiere/model/MRfQResponseLineQty.java new file mode 100644 index 0000000000..496b0e0443 --- /dev/null +++ b/base/src/org/compiere/model/MRfQResponseLineQty.java @@ -0,0 +1,240 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * RfQ Response Line Qty + * + * @author Jorg Janke + * @version $Id: MRfQResponseLineQty.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MRfQResponseLineQty extends X_C_RfQResponseLineQty implements Comparator +{ + /** + * Persistency Constructor + * @param ctx context + * @param C_RfQResponseLineQty_ID id + * @param trxName transaction + */ + public MRfQResponseLineQty (Properties ctx, int C_RfQResponseLineQty_ID, String trxName) + { + super (ctx, C_RfQResponseLineQty_ID, trxName); + if (C_RfQResponseLineQty_ID == 0) + { + // setC_RfQResponseLineQty_ID (0); // PK + // setC_RfQLineQty_ID (0); + // setC_RfQResponseLine_ID (0); + // + setPrice (Env.ZERO); + setDiscount(Env.ZERO); + } + + } // MRfQResponseLineQty + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MRfQResponseLineQty (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRfQResponseLineQty + + /** + * Parent Constructor + * @param line line + * @param qty qty + */ + public MRfQResponseLineQty (MRfQResponseLine line, MRfQLineQty qty) + { + this (line.getCtx(), 0, line.get_TrxName()); + setClientOrg(line); + setC_RfQResponseLine_ID (line.getC_RfQResponseLine_ID()); + setC_RfQLineQty_ID (qty.getC_RfQLineQty_ID()); + } // MRfQResponseLineQty + + + /** RfQ Line Qty */ + private MRfQLineQty m_rfqQty = null; + /** 100 */ + private static BigDecimal ONEHUNDRED = new BigDecimal (100); + + /** + * Get RfQ Line Qty + * @return RfQ Line Qty + */ + public MRfQLineQty getRfQLineQty() + { + if (m_rfqQty == null) + m_rfqQty = MRfQLineQty.get (getCtx(), getC_RfQLineQty_ID(), get_TrxName()); + return m_rfqQty; + } // getRfQLineQty + + + /** + * Is the Amount (price - discount) Valid + * @return true if valid + */ + public boolean isValidAmt() + { + BigDecimal price = getPrice(); + if (price == null || Env.ZERO.compareTo(price) == 0) + { + log.warning("No Price - " + price); + return false; + } + BigDecimal discount = getDiscount(); + if (discount != null) + { + if (discount.abs().compareTo(ONEHUNDRED) > 0) + { + log.warning("Discount > 100 - " + discount); + return false; + } + } + BigDecimal net = getNetAmt(); + if (net == null) + { + log.warning("Net is null"); + return false; + } + if (net.compareTo(Env.ZERO) <= 0) + { + log.warning("Net <= 0 - " + net); + return false; + } + return true; + } // isValidAmt + + /** + * Get Net Amt (price minus discount in %) + * @return net amount or null + */ + public BigDecimal getNetAmt() + { + BigDecimal price = getPrice(); + if (price == null || Env.ZERO.compareTo(price) == 0) + return null; + // + BigDecimal discount = getDiscount(); + if (discount == null || Env.ZERO.compareTo(discount) == 0) + return price; + // Calculate + // double result = price.doubleValue() * (100.0 - discount.doubleValue()) / 100.0; + BigDecimal factor = ONEHUNDRED.subtract(discount); + return price.multiply(factor).divide(ONEHUNDRED, 2, BigDecimal.ROUND_HALF_UP); + } // getNetAmt + + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MRfQResponseLineQty["); + sb.append(get_ID()).append(",Rank=").append(getRanking()) + .append(",Price=").append(getPrice()) + .append(",Discount=").append(getDiscount()) + .append(",Net=").append(getNetAmt()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Compare based on net amount + * @param o1 the first object to be compared. + * @param o2 the second object to be compared. + * @return a negative integer, zero, or a positive integer as the + * first argument is less than, equal to, or greater than the + * second. + * @throws ClassCastException if the arguments' types prevent them from + * being compared by this Comparator. + */ + public int compare(Object o1, Object o2) + { + if (o1 == null) + throw new IllegalArgumentException("o1 = null"); + if (o2 == null) + throw new IllegalArgumentException("o2 = null"); + MRfQResponseLineQty q1 = null; + MRfQResponseLineQty q2 = null; + if (o1 instanceof MRfQResponseLineQty) + q1 = (MRfQResponseLineQty)o1; + else + throw new ClassCastException("o1"); + if (o2 instanceof MRfQResponseLineQty) + q2 = (MRfQResponseLineQty)o2; + else + throw new ClassCastException("o2"); + // + if (!q1.isValidAmt()) + return -99; + if (!q2.isValidAmt()) + return +99; + BigDecimal net1 = q1.getNetAmt(); + if (net1 == null) + return -9; + BigDecimal net2 = q2.getNetAmt(); + if (net2 == null) + return +9; + return net1.compareTo(net2); + } // compare + + /** + * Is Net Amount equal ? + * @param obj the reference object with which to compare. + * @return true if Net Amount equal + */ + public boolean equals(Object obj) + { + if (obj instanceof MRfQResponseLineQty) + { + MRfQResponseLineQty cmp = (MRfQResponseLineQty)obj; + if (!cmp.isValidAmt() || !isValidAmt()) + return false; + BigDecimal cmpNet = cmp.getNetAmt(); + if (cmpNet == null) + return false; + BigDecimal net = cmp.getNetAmt(); + if (net == null) + return false; + return cmpNet.compareTo(net) == 0; + } + return false; + } // equals + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (!isActive()) + setRanking(999); + return true; + } // beforeSave + +} // MRfQResponseLineQty diff --git a/base/src/org/compiere/model/MRfQTopic.java b/base/src/org/compiere/model/MRfQTopic.java new file mode 100644 index 0000000000..aaf1fbd895 --- /dev/null +++ b/base/src/org/compiere/model/MRfQTopic.java @@ -0,0 +1,98 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * RfQ Topic Model + * + * @author Jorg Janke + * @version $Id: MRfQTopic.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MRfQTopic extends X_C_RfQ_Topic +{ + /** + * Standard Constructor + * @param ctx context + * @param C_RfQ_Topic_ID id + * @param trxName transaction + */ + public MRfQTopic (Properties ctx, int C_RfQ_Topic_ID, String trxName) + { + super (ctx, C_RfQ_Topic_ID, trxName); + } // MRfQTopic + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MRfQTopic (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRfQTopic + + /** + * Get Current Topic Subscribers + * @return array subscribers + */ + public MRfQTopicSubscriber[] getSubscribers() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_RfQ_TopicSubscriber " + + "WHERE C_RfQ_Topic_ID=? AND IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_RfQ_Topic_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MRfQTopicSubscriber (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getSubscribers", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + MRfQTopicSubscriber[] retValue = new MRfQTopicSubscriber[list.size ()]; + list.toArray (retValue); + return retValue; + } // getSubscribers + +} // MRfQTopic + diff --git a/base/src/org/compiere/model/MRfQTopicSubscriber.java b/base/src/org/compiere/model/MRfQTopicSubscriber.java new file mode 100644 index 0000000000..950f6f22c6 --- /dev/null +++ b/base/src/org/compiere/model/MRfQTopicSubscriber.java @@ -0,0 +1,131 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * RfQ Topic Subscriber Model + * + * @author Jorg Janke + * @version $Id: MRfQTopicSubscriber.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MRfQTopicSubscriber extends X_C_RfQ_TopicSubscriber +{ + /** + * Standard Constructor + * @param ctx context + * @param C_RfQ_TopicSubscriber_ID id + * @param trxName transaction + */ + public MRfQTopicSubscriber (Properties ctx, int C_RfQ_TopicSubscriber_ID, String trxName) + { + super (ctx, C_RfQ_TopicSubscriber_ID, trxName); + } // MRfQTopic_Subscriber + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MRfQTopicSubscriber (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRfQTopic_Subscriber + + /** Restrictions */ + private MRfQTopicSubscriberOnly[] m_restrictions = null; + + /** + * Get Restriction Records + * @param requery requery + * @return arry of onlys + */ + public MRfQTopicSubscriberOnly[] getRestrictions (boolean requery) + { + if (m_restrictions != null && !requery) + return m_restrictions; + + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_RfQ_TopicSubscriberOnly WHERE C_RfQ_TopicSubscriber_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_RfQ_TopicSubscriber_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MRfQTopicSubscriberOnly(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + m_restrictions = new MRfQTopicSubscriberOnly[list.size ()]; + list.toArray (m_restrictions); + return m_restrictions; + } // getRestrictions + + + /** + * Is the product included? + * @param M_Product_ID product + * @return true if no restrictions or included in "positive" only list + */ + public boolean isIncluded (int M_Product_ID) + { + // No restrictions + if (getRestrictions(false).length == 0) + return true; + + for (int i = 0; i < m_restrictions.length; i++) + { + MRfQTopicSubscriberOnly restriction = m_restrictions[i]; + if (!restriction.isActive()) + continue; + // Product + if (restriction.getM_Product_ID() == M_Product_ID) + return true; + // Product Category + if (MProductCategory.isCategory(restriction.getM_Product_Category_ID(), M_Product_ID)) + return true; + } + // must be on "positive" list + return false; + } // isIncluded + +} // MRfQTopicSubscriber diff --git a/base/src/org/compiere/model/MRfQTopicSubscriberOnly.java b/base/src/org/compiere/model/MRfQTopicSubscriberOnly.java new file mode 100644 index 0000000000..70e0005994 --- /dev/null +++ b/base/src/org/compiere/model/MRfQTopicSubscriberOnly.java @@ -0,0 +1,54 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Subcriber Topic Only List (positive - i.e. must be a match if exists) + * + * @author Jorg Janke + * @version $Id: MRfQTopicSubscriberOnly.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MRfQTopicSubscriberOnly extends X_C_RfQ_TopicSubscriberOnly +{ + + /** + * Standard Constructor + * @param ctx context + * @param C_RfQ_TopicSubscriberOnly_ID id + * @param trxName transaction + */ + public MRfQTopicSubscriberOnly (Properties ctx, int C_RfQ_TopicSubscriberOnly_ID, String trxName) + { + super (ctx, C_RfQ_TopicSubscriberOnly_ID, trxName); + } // MRfQTopicSubscriberOnly + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MRfQTopicSubscriberOnly (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MRfQTopicSubscriberOnly + +} // MRfQTopicSubscriberOnly diff --git a/base/src/org/compiere/model/MSLACriteria.java b/base/src/org/compiere/model/MSLACriteria.java new file mode 100644 index 0000000000..ec9c3a464f --- /dev/null +++ b/base/src/org/compiere/model/MSLACriteria.java @@ -0,0 +1,142 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import org.compiere.sla.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Service Level Agreement Criteria Model + * + * @author Jorg Janke + * @version $Id: MSLACriteria.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MSLACriteria extends X_PA_SLA_Criteria +{ + /** + * Get MSLACriteria from Cache + * @param ctx context + * @param PA_SLA_Criteria_ID id + * @param trxName transaction + * @return MSLACriteria + */ + public static MSLACriteria get (Properties ctx, int PA_SLA_Criteria_ID, String trxName) + { + Integer key = new Integer (PA_SLA_Criteria_ID); + MSLACriteria retValue = (MSLACriteria) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MSLACriteria (ctx, PA_SLA_Criteria_ID, trxName); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("PA_SLA_Criteria", 20); + + + /** + * Standard Constructor + * @param ctx context + * @param PA_SLA_Criteria_ID id + * @param trxName transaction + */ + public MSLACriteria (Properties ctx, int PA_SLA_Criteria_ID, String trxName) + { + super (ctx, PA_SLA_Criteria_ID, trxName); + } // MSLACriteria + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MSLACriteria (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MSLACriteria + + /** + * Get Goals of Criteria + * @return array of Goals + */ + public MSLAGoal[] getGoals() + { + String sql = "SELECT * FROM PA_SLA_Goal " + + "WHERE PA_SLA_Criteria_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getPA_SLA_Criteria_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MSLAGoal(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MSLAGoal[] retValue = new MSLAGoal[list.size ()]; + list.toArray (retValue); + return retValue; + } // getGoals + + + /** + * Create New Instance of SLA Criteria + * @return instanciated class + * @throws Exception + */ + public SLACriteria newInstance() throws Exception + { + if (getClassname() == null || getClassname().length() == 0) + throw new AdempiereSystemError("No SLA Criteria Classname"); + + try + { + Class clazz = Class.forName(getClassname()); + SLACriteria retValue = (SLACriteria)clazz.newInstance(); + return retValue; + } + catch (Exception e) + { + throw new AdempiereSystemError("Could not intsnciate SLA Criteria", e); + } + } // newInstance + +} // MSLACriteria diff --git a/base/src/org/compiere/model/MSLAGoal.java b/base/src/org/compiere/model/MSLAGoal.java new file mode 100644 index 0000000000..d772085570 --- /dev/null +++ b/base/src/org/compiere/model/MSLAGoal.java @@ -0,0 +1,142 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Service Level Agreement Goals + * + * @author Jorg Janke + * @version $Id: MSLAGoal.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MSLAGoal extends X_PA_SLA_Goal +{ + + /** + * Standard Constructor + * @param ctx context + * @param PA_SLA_Goal_ID id + * @param trxName transaction + */ + public MSLAGoal (Properties ctx, int PA_SLA_Goal_ID, String trxName) + { + super (ctx, PA_SLA_Goal_ID, trxName); + if (PA_SLA_Goal_ID == 0) + { + setMeasureActual (Env.ZERO); + setMeasureTarget (Env.ZERO); + setProcessed (false); + } + } // MSLAGoal + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MSLAGoal (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MSLAGoal + + /** + * Get All Measures + * @return array of measures + */ + public MSLAMeasure[] getAllMeasures() + { + String sql = "SELECT * FROM PA_SLA_Measure " + + "WHERE PA_SLA_Goal_ID=? " + + "ORDER BY DateTrx"; + return getMeasures (sql); + } // getAllMeasures + + /** + * Get New Measures only + * @return array of unprocessed Measures + */ + public MSLAMeasure[] getNewMeasures() + { + String sql = "SELECT * FROM PA_SLA_Measure " + + "WHERE PA_SLA_Goal_ID=?" + + " AND Processed='N' " + + "ORDER BY DateTrx"; + return getMeasures (sql); + } // getNewMeasures + + /** + * Get Measures + * @param sql sql + * @return array of measures + */ + private MSLAMeasure[] getMeasures (String sql) + { + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getPA_SLA_Goal_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MSLAMeasure(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MSLAMeasure[] retValue = new MSLAMeasure[list.size ()]; + list.toArray (retValue); + return retValue; + } // getMeasures + + /** + * Is the Date in the Valid Range + * @param date date + * @return true if valid + */ + public boolean isDateValid (Timestamp date) + { + if (date == null) + return false; + if (getValidFrom() != null && date.before(getValidFrom())) + return false; + if (getValidTo() != null && date.after(getValidTo())) + return false; + return true; + } // isDateValid + +} // MSLAGoal diff --git a/base/src/org/compiere/model/MSLAMeasure.java b/base/src/org/compiere/model/MSLAMeasure.java new file mode 100644 index 0000000000..a2d46ba810 --- /dev/null +++ b/base/src/org/compiere/model/MSLAMeasure.java @@ -0,0 +1,112 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Service Level Agreement Measure + * + * @author Jorg Janke + * @version $Id: MSLAMeasure.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MSLAMeasure extends X_PA_SLA_Measure +{ + + /** + * Standard Constructor + * @param ctx context + * @param PA_SLA_Measure_ID id + * @param trxName transaction + */ + public MSLAMeasure (Properties ctx, int PA_SLA_Measure_ID, String trxName) + { + super (ctx, PA_SLA_Measure_ID, trxName); + if (PA_SLA_Measure_ID == 0) + { + // setPA_SLA_Goal_ID (0); + setDateTrx (new Timestamp(System.currentTimeMillis())); + setMeasureActual (Env.ZERO); + setProcessed (false); + } + } // MSLAMeasure + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MSLAMeasure (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MSLAMeasure + + /** + * Parent Constructor + * @param goal parent + * @param DateTrx optional date + * @param MeasureActual optional measure + * @param Description optional description + */ + public MSLAMeasure (MSLAGoal goal, Timestamp DateTrx, BigDecimal MeasureActual, + String Description) + { + super (goal.getCtx(), 0, goal.get_TrxName()); + setClientOrg(goal); + setPA_SLA_Goal_ID(goal.getPA_SLA_Goal_ID()); + if (DateTrx != null) + setDateTrx (DateTrx); + else + setDateTrx (new Timestamp(System.currentTimeMillis())); + if (MeasureActual != null) + setMeasureActual(MeasureActual); + else + setMeasureActual (Env.ZERO); + if (Description != null) + setDescription(Description); + } // MSLAMeasure + + /** + * Set Link to Source + * @param AD_Table_ID table + * @param Record_ID record + */ + public void setLink (int AD_Table_ID, int Record_ID) + { + setAD_Table_ID(AD_Table_ID); + setRecord_ID(Record_ID); + } // setLink + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MSLAMeasure["); + sb.append(get_ID()).append("-PA_SLA_Goal_ID=").append(getPA_SLA_Goal_ID()) + .append(",").append(getDateTrx()) + .append(",Actual=").append(getMeasureActual()) + .append ("]"); + return sb.toString (); + } // toString + +} // MSLAMeasure diff --git a/base/src/org/compiere/model/MScheduler.java b/base/src/org/compiere/model/MScheduler.java new file mode 100644 index 0000000000..848c4aa74a --- /dev/null +++ b/base/src/org/compiere/model/MScheduler.java @@ -0,0 +1,374 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Scheduler Model + * + * @author Jorg Janke + * @version $Id: MScheduler.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MScheduler extends X_AD_Scheduler + implements AdempiereProcessor +{ + /** + * Get Active + * @param ctx context + * @return active processors + */ + public static MScheduler[] getActive (Properties ctx) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM AD_Scheduler WHERE IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MScheduler (ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MScheduler[] retValue = new MScheduler[list.size ()]; + list.toArray (retValue); + return retValue; + } // getActive + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MScheduler.class); + + + /** + * Standard Constructor + * @param ctx context + * @param AD_Scheduler_ID id + * @param trxName transaction + */ + public MScheduler (Properties ctx, int AD_Scheduler_ID, String trxName) + { + super (ctx, AD_Scheduler_ID, trxName); + if (AD_Scheduler_ID == 0) + { + // setAD_Process_ID (0); + // setName (null); + setScheduleType (SCHEDULETYPE_Frequency); // F + setFrequencyType (FREQUENCYTYPE_Day); + // setFrequency (1); + // setMonthDay(1); + // setWeekDay(WEEKDAY_Monday); + // + setKeepLogDays (7); + // setSupervisor_ID (0); + } + } // MScheduler + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MScheduler (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MScheduler + + /** Process Parameter */ + private MSchedulerPara[] m_parameter = null; + /** Process Recipients */ + private MSchedulerRecipient[] m_recipients = null; + + /** + * Get Server ID + * @return id + */ + public String getServerID () + { + return "Scheduler" + get_ID(); + } // getServerID + + /** + * Get Date Next Run + * @param requery requery + * @return date next run + */ + public Timestamp getDateNextRun (boolean requery) + { + if (requery) + load(get_TrxName()); + return getDateNextRun(); + } // getDateNextRun + + /** + * Get Logs + * @return logs + */ + public AdempiereProcessorLog[] getLogs () + { + ArrayList list = new ArrayList(); + String sql = "SELECT * " + + "FROM AD_SchedulerLog " + + "WHERE AD_Scheduler_ID=? " + + "ORDER BY Created DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getAD_Scheduler_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MSchedulerLog (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MSchedulerLog[] retValue = new MSchedulerLog[list.size ()]; + list.toArray (retValue); + return retValue; + } // getLogs + + /** + * Delete old Request Log + * @return number of records + */ + public int deleteLog() + { + if (getKeepLogDays() < 1) + return 0; + String sql = "DELETE AD_SchedulerLog " + + "WHERE AD_Scheduler_ID=" + getAD_Scheduler_ID() + + " AND (Created+" + getKeepLogDays() + ") < SysDate"; + int no = DB.executeUpdate(sql, get_TrxName()); + return no; + } // deleteLog + + /** + * Get Process + * @return process + */ + public MProcess getProcess() + { + return MProcess.get(getCtx(), getAD_Process_ID()); + } // getProcess + + /** + * Get Parameters + * @param reload reload + * @return parameter + */ + public MSchedulerPara[] getParameters (boolean reload) + { + if (!reload && m_parameter != null) + return m_parameter; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM AD_Scheduler_Para WHERE AD_Scheduler_ID=? AND IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getAD_Scheduler_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MSchedulerPara (getCtx(), rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_parameter = new MSchedulerPara[list.size()]; + list.toArray(m_parameter); + return m_parameter; + } // getParameter + + /** + * Get Recipients + * @param reload reload + * @return Recipients + */ + public MSchedulerRecipient[] getRecipients (boolean reload) + { + if (!reload && m_recipients != null) + return m_recipients; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM AD_SchedulerRecipient WHERE AD_Scheduler_ID=? AND IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getAD_Scheduler_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MSchedulerRecipient (getCtx(), rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_recipients = new MSchedulerRecipient[list.size()]; + list.toArray(m_recipients); + return m_recipients; + } // getRecipients + + /** + * Get Recipient AD_User_IDs + * @return array of user IDs + */ + public Integer[] getRecipientAD_User_IDs() + { + ArrayList list = new ArrayList(); + MSchedulerRecipient[] recipients = getRecipients(false); + for (int i = 0; i < recipients.length; i++) + { + MSchedulerRecipient recipient = recipients[i]; + if (!recipient.isActive()) + continue; + if (recipient.getAD_User_ID() != 0) + { + Integer ii = new Integer(recipient.getAD_User_ID()); + if (!list.contains(ii)) + list.add(ii); + } + if (recipient.getAD_Role_ID() != 0) + { + MUserRoles[] urs = MUserRoles.getOfRole(getCtx(), recipient.getAD_Role_ID()); + for (int j = 0; j < urs.length; j++) + { + MUserRoles ur = urs[j]; + if (!ur.isActive()) + continue; + Integer ii = new Integer(ur.getAD_User_ID()); + if (!list.contains(ii)) + list.add(ii); + } + } + } + // Add Updater + if (list.size() == 0) + { + Integer ii = new Integer(getUpdatedBy()); + list.add(ii); + } + // + Integer[] recipientIDs = new Integer[list.size()]; + list.toArray(recipientIDs); + return recipientIDs; + } // getRecipientAD_User_IDs + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave(boolean newRecord) + { + // Set Schedule Type & Frequencies + if (SCHEDULETYPE_Frequency.equals(getScheduleType())) + { + if (getFrequencyType() == null) + setFrequencyType(FREQUENCYTYPE_Day); + if (getFrequency() < 1) + setFrequency(1); + } + else if (SCHEDULETYPE_MonthDay.equals(getScheduleType())) + { + if (getMonthDay() < 1 || getMonthDay() > 31) + setMonthDay(1); + } + else // SCHEDULETYPE_WeekDay + { + if (getScheduleType() == null) + setScheduleType(SCHEDULETYPE_WeekDay); + if (getWeekDay() == null) + setWeekDay(WEEKDAY_Monday); + } + return true; + } // beforeSave + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MScheduler["); + sb.append (get_ID ()).append ("-").append (getName()).append ("]"); + return sb.toString (); + } // toString + +} // MScheduler diff --git a/base/src/org/compiere/model/MSchedulerLog.java b/base/src/org/compiere/model/MSchedulerLog.java new file mode 100644 index 0000000000..784ffc11f5 --- /dev/null +++ b/base/src/org/compiere/model/MSchedulerLog.java @@ -0,0 +1,67 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Scheduler Log + * + * @author Jorg Janke + * @version $Id: MSchedulerLog.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MSchedulerLog extends X_AD_SchedulerLog + implements AdempiereProcessorLog +{ + /** + * Standard Constructor + * @param ctx context + * @param AD_SchedulerLog_ID id + * @param trxName transaction + */ + public MSchedulerLog (Properties ctx, int AD_SchedulerLog_ID, String trxName) + { + super (ctx, AD_SchedulerLog_ID, trxName); + } // MSchedulerLog + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MSchedulerLog (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MSchedulerLog + + /** + * Parent Constructor + * @param parent parent + * @param summary summary + */ + public MSchedulerLog (MScheduler parent, String summary) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setAD_Scheduler_ID(parent.getAD_Scheduler_ID()); + setSummary(summary); + } // MSchedulerLog + +} // MSchedulerLog diff --git a/base/src/org/compiere/model/MSchedulerPara.java b/base/src/org/compiere/model/MSchedulerPara.java new file mode 100644 index 0000000000..bf39801390 --- /dev/null +++ b/base/src/org/compiere/model/MSchedulerPara.java @@ -0,0 +1,91 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Scheduler Parameter Model + * + * @author Jorg Janke + * @version $Id: MSchedulerPara.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MSchedulerPara extends X_AD_Scheduler_Para +{ + /** + * Standard Constructor + * @param ctx context + * @param AD_Scheduler_Para_ID id + * @param trxName transaction + */ + public MSchedulerPara (Properties ctx, int AD_Scheduler_Para_ID, + String trxName) + { + super (ctx, AD_Scheduler_Para_ID, trxName); + } // MSchedulerPara + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MSchedulerPara (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MSchedulerPara + + /** Parameter Column Name */ + private MProcessPara m_parameter = null; + + /** + * Get Parameter Column Name + * @return column name + */ + public String getColumnName() + { + if (m_parameter == null) + m_parameter = MProcessPara.get(getCtx(), getAD_Process_Para_ID()); + return m_parameter.getColumnName(); + } // getColumnName + + /** + * Get Display Type + * @return display type + */ + public int getDisplayType() + { + if (m_parameter == null) + m_parameter = MProcessPara.get(getCtx(), getAD_Process_Para_ID()); + return m_parameter.getAD_Reference_ID(); + } // getDisplayType + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("MSchedulerPara["); + sb.append(get_ID()).append("-") + .append(getColumnName()).append("=").append(getParameterDefault()) + .append("]"); + return sb.toString(); + } // toString + +} // MSchedulerPara diff --git a/base/src/org/compiere/model/MSchedulerRecipient.java b/base/src/org/compiere/model/MSchedulerRecipient.java new file mode 100644 index 0000000000..125c3c65e3 --- /dev/null +++ b/base/src/org/compiere/model/MSchedulerRecipient.java @@ -0,0 +1,53 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Scheduler Recipient Model + * + * @author Jorg Janke + * @version $Id: MSchedulerRecipient.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MSchedulerRecipient extends X_AD_SchedulerRecipient +{ + /** + * Standard Constructor + * @param ctx context + * @param AD_SchedulerRecipient_ID id + * @param trxName transaction + */ + public MSchedulerRecipient (Properties ctx, int AD_SchedulerRecipient_ID, + String trxName) + { + super (ctx, AD_SchedulerRecipient_ID, trxName); + } // MSchedulerRecipient + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MSchedulerRecipient (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MSchedulerRecipient + +} // MSchedulerRecipient diff --git a/base/src/org/compiere/model/MSerNoCtl.java b/base/src/org/compiere/model/MSerNoCtl.java new file mode 100644 index 0000000000..5ae1305dcd --- /dev/null +++ b/base/src/org/compiere/model/MSerNoCtl.java @@ -0,0 +1,81 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.ResultSet; +import java.util.Properties; + +/** + * Serial Number Control Model + * + * @author Jorg Janke + * @version $Id: MSerNoCtl.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MSerNoCtl extends X_M_SerNoCtl +{ + /** + * Standard Constructor + * @param ctx context + * @param M_SerNoCtl_ID id + * @param trxName transaction + */ + public MSerNoCtl(Properties ctx, int M_SerNoCtl_ID, String trxName) + { + super(ctx, M_SerNoCtl_ID, trxName); + if (M_SerNoCtl_ID == 0) + { + // setM_SerNoCtl_ID (0); + setStartNo (1); + setCurrentNext (1); + setIncrementNo (1); + // setName (null); + } + } // MSerNoCtl + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MSerNoCtl(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MSerNoCtl + + /** + * Create new Lot. + * Increments Current Next and Commits + * @return saved Lot + */ + public String createSerNo () + { + StringBuffer name = new StringBuffer(); + if (getPrefix() != null) + name.append(getPrefix()); + int no = getCurrentNext(); + name.append(no); + if (getSuffix() != null) + name.append(getSuffix()); + // + no += getIncrementNo(); + setCurrentNext(no); + save(); + return name.toString(); + } // createSerNo + +} // MSerNoCtl diff --git a/base/src/org/compiere/model/MSetup.java b/base/src/org/compiere/model/MSetup.java new file mode 100644 index 0000000000..bbbe69dbac --- /dev/null +++ b/base/src/org/compiere/model/MSetup.java @@ -0,0 +1,1389 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Initial Setup Model + * + * @author Jorg Janke + * @version $Id: MSetup.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public final class MSetup +{ + /** + * Constructor + * @param ctx context + * @param WindowNo window + */ + public MSetup(Properties ctx, int WindowNo) + { + m_ctx = new Properties(ctx); // copy + m_lang = Env.getAD_Language(m_ctx); + m_WindowNo = WindowNo; + } // MSetup + + /** Logger */ + protected CLogger log = CLogger.getCLogger(getClass()); + + private Trx m_trx = Trx.get(Trx.createTrxName("Setup"), true); + private Properties m_ctx; + private String m_lang; + private int m_WindowNo; + private StringBuffer m_info; + // + private String m_clientName; +// private String m_orgName; + // + private String m_stdColumns = "AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy"; + private String m_stdValues; + private String m_stdValuesOrg; + // + private NaturalAccountMap m_nap = null; + // + private MClient m_client; + private MOrg m_org; + private MAcctSchema m_as; + // + private int AD_User_ID; + private String AD_User_Name; + private int AD_User_U_ID; + private String AD_User_U_Name; + private MCalendar m_calendar; + private int m_AD_Tree_Account_ID; + private int C_Cycle_ID; + // + private boolean m_hasProject = false; + private boolean m_hasMCampaign = false; + private boolean m_hasSRegion = false; + /** Account Creation OK */ + private boolean m_accountsOK = false; + + /** + * Create Client Info. + * - Client, Trees, Org, Role, User, User_Role + * @param clientName client name + * @param orgName org name + * @param userClient user id client + * @param userOrg user id org + * @return true if created + */ + public boolean createClient (String clientName, String orgName, + String userClient, String userOrg) + { + log.info(clientName); + m_trx.start(); + + // info header + m_info = new StringBuffer(); + // Standarc columns + String name = null; + String sql = null; + int no = 0; + + /** + * Create Client + */ + name = clientName; + if (name == null || name.length() == 0) + name = "newClient"; + m_clientName = name; + m_client = new MClient(m_ctx, 0, true, m_trx.getTrxName()); + m_client.setValue(m_clientName); + m_client.setName(m_clientName); + if (!m_client.save()) + { + String err = "Client NOT created"; + log.log(Level.SEVERE, err); + m_info.append(err); + m_trx.rollback(); + m_trx.close(); + return false; + } + int AD_Client_ID = m_client.getAD_Client_ID(); + Env.setContext(m_ctx, m_WindowNo, "AD_Client_ID", AD_Client_ID); + Env.setContext(m_ctx, "#AD_Client_ID", AD_Client_ID); + + // Standard Values + m_stdValues = String.valueOf(AD_Client_ID) + ",0,'Y',SysDate,0,SysDate,0"; + // Info - Client + m_info.append(Msg.translate(m_lang, "AD_Client_ID")).append("=").append(name).append("\n"); + + // Setup Sequences + if (!MSequence.checkClientSequences (m_ctx, AD_Client_ID, m_trx.getTrxName())) + { + String err = "Sequences NOT created"; + log.log(Level.SEVERE, err); + m_info.append(err); + m_trx.rollback(); + m_trx.close(); + return false; + } + + // Trees and Client Info + if (!m_client.setupClientInfo(m_lang)) + { + String err = "Client Info NOT created"; + log.log(Level.SEVERE, err); + m_info.append(err); + m_trx.rollback(); + m_trx.close(); + return false; + } + m_AD_Tree_Account_ID = m_client.getSetup_AD_Tree_Account_ID(); + + /** + * Create Org + */ + name = orgName; + if (name == null || name.length() == 0) + name = "newOrg"; + m_org = new MOrg (m_client, name); + if (!m_org.save()) + { + String err = "Organization NOT created"; + log.log(Level.SEVERE, err); + m_info.append(err); + m_trx.rollback(); + m_trx.close(); + return false; + } + Env.setContext(m_ctx, m_WindowNo, "AD_Org_ID", getAD_Org_ID()); + Env.setContext(m_ctx, "#AD_Org_ID", getAD_Org_ID()); + m_stdValuesOrg = AD_Client_ID + "," + getAD_Org_ID() + ",'Y',SysDate,0,SysDate,0"; + // Info + m_info.append(Msg.translate(m_lang, "AD_Org_ID")).append("=").append(name).append("\n"); + + /** + * Create Roles + * - Admin + * - User + */ + name = m_clientName + " Admin"; + MRole admin = new MRole(m_ctx, 0, m_trx.getTrxName()); + admin.setClientOrg(m_client); + admin.setName(name); + admin.setUserLevel(MRole.USERLEVEL_ClientPlusOrganization); + admin.setPreferenceType(MRole.PREFERENCETYPE_Client); + admin.setIsShowAcct(true); + if (!admin.save()) + { + String err = "Admin Role A NOT inserted"; + log.log(Level.SEVERE, err); + m_info.append(err); + m_trx.rollback(); + m_trx.close(); + return false; + } + // OrgAccess x, 0 + MRoleOrgAccess adminClientAccess = new MRoleOrgAccess (admin, 0); + if (!adminClientAccess.save()) + log.log(Level.SEVERE, "Admin Role_OrgAccess 0 NOT created"); + // OrgAccess x,y + MRoleOrgAccess adminOrgAccess = new MRoleOrgAccess (admin, m_org.getAD_Org_ID()); + if (!adminOrgAccess.save()) + log.log(Level.SEVERE, "Admin Role_OrgAccess NOT created"); + + // Info - Admin Role + m_info.append(Msg.translate(m_lang, "AD_Role_ID")).append("=").append(name).append("\n"); + + // + name = m_clientName + " User"; + MRole user = new MRole (m_ctx, 0, m_trx.getTrxName()); + user.setClientOrg(m_client); + user.setName(name); + if (!user.save()) + { + String err = "User Role A NOT inserted"; + log.log(Level.SEVERE, err); + m_info.append(err); + m_trx.rollback(); + m_trx.close(); + return false; + } + // OrgAccess x,y + MRoleOrgAccess userOrgAccess = new MRoleOrgAccess (user, m_org.getAD_Org_ID()); + if (!userOrgAccess.save()) + log.log(Level.SEVERE, "User Role_OrgAccess NOT created"); + + // Info - Client Role + m_info.append(Msg.translate(m_lang, "AD_Role_ID")).append("=").append(name).append("\n"); + + /** + * Create Users + * - Client + * - Org + */ + name = userClient; + if (name == null || name.length() == 0) + name = m_clientName + "Client"; + AD_User_ID = getNextID(AD_Client_ID, "AD_User"); + AD_User_Name = name; + name = DB.TO_STRING(name); + sql = "INSERT INTO AD_User(" + m_stdColumns + ",AD_User_ID," + + "Name,Description,Password)" + + " VALUES (" + m_stdValues + "," + AD_User_ID + "," + + name + "," + name + "," + name + ")"; + no = DB.executeUpdate(sql, m_trx.getTrxName()); + if (no != 1) + { + String err = "Admin User NOT inserted - " + AD_User_Name; + log.log(Level.SEVERE, err); + m_info.append(err); + m_trx.rollback(); + m_trx.close(); + return false; + } + // Info + m_info.append(Msg.translate(m_lang, "AD_User_ID")).append("=").append(AD_User_Name).append("/").append(AD_User_Name).append("\n"); + + name = userOrg; + if (name == null || name.length() == 0) + name = m_clientName + "Org"; + AD_User_U_ID = getNextID(AD_Client_ID, "AD_User"); + AD_User_U_Name = name; + name = DB.TO_STRING(name); + sql = "INSERT INTO AD_User(" + m_stdColumns + ",AD_User_ID," + + "Name,Description,Password)" + + " VALUES (" + m_stdValues + "," + AD_User_U_ID + "," + + name + "," + name + "," + name + ")"; + no = DB.executeUpdate(sql, m_trx.getTrxName()); + if (no != 1) + { + String err = "Org User NOT inserted - " + AD_User_U_Name; + log.log(Level.SEVERE, err); + m_info.append(err); + m_trx.rollback(); + m_trx.close(); + return false; + } + // Info + m_info.append(Msg.translate(m_lang, "AD_User_ID")).append("=").append(AD_User_U_Name).append("/").append(AD_User_U_Name).append("\n"); + + /** + * Create User-Role + */ + // ClientUser - Admin & User + sql = "INSERT INTO AD_User_Roles(" + m_stdColumns + ",AD_User_ID,AD_Role_ID)" + + " VALUES (" + m_stdValues + "," + AD_User_ID + "," + admin.getAD_Role_ID() + ")"; + no = DB.executeUpdate(sql, m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "UserRole ClientUser+Admin NOT inserted"); + sql = "INSERT INTO AD_User_Roles(" + m_stdColumns + ",AD_User_ID,AD_Role_ID)" + + " VALUES (" + m_stdValues + "," + AD_User_ID + "," + user.getAD_Role_ID() + ")"; + no = DB.executeUpdate(sql, m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "UserRole ClientUser+User NOT inserted"); + // OrgUser - User + sql = "INSERT INTO AD_User_Roles(" + m_stdColumns + ",AD_User_ID,AD_Role_ID)" + + " VALUES (" + m_stdValues + "," + AD_User_U_ID + "," + user.getAD_Role_ID() + ")"; + no = DB.executeUpdate(sql, m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "UserRole OrgUser+Org NOT inserted"); + + // Processors + MAcctProcessor ap = new MAcctProcessor(m_client, AD_User_ID); + ap.save(); + + MRequestProcessor rp = new MRequestProcessor (m_client, AD_User_ID); + rp.save(); + + log.info("fini"); + return true; + } // createClient + + + + /************************************************************************** + * Create Accounting elements. + * - Calendar + * - Account Trees + * - Account Values + * - Accounting Schema + * - Default Accounts + * + * @param currency currency + * @param hasProduct has product segment + * @param hasBPartner has bp segment + * @param hasProject has project segment + * @param hasMCampaign has campaign segment + * @param hasSRegion has sales region segment + * @param AccountingFile file name of accounting file + * @return true if created + */ + public boolean createAccounting(KeyNamePair currency, + boolean hasProduct, boolean hasBPartner, boolean hasProject, + boolean hasMCampaign, boolean hasSRegion, + File AccountingFile) + { + log.info(m_client.toString()); + // + m_hasProject = hasProject; + m_hasMCampaign = hasMCampaign; + m_hasSRegion = hasSRegion; + + // Standard variables + m_info = new StringBuffer(); + String name = null; + StringBuffer sqlCmd = null; + int no = 0; + + /** + * Create Calendar + */ + m_calendar = new MCalendar(m_client); + if (!m_calendar.save()) + { + String err = "Calendar NOT inserted"; + log.log(Level.SEVERE, err); + m_info.append(err); + m_trx.rollback(); + m_trx.close(); + return false; + } + // Info + m_info.append(Msg.translate(m_lang, "C_Calendar_ID")).append("=").append(m_calendar.getName()).append("\n"); + + if (m_calendar.createYear(m_client.getLocale()) == null) + log.log(Level.SEVERE, "Year NOT inserted"); + + // Create Account Elements + name = m_clientName + " " + Msg.translate(m_lang, "Account_ID"); + MElement element = new MElement (m_client, name, + MElement.ELEMENTTYPE_Account, m_AD_Tree_Account_ID); + if (!element.save()) + { + String err = "Acct Element NOT inserted"; + log.log(Level.SEVERE, err); + m_info.append(err); + m_trx.rollback(); + m_trx.close(); + return false; + } + int C_Element_ID = element.getC_Element_ID(); + m_info.append(Msg.translate(m_lang, "C_Element_ID")).append("=").append(name).append("\n"); + + // Create Account Values + m_nap = new NaturalAccountMap(m_ctx, m_trx.getTrxName()); + String errMsg = m_nap.parseFile(AccountingFile); + if (errMsg.length() != 0) + { + log.log(Level.SEVERE, errMsg); + m_info.append(errMsg); + m_trx.rollback(); + m_trx.close(); + return false; + } + if (m_nap.saveAccounts(getAD_Client_ID(), getAD_Org_ID(), C_Element_ID)) + m_info.append(Msg.translate(m_lang, "C_ElementValue_ID")).append(" # ").append(m_nap.size()).append("\n"); + else + { + String err = "Acct Element Values NOT inserted"; + log.log(Level.SEVERE, err); + m_info.append(err); + m_trx.rollback(); + m_trx.close(); + return false; + } + + int C_ElementValue_ID = m_nap.getC_ElementValue_ID("DEFAULT_ACCT"); + log.fine("C_ElementValue_ID=" + C_ElementValue_ID); + + /** + * Create AccountingSchema + */ + m_as = new MAcctSchema (m_client, currency); + if (!m_as.save()) + { + String err = "AcctSchema NOT inserted"; + log.log(Level.SEVERE, err); + m_info.append(err); + m_trx.rollback(); + m_trx.close(); + return false; + } + // Info + m_info.append(Msg.translate(m_lang, "C_AcctSchema_ID")).append("=").append(m_as.getName()).append("\n"); + + /** + * Create AccountingSchema Elements (Structure) + */ + String sql2 = null; + if (Env.isBaseLanguage(m_lang, "AD_Reference")) // Get ElementTypes & Name + sql2 = "SELECT Value, Name FROM AD_Ref_List WHERE AD_Reference_ID=181"; + else + sql2 = "SELECT l.Value, t.Name FROM AD_Ref_List l, AD_Ref_List_Trl t " + + "WHERE l.AD_Reference_ID=181 AND l.AD_Ref_List_ID=t.AD_Ref_List_ID"; + // + int Element_OO=0, Element_AC=0, Element_PR=0, Element_BP=0, Element_PJ=0, + Element_MC=0, Element_SR=0; + try + { + int AD_Client_ID = m_client.getAD_Client_ID(); + PreparedStatement stmt = DB.prepareStatement(sql2, m_trx.getTrxName()); + ResultSet rs = stmt.executeQuery(); + while (rs.next()) + { + String ElementType = rs.getString(1); + name = rs.getString(2); + // + String IsMandatory = null; + String IsBalanced = "N"; + int SeqNo = 0; + int C_AcctSchema_Element_ID = 0; + + if (ElementType.equals("OO")) + { + C_AcctSchema_Element_ID = getNextID(AD_Client_ID, "C_AcctSchema_Element"); + Element_OO = C_AcctSchema_Element_ID; + IsMandatory = "Y"; + IsBalanced = "Y"; + SeqNo = 10; + } + else if (ElementType.equals("AC")) + { + C_AcctSchema_Element_ID = getNextID(AD_Client_ID, "C_AcctSchema_Element"); + Element_AC = C_AcctSchema_Element_ID; + IsMandatory = "Y"; + SeqNo = 20; + } + else if (ElementType.equals("PR") && hasProduct) + { + C_AcctSchema_Element_ID = getNextID(AD_Client_ID, "C_AcctSchema_Element"); + Element_PR = C_AcctSchema_Element_ID; + IsMandatory = "N"; + SeqNo = 30; + } + else if (ElementType.equals("BP") && hasBPartner) + { + C_AcctSchema_Element_ID = getNextID(AD_Client_ID, "C_AcctSchema_Element"); + Element_BP = C_AcctSchema_Element_ID; + IsMandatory = "N"; + SeqNo = 40; + } + else if (ElementType.equals("PJ") && hasProject) + { + C_AcctSchema_Element_ID = getNextID(AD_Client_ID, "C_AcctSchema_Element"); + Element_PJ = C_AcctSchema_Element_ID; + IsMandatory = "N"; + SeqNo = 50; + } + else if (ElementType.equals("MC") && hasMCampaign) + { + C_AcctSchema_Element_ID = getNextID(AD_Client_ID, "C_AcctSchema_Element"); + Element_MC = C_AcctSchema_Element_ID; + IsMandatory = "N"; + SeqNo = 60; + } + else if (ElementType.equals("SR") && hasSRegion) + { + C_AcctSchema_Element_ID = getNextID(AD_Client_ID, "C_AcctSchema_Element"); + Element_SR = C_AcctSchema_Element_ID; + IsMandatory = "N"; + SeqNo = 70; + } + // Not OT, LF, LT, U1, U2, AY + + if (IsMandatory != null) + { + sqlCmd = new StringBuffer ("INSERT INTO C_AcctSchema_Element("); + sqlCmd.append(m_stdColumns).append(",C_AcctSchema_Element_ID,C_AcctSchema_ID,") + .append("ElementType,Name,SeqNo,IsMandatory,IsBalanced) VALUES ("); + sqlCmd.append(m_stdValues).append(",").append(C_AcctSchema_Element_ID).append(",").append(m_as.getC_AcctSchema_ID()).append(",") + .append("'").append(ElementType).append("','").append(name).append("',").append(SeqNo).append(",'") + .append(IsMandatory).append("','").append(IsBalanced).append("')"); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no == 1) + m_info.append(Msg.translate(m_lang, "C_AcctSchema_Element_ID")).append("=").append(name).append("\n"); + + /** Default value for mandatory elements: OO and AC */ + if (ElementType.equals("OO")) + { + sqlCmd = new StringBuffer ("UPDATE C_AcctSchema_Element SET Org_ID="); + sqlCmd.append(getAD_Org_ID()).append(" WHERE C_AcctSchema_Element_ID=").append(C_AcctSchema_Element_ID); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "Default Org in AcctSchamaElement NOT updated"); + } + if (ElementType.equals("AC")) + { + sqlCmd = new StringBuffer ("UPDATE C_AcctSchema_Element SET C_ElementValue_ID="); + sqlCmd.append(C_ElementValue_ID).append(", C_Element_ID=").append(C_Element_ID); + sqlCmd.append(" WHERE C_AcctSchema_Element_ID=").append(C_AcctSchema_Element_ID); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "Default Account in AcctSchamaElement NOT updated"); + } + } + } + rs.close(); + stmt.close(); + } + catch (SQLException e1) + { + log.log(Level.SEVERE, "Elements", e1); + m_info.append(e1.getMessage()); + m_trx.rollback(); + m_trx.close(); + return false; + } + // Create AcctSchema + + + // Create GL Accounts + m_accountsOK = true; + sqlCmd = new StringBuffer ("INSERT INTO C_AcctSCHEMA_GL ("); + sqlCmd.append(m_stdColumns).append(",C_AcctSCHEMA_ID," + + "USESUSPENSEBALANCING,SUSPENSEBALANCING_Acct," + + "USESUSPENSEERROR,SUSPENSEERROR_Acct," + + "USECURRENCYBALANCING,CURRENCYBALANCING_Acct," + + "RETAINEDEARNING_Acct,INCOMESUMMARY_Acct," + + "INTERCOMPANYDUETO_Acct,INTERCOMPANYDUEFROM_Acct," + + "PPVOFFSET_Acct, CommitmentOffset_Acct) VALUES ("); + sqlCmd.append(m_stdValues).append(",").append(m_as.getC_AcctSchema_ID()).append(",") + .append("'Y',").append(getAcct("SUSPENSEBALANCING_Acct")).append(",") + .append("'Y',").append(getAcct("SUSPENSEERROR_Acct")).append(",") + .append("'Y',").append(getAcct("CURRENCYBALANCING_Acct")).append(","); + // RETAINEDEARNING_Acct,INCOMESUMMARY_Acct, + sqlCmd.append(getAcct("RETAINEDEARNING_Acct")).append(",") + .append(getAcct("INCOMESUMMARY_Acct")).append(",") + // INTERCOMPANYDUETO_Acct,INTERCOMPANYDUEFROM_Acct) + .append(getAcct("INTERCOMPANYDUETO_Acct")).append(",") + .append(getAcct("INTERCOMPANYDUEFROM_Acct")).append(",") + .append(getAcct("PPVOFFSET_Acct")).append(",") + .append(getAcct("CommitmentOffset_Acct")) + .append(")"); + if (m_accountsOK) + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + else + no = -1; + if (no != 1) + { + String err = "GL Accounts NOT inserted"; + log.log(Level.SEVERE, err); + m_info.append(err); + m_trx.rollback(); + m_trx.close(); + return false; + } + + // Create Std Accounts + sqlCmd = new StringBuffer ("INSERT INTO C_AcctSchema_Default ("); + sqlCmd.append(m_stdColumns).append(",C_AcctSchema_ID," + + "W_INVENTORY_Acct,W_DIFFERENCES_Acct,W_REVALUATION_Acct,W_INVACTUALADJUST_Acct, " + + "P_REVENUE_Acct,P_EXPENSE_Acct,P_CostAdjustment_Acct,P_InventoryClearing_Acct,P_ASSET_Acct,P_COGS_Acct, " + + "P_PURCHASEPRICEVARIANCE_Acct,P_INVOICEPRICEVARIANCE_Acct,P_TRADEDISCOUNTREC_Acct,P_TRADEDISCOUNTGRANT_Acct, " + + "C_RECEIVABLE_Acct,C_Receivable_Services_Acct,C_PREPAYMENT_Acct, " + + "V_LIABILITY_Acct,V_LIABILITY_SERVICES_Acct,V_PREPAYMENT_Acct, " + + "PAYDISCOUNT_EXP_Acct,PAYDISCOUNT_REV_Acct,WRITEOFF_Acct, " + + "UNREALIZEDGAIN_Acct,UNREALIZEDLOSS_Acct,REALIZEDGAIN_Acct,REALIZEDLOSS_Acct, " + + "WITHHOLDING_Acct,E_PREPAYMENT_Acct,E_EXPENSE_Acct, " + + "PJ_ASSET_Acct,PJ_WIP_Acct," + + "T_EXPENSE_Acct,T_LIABILITY_Acct,T_RECEIVABLES_Acct,T_DUE_Acct,T_CREDIT_Acct, " + + "B_INTRANSIT_Acct,B_ASSET_Acct,B_EXPENSE_Acct,B_INTERESTREV_Acct,B_INTERESTEXP_Acct," + + "B_UNIDENTIFIED_Acct,B_SETTLEMENTGAIN_Acct,B_SETTLEMENTLOSS_Acct," + + "B_REVALUATIONGAIN_Acct,B_REVALUATIONLOSS_Acct,B_PAYMENTSELECT_Acct,B_UNALLOCATEDCASH_Acct, " + + "CH_EXPENSE_Acct,CH_REVENUE_Acct, " + + "UNEARNEDREVENUE_Acct,NOTINVOICEDRECEIVABLES_Acct,NOTINVOICEDREVENUE_Acct,NOTINVOICEDRECEIPTS_Acct, " + + "CB_ASSET_Acct,CB_CASHTRANSFER_Acct,CB_DIFFERENCES_Acct,CB_EXPENSE_Acct,CB_RECEIPT_Acct) VALUES ("); + sqlCmd.append(m_stdValues).append(",").append(m_as.getC_AcctSchema_ID()).append(","); + // W_INVENTORY_Acct,W_DIFFERENCES_Acct,W_REVALUATION_Acct,W_INVACTUALADJUST_Acct + sqlCmd.append(getAcct("W_INVENTORY_Acct")).append(","); + sqlCmd.append(getAcct("W_DIFFERENCES_Acct")).append(","); + sqlCmd.append(getAcct("W_REVALUATION_Acct")).append(","); + sqlCmd.append(getAcct("W_INVACTUALADJUST_Acct")).append(", "); + // P_REVENUE_Acct,P_EXPENSE_Acct,P_ASSET_Acct,P_COGS_Acct, + sqlCmd.append(getAcct("P_REVENUE_Acct")).append(","); + sqlCmd.append(getAcct("P_EXPENSE_Acct")).append(","); + sqlCmd.append(getAcct("P_CostAdjustment_Acct")).append(","); + sqlCmd.append(getAcct("P_InventoryClearing_Acct")).append(","); + sqlCmd.append(getAcct("P_ASSET_Acct")).append(","); + sqlCmd.append(getAcct("P_COGS_Acct")).append(", "); + // P_PURCHASEPRICEVARIANCE_Acct,P_INVOICEPRICEVARIANCE_Acct,P_TRADEDISCOUNTREC_Acct,P_TRADEDISCOUNTGRANT_Acct, + sqlCmd.append(getAcct("P_PURCHASEPRICEVARIANCE_Acct")).append(","); + sqlCmd.append(getAcct("P_INVOICEPRICEVARIANCE_Acct")).append(","); + sqlCmd.append(getAcct("P_TRADEDISCOUNTREC_Acct")).append(","); + sqlCmd.append(getAcct("P_TRADEDISCOUNTGRANT_Acct")).append(", "); + // C_RECEIVABLE_Acct,C_Receivable_Services_Acct,C_PREPAYMENT_Acct, + sqlCmd.append(getAcct("C_RECEIVABLE_Acct")).append(","); + sqlCmd.append(getAcct("C_RECEIVABLE_SERVICES_Acct")).append(","); + sqlCmd.append(getAcct("C_PREPAYMENT_Acct")).append(", "); + // V_LIABILITY_Acct,V_LIABILITY_SERVICES_Acct,V_PREPAYMENT_Acct, + sqlCmd.append(getAcct("V_LIABILITY_Acct")).append(","); + sqlCmd.append(getAcct("V_LIABILITY_SERVICES_Acct")).append(","); + sqlCmd.append(getAcct("V_PREPAYMENT_Acct")).append(", "); + // PAYDISCOUNT_EXP_Acct,PAYDISCOUNT_REV_Acct,WRITEOFF_Acct, + sqlCmd.append(getAcct("PAYDISCOUNT_EXP_Acct")).append(","); + sqlCmd.append(getAcct("PAYDISCOUNT_REV_Acct")).append(","); + sqlCmd.append(getAcct("WRITEOFF_Acct")).append(", "); + // UNREALIZEDGAIN_Acct,UNREALIZEDLOSS_Acct,REALIZEDGAIN_Acct,REALIZEDLOSS_Acct, + sqlCmd.append(getAcct("UNREALIZEDGAIN_Acct")).append(","); + sqlCmd.append(getAcct("UNREALIZEDLOSS_Acct")).append(","); + sqlCmd.append(getAcct("REALIZEDGAIN_Acct")).append(","); + sqlCmd.append(getAcct("REALIZEDLOSS_Acct")).append(", "); + // WITHHOLDING_Acct,E_PREPAYMENT_Acct,E_EXPENSE_Acct, + sqlCmd.append(getAcct("WITHHOLDING_Acct")).append(","); + sqlCmd.append(getAcct("E_PREPAYMENT_Acct")).append(","); + sqlCmd.append(getAcct("E_EXPENSE_Acct")).append(", "); + // PJ_ASSET_Acct,PJ_WIP_Acct, + sqlCmd.append(getAcct("PJ_ASSET_Acct")).append(","); + sqlCmd.append(getAcct("PJ_WIP_Acct")).append(","); + // T_EXPENSE_Acct,T_LIABILITY_Acct,T_RECEIVABLES_Acct,T_DUE_Acct,T_CREDIT_Acct, + sqlCmd.append(getAcct("T_EXPENSE_Acct")).append(","); + sqlCmd.append(getAcct("T_LIABILITY_Acct")).append(","); + sqlCmd.append(getAcct("T_RECEIVABLES_Acct")).append(","); + sqlCmd.append(getAcct("T_DUE_Acct")).append(","); + sqlCmd.append(getAcct("T_CREDIT_Acct")).append(", "); + // B_INTRANSIT_Acct,B_ASSET_Acct,B_EXPENSE_Acct,B_INTERESTREV_Acct,B_INTERESTEXP_Acct, + sqlCmd.append(getAcct("B_INTRANSIT_Acct")).append(","); + sqlCmd.append(getAcct("B_ASSET_Acct")).append(","); + sqlCmd.append(getAcct("B_EXPENSE_Acct")).append(","); + sqlCmd.append(getAcct("B_INTERESTREV_Acct")).append(","); + sqlCmd.append(getAcct("B_INTERESTEXP_Acct")).append(","); + // B_UNIDENTIFIED_Acct,B_SETTLEMENTGAIN_Acct,B_SETTLEMENTLOSS_Acct, + sqlCmd.append(getAcct("B_UNIDENTIFIED_Acct")).append(","); + sqlCmd.append(getAcct("B_SETTLEMENTGAIN_Acct")).append(","); + sqlCmd.append(getAcct("B_SETTLEMENTLOSS_Acct")).append(","); + // B_REVALUATIONGAIN_Acct,B_REVALUATIONLOSS_Acct,B_PAYMENTSELECT_Acct,B_UNALLOCATEDCASH_Acct, + sqlCmd.append(getAcct("B_REVALUATIONGAIN_Acct")).append(","); + sqlCmd.append(getAcct("B_REVALUATIONLOSS_Acct")).append(","); + sqlCmd.append(getAcct("B_PAYMENTSELECT_Acct")).append(","); + sqlCmd.append(getAcct("B_UNALLOCATEDCASH_Acct")).append(", "); + // CH_EXPENSE_Acct,CH_REVENUE_Acct, + sqlCmd.append(getAcct("CH_EXPENSE_Acct")).append(","); + sqlCmd.append(getAcct("CH_REVENUE_Acct")).append(", "); + // UNEARNEDREVENUE_Acct,NOTINVOICEDRECEIVABLES_Acct,NOTINVOICEDREVENUE_Acct,NOTINVOICEDRECEIPTS_Acct, + sqlCmd.append(getAcct("UNEARNEDREVENUE_Acct")).append(","); + sqlCmd.append(getAcct("NOTINVOICEDRECEIVABLES_Acct")).append(","); + sqlCmd.append(getAcct("NOTINVOICEDREVENUE_Acct")).append(","); + sqlCmd.append(getAcct("NOTINVOICEDRECEIPTS_Acct")).append(", "); + // CB_ASSET_Acct,CB_CASHTRANSFER_Acct,CB_DIFFERENCES_Acct,CB_EXPENSE_Acct,CB_RECEIPT_Acct) + sqlCmd.append(getAcct("CB_ASSET_Acct")).append(","); + sqlCmd.append(getAcct("CB_CASHTRANSFER_Acct")).append(","); + sqlCmd.append(getAcct("CB_DIFFERENCES_Acct")).append(","); + sqlCmd.append(getAcct("CB_EXPENSE_Acct")).append(","); + sqlCmd.append(getAcct("CB_RECEIPT_Acct")).append(")"); + if (m_accountsOK) + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + else + no = -1; + if (no != 1) + { + String err = "Default Accounts NOT inserted"; + log.log(Level.SEVERE, err); + m_info.append(err); + m_trx.rollback(); + m_trx.close(); + return false; + } + + // GL Categories + createGLCategory("Standard", MGLCategory.CATEGORYTYPE_Manual, true); + int GL_None = createGLCategory("None", MGLCategory.CATEGORYTYPE_Document, false); + int GL_GL = createGLCategory("Manual", MGLCategory.CATEGORYTYPE_Manual, false); + int GL_ARI = createGLCategory("AR Invoice", MGLCategory.CATEGORYTYPE_Document, false); + int GL_ARR = createGLCategory("AR Receipt", MGLCategory.CATEGORYTYPE_Document, false); + int GL_MM = createGLCategory("Material Management", MGLCategory.CATEGORYTYPE_Document, false); + int GL_API = createGLCategory("AP Invoice", MGLCategory.CATEGORYTYPE_Document, false); + int GL_APP = createGLCategory("AP Payment", MGLCategory.CATEGORYTYPE_Document, false); + int GL_CASH = createGLCategory("Cash/Payments", MGLCategory.CATEGORYTYPE_Document, false); + + // Base DocumentTypes + int ii = createDocType("GL Journal", Msg.getElement(m_ctx, "GL_Journal_ID"), + MDocType.DOCBASETYPE_GLJournal, null, 0, 0, 1000, GL_GL); + if (ii == 0) + { + String err = "Document Type not created"; + m_info.append(err); + m_trx.rollback(); + m_trx.close(); + return false; + } + createDocType("GL Journal Batch", Msg.getElement(m_ctx, "GL_JournalBatch_ID"), + MDocType.DOCBASETYPE_GLJournal, null, 0, 0, 100, GL_GL); + // MDocType.DOCBASETYPE_GLDocument + // + int DT_I = createDocType("AR Invoice", Msg.getElement(m_ctx, "C_Invoice_ID", true), + MDocType.DOCBASETYPE_ARInvoice, null, 0, 0, 100000, GL_ARI); + int DT_II = createDocType("AR Invoice Indirect", Msg.getElement(m_ctx, "C_Invoice_ID", true), + MDocType.DOCBASETYPE_ARInvoice, null, 0, 0, 150000, GL_ARI); + int DT_IC = createDocType("AR Credit Memo", Msg.getMsg(m_ctx, "CreditMemo"), + MDocType.DOCBASETYPE_ARCreditMemo, null, 0, 0, 170000, GL_ARI); + // MDocType.DOCBASETYPE_ARProFormaInvoice + + createDocType("AP Invoice", Msg.getElement(m_ctx, "C_Invoice_ID", false), + MDocType.DOCBASETYPE_APInvoice, null, 0, 0, 0, GL_API); + createDocType("AP CreditMemo", Msg.getMsg(m_ctx, "CreditMemo"), + MDocType.DOCBASETYPE_APCreditMemo, null, 0, 0, 0, GL_API); + createDocType("Match Invoice", Msg.getElement(m_ctx, "M_MatchInv_ID", false), + MDocType.DOCBASETYPE_MatchInvoice, null, 0, 0, 390000, GL_API); + + createDocType("AR Receipt", Msg.getElement(m_ctx, "C_Payment_ID", true), + MDocType.DOCBASETYPE_ARReceipt, null, 0, 0, 0, GL_ARR); + createDocType("AP Payment", Msg.getElement(m_ctx, "C_Payment_ID", false), + MDocType.DOCBASETYPE_APPayment, null, 0, 0, 0, GL_APP); + createDocType("Allocation", "Allocation", + MDocType.DOCBASETYPE_PaymentAllocation, null, 0, 0, 490000, GL_CASH); + + int DT_S = createDocType("MM Shipment", "Delivery Note", + MDocType.DOCBASETYPE_MaterialDelivery, null, 0, 0, 500000, GL_MM); + int DT_SI = createDocType("MM Shipment Indirect", "Delivery Note", + MDocType.DOCBASETYPE_MaterialDelivery, null, 0, 0, 550000, GL_MM); + + createDocType("MM Receipt", "Vendor Delivery", + MDocType.DOCBASETYPE_MaterialReceipt, null, 0, 0, 0, GL_MM); + int DT_RM = createDocType("MM Returns", "Customer Returns", + MDocType.DOCBASETYPE_MaterialReceipt, null, 0, 0, 570000, GL_MM); + + createDocType("Purchase Order", Msg.getElement(m_ctx, "C_Order_ID", false), + MDocType.DOCBASETYPE_PurchaseOrder, null, 0, 0, 800000, GL_None); + createDocType("Match PO", Msg.getElement(m_ctx, "M_MatchPO_ID", false), + MDocType.DOCBASETYPE_MatchPO, null, 0, 0, 890000, GL_None); + createDocType("Purchase Requisition", Msg.getElement(m_ctx, "M_Requisition_ID", false), + MDocType.DOCBASETYPE_PurchaseRequisition, null, 0, 0, 900000, GL_None); + + createDocType("Bank Statement", Msg.getElement(m_ctx, "C_BankStatemet_ID", true), + MDocType.DOCBASETYPE_BankStatement, null, 0, 0, 700000, GL_CASH); + createDocType("Cash Journal", Msg.getElement(m_ctx, "C_Cash_ID", true), + MDocType.DOCBASETYPE_CashJournal, null, 0, 0, 750000, GL_CASH); + + createDocType("Material Movement", Msg.getElement(m_ctx, "M_Movement_ID", false), + MDocType.DOCBASETYPE_MaterialMovement, null, 0, 0, 610000, GL_MM); + createDocType("Physical Inventory", Msg.getElement(m_ctx, "M_Inventory_ID", false), + MDocType.DOCBASETYPE_MaterialPhysicalInventory, null, 0, 0, 620000, GL_MM); + createDocType("Material Production", Msg.getElement(m_ctx, "M_Production_ID", false), + MDocType.DOCBASETYPE_MaterialProduction, null, 0, 0, 630000, GL_MM); + createDocType("Project Issue", Msg.getElement(m_ctx, "C_ProjectIssue_ID", false), + MDocType.DOCBASETYPE_ProjectIssue, null, 0, 0, 640000, GL_MM); + + // Order Entry + createDocType("Binding offer", "Quotation", + MDocType.DOCBASETYPE_SalesOrder, MDocType.DOCSUBTYPESO_Quotation, + 0, 0, 10000, GL_None); + createDocType("Non binding offer", "Proposal", + MDocType.DOCBASETYPE_SalesOrder, MDocType.DOCSUBTYPESO_Proposal, + 0, 0, 20000, GL_None); + createDocType("Prepay Order", "Prepay Order", + MDocType.DOCBASETYPE_SalesOrder, MDocType.DOCSUBTYPESO_PrepayOrder, + DT_S, DT_I, 30000, GL_None); + createDocType("Return Material", "Return Material Authorization", + MDocType.DOCBASETYPE_SalesOrder, MDocType.DOCSUBTYPESO_ReturnMaterial, + DT_RM, DT_IC, 30000, GL_None); + createDocType("Standard Order", "Order Confirmation", + MDocType.DOCBASETYPE_SalesOrder, MDocType.DOCSUBTYPESO_StandardOrder, + DT_S, DT_I, 50000, GL_None); + createDocType("Credit Order", "Order Confirmation", + MDocType.DOCBASETYPE_SalesOrder, MDocType.DOCSUBTYPESO_OnCreditOrder, + DT_SI, DT_I, 60000, GL_None); // RE + createDocType("Warehouse Order", "Order Confirmation", + MDocType.DOCBASETYPE_SalesOrder, MDocType.DOCSUBTYPESO_WarehouseOrder, + DT_S, DT_I, 70000, GL_None); // LS + int DT = createDocType("POS Order", "Order Confirmation", + MDocType.DOCBASETYPE_SalesOrder, MDocType.DOCSUBTYPESO_POSOrder, + DT_SI, DT_II, 80000, GL_None); // Bar + // POS As Default for window SO + createPreference("C_DocTypeTarget_ID", String.valueOf(DT), 143); + + // Update ClientInfo + sqlCmd = new StringBuffer ("UPDATE AD_ClientInfo SET "); + sqlCmd.append("C_AcctSchema1_ID=").append(m_as.getC_AcctSchema_ID()) + .append(", C_Calendar_ID=").append(m_calendar.getC_Calendar_ID()) + .append(" WHERE AD_Client_ID=").append(m_client.getAD_Client_ID()); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + { + String err = "ClientInfo not updated"; + log.log(Level.SEVERE, err); + m_info.append(err); + m_trx.rollback(); + m_trx.close(); + return false; + } + + // Validate Completeness + DocumentTypeVerify.createDocumentTypes(m_ctx, getAD_Client_ID(), null, m_trx.getTrxName()); + DocumentTypeVerify.createPeriodControls(m_ctx, getAD_Client_ID(), null, m_trx.getTrxName()); + // + log.info("fini"); + return true; + } // createAccounting + + /** + * Get Account ID for key + * @param key key + * @return C_ValidCombination_ID + */ + private int getAcct (String key) + { + log.fine(key); + // Element + int C_ElementValue_ID = m_nap.getC_ElementValue_ID(key.toUpperCase()); + if (C_ElementValue_ID == 0) + { + log.severe("Account not defined: " + key); + m_accountsOK = false; + return 0; + } + + MAccount vc = MAccount.getDefault(m_as, true); // optional null + vc.setAD_Org_ID(0); // will be overwritten + vc.setAccount_ID(C_ElementValue_ID); + if (!vc.save()) + { + log.severe("Not Saved - Key=" + key + ", C_ElementValue_ID=" + C_ElementValue_ID); + m_accountsOK = false; + return 0; + } + int C_ValidCombination_ID = vc.getC_ValidCombination_ID(); + if (C_ValidCombination_ID == 0) + { + log.severe("No account - Key=" + key + ", C_ElementValue_ID=" + C_ElementValue_ID); + m_accountsOK = false; + } + return C_ValidCombination_ID; + } // getAcct + + /** + * Create GL Category + * @param Name name + * @param CategoryType category type MGLCategory.CATEGORYTYPE_* + * @param isDefault is default value + * @return GL_Category_ID + */ + private int createGLCategory (String Name, String CategoryType, boolean isDefault) + { + MGLCategory cat = new MGLCategory (m_ctx, 0, m_trx.getTrxName()); + cat.setName(Name); + cat.setCategoryType(CategoryType); + cat.setIsDefault(isDefault); + if (!cat.save()) + { + log.log(Level.SEVERE, "GL Category NOT created - " + Name); + return 0; + } + // + return cat.getGL_Category_ID(); + } // createGLCategory + + /** + * Create Document Types with Sequence + * @param Name name + * @param PrintName print name + * @param DocBaseType document base type + * @param DocSubTypeSO sales order sub type + * @param C_DocTypeShipment_ID shipment doc + * @param C_DocTypeInvoice_ID invoice doc + * @param StartNo start doc no + * @param GL_Category_ID gl category + * @return C_DocType_ID doc type or 0 for error + */ + private int createDocType (String Name, String PrintName, + String DocBaseType, String DocSubTypeSO, + int C_DocTypeShipment_ID, int C_DocTypeInvoice_ID, + int StartNo, int GL_Category_ID) + { + MSequence sequence = null; + if (StartNo != 0) + { + sequence = new MSequence(m_ctx, getAD_Client_ID(), Name, StartNo, m_trx.getTrxName()); + if (!sequence.save()) + { + log.log(Level.SEVERE, "Sequence NOT created - " + Name); + return 0; + } + } + + MDocType dt = new MDocType (m_ctx, DocBaseType, Name, m_trx.getTrxName()); + if (PrintName != null && PrintName.length() > 0) + dt.setPrintName(PrintName); // Defaults to Name + if (DocSubTypeSO != null) + dt.setDocSubTypeSO(DocSubTypeSO); + if (C_DocTypeShipment_ID != 0) + dt.setC_DocTypeShipment_ID(C_DocTypeShipment_ID); + if (C_DocTypeInvoice_ID != 0) + dt.setC_DocTypeInvoice_ID(C_DocTypeInvoice_ID); + if (GL_Category_ID != 0) + dt.setGL_Category_ID(GL_Category_ID); + if (sequence == null) + dt.setIsDocNoControlled(false); + else + { + dt.setIsDocNoControlled(true); + dt.setDocNoSequence_ID(sequence.getAD_Sequence_ID()); + } + dt.setIsSOTrx(); + if (!dt.save()) + { + log.log(Level.SEVERE, "DocType NOT created - " + Name); + return 0; + } + // + return dt.getC_DocType_ID(); + } // createDocType + + + /************************************************************************** + * Create Default main entities. + * - Dimensions & BPGroup, Prod Category) + * - Location, Locator, Warehouse + * - PriceList + * - Cashbook, PaymentTerm + * @param C_Country_ID country + * @param City city + * @param C_Region_ID region + * @param C_Currency_ID currency + * @return true if created + */ + public boolean createEntities (int C_Country_ID, String City, int C_Region_ID, int C_Currency_ID) + { + if (m_as == null) + { + log.severe ("No AcctountingSChema"); + m_trx.rollback(); + m_trx.close(); + return false; + } + log.info("C_Country_ID=" + C_Country_ID + + ", City=" + City + ", C_Region_ID=" + C_Region_ID); + m_info.append("\n----\n"); + // + String defaultName = Msg.translate(m_lang, "Standard"); + String defaultEntry = "'" + defaultName + "',"; + StringBuffer sqlCmd = null; + int no = 0; + + // Create Marketing Channel/Campaign + int C_Channel_ID = getNextID(getAD_Client_ID(), "C_Channel"); + sqlCmd = new StringBuffer("INSERT INTO C_Channel "); + sqlCmd.append("(C_Channel_ID,Name,"); + sqlCmd.append(m_stdColumns).append(") VALUES ("); + sqlCmd.append(C_Channel_ID).append(",").append(defaultEntry); + sqlCmd.append(m_stdValues).append(")"); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "Channel NOT inserted"); + int C_Campaign_ID = getNextID(getAD_Client_ID(), "C_Campaign"); + sqlCmd = new StringBuffer("INSERT INTO C_Campaign "); + sqlCmd.append("(C_Campaign_ID,C_Channel_ID,").append(m_stdColumns).append(","); + sqlCmd.append(" Value,Name,Costs) VALUES ("); + sqlCmd.append(C_Campaign_ID).append(",").append(C_Channel_ID).append(",").append(m_stdValues).append(","); + sqlCmd.append(defaultEntry).append(defaultEntry).append("0)"); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no == 1) + m_info.append(Msg.translate(m_lang, "C_Campaign_ID")).append("=").append(defaultName).append("\n"); + else + log.log(Level.SEVERE, "Campaign NOT inserted"); + if (m_hasMCampaign) + { + // Default + sqlCmd = new StringBuffer ("UPDATE C_AcctSchema_Element SET "); + sqlCmd.append("C_Campaign_ID=").append(C_Campaign_ID); + sqlCmd.append(" WHERE C_AcctSchema_ID=").append(m_as.getC_AcctSchema_ID()); + sqlCmd.append(" AND ElementType='MC'"); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "AcctSchema ELement Campaign NOT updated"); + } + + // Create Sales Region + int C_SalesRegion_ID = getNextID(getAD_Client_ID(), "C_SalesRegion"); + sqlCmd = new StringBuffer ("INSERT INTO C_SalesRegion "); + sqlCmd.append("(C_SalesRegion_ID,").append(m_stdColumns).append(","); + sqlCmd.append(" Value,Name,IsSummary) VALUES ("); + sqlCmd.append(C_SalesRegion_ID).append(",").append(m_stdValues).append(", "); + sqlCmd.append(defaultEntry).append(defaultEntry).append("'N')"); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no == 1) + m_info.append(Msg.translate(m_lang, "C_SalesRegion_ID")).append("=").append(defaultName).append("\n"); + else + log.log(Level.SEVERE, "SalesRegion NOT inserted"); + if (m_hasSRegion) + { + // Default + sqlCmd = new StringBuffer ("UPDATE C_AcctSchema_Element SET "); + sqlCmd.append("C_SalesRegion_ID=").append(C_SalesRegion_ID); + sqlCmd.append(" WHERE C_AcctSchema_ID=").append(m_as.getC_AcctSchema_ID()); + sqlCmd.append(" AND ElementType='SR'"); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "AcctSchema ELement SalesRegion NOT updated"); + } + + /** + * Business Partner + */ + // Create BP Group + MBPGroup bpg = new MBPGroup (m_ctx, 0, m_trx.getTrxName()); + bpg.setValue(defaultName); + bpg.setName(defaultName); + bpg.setIsDefault(true); + if (bpg.save()) + m_info.append(Msg.translate(m_lang, "C_BP_Group_ID")).append("=").append(defaultName).append("\n"); + else + log.log(Level.SEVERE, "BP Group NOT inserted"); + + // Create BPartner + MBPartner bp = new MBPartner (m_ctx, 0, m_trx.getTrxName()); + bp.setValue(defaultName); + bp.setName(defaultName); + bp.setBPGroup(bpg); + if (bp.save()) + m_info.append(Msg.translate(m_lang, "C_BPartner_ID")).append("=").append(defaultName).append("\n"); + else + log.log(Level.SEVERE, "BPartner NOT inserted"); + // Location for Standard BP + MLocation bpLoc = new MLocation(m_ctx, C_Country_ID, C_Region_ID, City, m_trx.getTrxName()); + bpLoc.save(); + MBPartnerLocation bpl = new MBPartnerLocation(bp); + bpl.setC_Location_ID(bpLoc.getC_Location_ID()); + if (!bpl.save()) + log.log(Level.SEVERE, "BP_Location (Standard) NOT inserted"); + // Default + sqlCmd = new StringBuffer ("UPDATE C_AcctSchema_Element SET "); + sqlCmd.append("C_BPartner_ID=").append(bp.getC_BPartner_ID()); + sqlCmd.append(" WHERE C_AcctSchema_ID=").append(m_as.getC_AcctSchema_ID()); + sqlCmd.append(" AND ElementType='BP'"); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "AcctSchema Element BPartner NOT updated"); + createPreference("C_BPartner_ID", String.valueOf(bp.getC_BPartner_ID()), 143); + + /** + * Product + */ + // Create Product Category + MProductCategory pc = new MProductCategory(m_ctx, 0, m_trx.getTrxName()); + pc.setValue(defaultName); + pc.setName(defaultName); + pc.setIsDefault(true); + if (pc.save()) + m_info.append(Msg.translate(m_lang, "M_Product_Category_ID")).append("=").append(defaultName).append("\n"); + else + log.log(Level.SEVERE, "Product Category NOT inserted"); + + // UOM (EA) + int C_UOM_ID = 100; + + // TaxCategory + int C_TaxCategory_ID = getNextID(getAD_Client_ID(), "C_TaxCategory"); + sqlCmd = new StringBuffer ("INSERT INTO C_TaxCategory "); + sqlCmd.append("(C_TaxCategory_ID,").append(m_stdColumns).append(","); + sqlCmd.append(" Name,IsDefault) VALUES ("); + sqlCmd.append(C_TaxCategory_ID).append(",").append(m_stdValues).append(", "); + if (C_Country_ID == 100) // US + sqlCmd.append("'Sales Tax','Y')"); + else + sqlCmd.append(defaultEntry).append("'Y')"); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "TaxCategory NOT inserted"); + + // Tax - Zero Rate + MTax tax = new MTax (m_ctx, "Standard", Env.ZERO, C_TaxCategory_ID, m_trx.getTrxName()); + tax.setIsDefault(true); + if (tax.save()) + m_info.append(Msg.translate(m_lang, "C_Tax_ID")) + .append("=").append(tax.getName()).append("\n"); + else + log.log(Level.SEVERE, "Tax NOT inserted"); + + // Create Product + MProduct product = new MProduct (m_ctx, 0, m_trx.getTrxName()); + product.setValue(defaultName); + product.setName(defaultName); + product.setC_UOM_ID(C_UOM_ID); + product.setM_Product_Category_ID(pc.getM_Product_Category_ID()); + product.setC_TaxCategory_ID(C_TaxCategory_ID); + if (product.save()) + m_info.append(Msg.translate(m_lang, "M_Product_ID")).append("=").append(defaultName).append("\n"); + else + log.log(Level.SEVERE, "Product NOT inserted"); + // Default + sqlCmd = new StringBuffer ("UPDATE C_AcctSchema_Element SET "); + sqlCmd.append("M_Product_ID=").append(product.getM_Product_ID()); + sqlCmd.append(" WHERE C_AcctSchema_ID=").append(m_as.getC_AcctSchema_ID()); + sqlCmd.append(" AND ElementType='PR'"); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "AcctSchema Element Product NOT updated"); + + /** + * Location, Warehouse, Locator + */ + // Location (Company) + MLocation loc = new MLocation(m_ctx, C_Country_ID, C_Region_ID, City, m_trx.getTrxName()); + loc.save(); + sqlCmd = new StringBuffer ("UPDATE AD_OrgInfo SET C_Location_ID="); + sqlCmd.append(loc.getC_Location_ID()).append(" WHERE AD_Org_ID=").append(getAD_Org_ID()); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "Location NOT inserted"); + createPreference("C_Country_ID", String.valueOf(C_Country_ID), 0); + + // Default Warehouse + MWarehouse wh = new MWarehouse(m_ctx, 0, m_trx.getTrxName()); + wh.setValue(defaultName); + wh.setName(defaultName); + wh.setC_Location_ID(loc.getC_Location_ID()); + if (!wh.save()) + log.log(Level.SEVERE, "Warehouse NOT inserted"); + + // Locator + MLocator locator = new MLocator(wh, defaultName); + locator.setIsDefault(true); + if (!locator.save()) + log.log(Level.SEVERE, "Locator NOT inserted"); + + // Update ClientInfo + sqlCmd = new StringBuffer ("UPDATE AD_ClientInfo SET "); + sqlCmd.append("C_BPartnerCashTrx_ID=").append(bp.getC_BPartner_ID()); + sqlCmd.append(",M_ProductFreight_ID=").append(product.getM_Product_ID()); +// sqlCmd.append("C_UOM_Volume_ID="); +// sqlCmd.append(",C_UOM_Weight_ID="); +// sqlCmd.append(",C_UOM_Length_ID="); +// sqlCmd.append(",C_UOM_Time_ID="); + sqlCmd.append(" WHERE AD_Client_ID=").append(getAD_Client_ID()); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + { + String err = "ClientInfo not updated"; + log.log(Level.SEVERE, err); + m_info.append(err); + return false; + } + + /** + * Other + */ + // PriceList + MPriceList pl = new MPriceList(m_ctx, 0, m_trx.getTrxName()); + pl.setName(defaultName); + pl.setC_Currency_ID(C_Currency_ID); + pl.setIsDefault(true); + if (!pl.save()) + log.log(Level.SEVERE, "PriceList NOT inserted"); + // Price List + MDiscountSchema ds = new MDiscountSchema(m_ctx, 0, m_trx.getTrxName()); + ds.setName(defaultName); + ds.setDiscountType(MDiscountSchema.DISCOUNTTYPE_Pricelist); + if (!ds.save()) + log.log(Level.SEVERE, "DiscountSchema NOT inserted"); + // PriceList Version + MPriceListVersion plv = new MPriceListVersion(pl); + plv.setName(); + plv.setM_DiscountSchema_ID(ds.getM_DiscountSchema_ID()); + if (!plv.save()) + log.log(Level.SEVERE, "PriceList_Version NOT inserted"); + // ProductPrice + MProductPrice pp = new MProductPrice(plv, product.getM_Product_ID(), + Env.ONE, Env.ONE, Env.ONE); + if (!pp.save()) + log.log(Level.SEVERE, "ProductPrice NOT inserted"); + + + // Create Sales Rep for Client-User + MBPartner bpCU = new MBPartner (m_ctx, 0, m_trx.getTrxName()); + bpCU.setValue(AD_User_U_Name); + bpCU.setName(AD_User_U_Name); + bpCU.setBPGroup(bpg); + bpCU.setIsEmployee(true); + bpCU.setIsSalesRep(true); + if (bpCU.save()) + m_info.append(Msg.translate(m_lang, "SalesRep_ID")).append("=").append(AD_User_U_Name).append("\n"); + else + log.log(Level.SEVERE, "SalesRep (User) NOT inserted"); + // Location for Client-User + MLocation bpLocCU = new MLocation(m_ctx, C_Country_ID, C_Region_ID, City, m_trx.getTrxName()); + bpLocCU.save(); + MBPartnerLocation bplCU = new MBPartnerLocation(bpCU); + bplCU.setC_Location_ID(bpLocCU.getC_Location_ID()); + if (!bplCU.save()) + log.log(Level.SEVERE, "BP_Location (User) NOT inserted"); + // Update User + sqlCmd = new StringBuffer ("UPDATE AD_User SET C_BPartner_ID="); + sqlCmd.append(bpCU.getC_BPartner_ID()).append(" WHERE AD_User_ID=").append(AD_User_U_ID); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "User of SalesRep (User) NOT updated"); + + + // Create Sales Rep for Client-Admin + MBPartner bpCA = new MBPartner (m_ctx, 0, m_trx.getTrxName()); + bpCA.setValue(AD_User_Name); + bpCA.setName(AD_User_Name); + bpCA.setBPGroup(bpg); + bpCA.setIsEmployee(true); + bpCA.setIsSalesRep(true); + if (bpCA.save()) + m_info.append(Msg.translate(m_lang, "SalesRep_ID")).append("=").append(AD_User_Name).append("\n"); + else + log.log(Level.SEVERE, "SalesRep (Admin) NOT inserted"); + // Location for Client-Admin + MLocation bpLocCA = new MLocation(m_ctx, C_Country_ID, C_Region_ID, City, m_trx.getTrxName()); + bpLocCA.save(); + MBPartnerLocation bplCA = new MBPartnerLocation(bpCA); + bplCA.setC_Location_ID(bpLocCA.getC_Location_ID()); + if (!bplCA.save()) + log.log(Level.SEVERE, "BP_Location (Admin) NOT inserted"); + // Update User + sqlCmd = new StringBuffer ("UPDATE AD_User SET C_BPartner_ID="); + sqlCmd.append(bpCA.getC_BPartner_ID()).append(" WHERE AD_User_ID=").append(AD_User_ID); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "User of SalesRep (Admin) NOT updated"); + + + // Payment Term + int C_PaymentTerm_ID = getNextID(getAD_Client_ID(), "C_PaymentTerm"); + sqlCmd = new StringBuffer ("INSERT INTO C_PaymentTerm "); + sqlCmd.append("(C_PaymentTerm_ID,").append(m_stdColumns).append(","); + sqlCmd.append("Value,Name,NetDays,GraceDays,DiscountDays,Discount,DiscountDays2,Discount2,IsDefault) VALUES ("); + sqlCmd.append(C_PaymentTerm_ID).append(",").append(m_stdValues).append(","); + sqlCmd.append("'Immediate','Immediate',0,0,0,0,0,0,'Y')"); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "PaymentTerm NOT inserted"); + + // Project Cycle + C_Cycle_ID = getNextID(getAD_Client_ID(), "C_Cycle"); + sqlCmd = new StringBuffer ("INSERT INTO C_Cycle "); + sqlCmd.append("(C_Cycle_ID,").append(m_stdColumns).append(","); + sqlCmd.append(" Name,C_Currency_ID) VALUES ("); + sqlCmd.append(C_Cycle_ID).append(",").append(m_stdValues).append(", "); + sqlCmd.append(defaultEntry).append(C_Currency_ID).append(")"); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "Cycle NOT inserted"); + + /** + * Organization level data =========================================== + */ + + // Create Default Project + int C_Project_ID = getNextID(getAD_Client_ID(), "C_Project"); + sqlCmd = new StringBuffer ("INSERT INTO C_Project "); + sqlCmd.append("(C_Project_ID,").append(m_stdColumns).append(","); + sqlCmd.append(" Value,Name,C_Currency_ID,IsSummary) VALUES ("); + sqlCmd.append(C_Project_ID).append(",").append(m_stdValuesOrg).append(", "); + sqlCmd.append(defaultEntry).append(defaultEntry).append(C_Currency_ID).append(",'N')"); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no == 1) + m_info.append(Msg.translate(m_lang, "C_Project_ID")).append("=").append(defaultName).append("\n"); + else + log.log(Level.SEVERE, "Project NOT inserted"); + // Default Project + if (m_hasProject) + { + sqlCmd = new StringBuffer ("UPDATE C_AcctSchema_Element SET "); + sqlCmd.append("C_Project_ID=").append(C_Project_ID); + sqlCmd.append(" WHERE C_AcctSchema_ID=").append(m_as.getC_AcctSchema_ID()); + sqlCmd.append(" AND ElementType='PJ'"); + no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "AcctSchema ELement Project NOT updated"); + } + + // CashBook + MCashBook cb = new MCashBook(m_ctx, 0, m_trx.getTrxName()); + cb.setName(defaultName); + cb.setC_Currency_ID(C_Currency_ID); + if (cb.save()) + m_info.append(Msg.translate(m_lang, "C_CashBook_ID")).append("=").append(defaultName).append("\n"); + else + log.log(Level.SEVERE, "CashBook NOT inserted"); + // + m_trx.commit(); + m_trx.close(); + log.info("fini"); + return true; + } // createEntities + + /** + * Create Preference + * @param Attribute attribute + * @param Value value + * @param AD_Window_ID window + */ + private void createPreference (String Attribute, String Value, int AD_Window_ID) + { + int AD_Preference_ID = getNextID(getAD_Client_ID(), "AD_Preference"); + StringBuffer sqlCmd = new StringBuffer ("INSERT INTO AD_Preference "); + sqlCmd.append("(AD_Preference_ID,").append(m_stdColumns).append(","); + sqlCmd.append("Attribute,Value,AD_Window_ID) VALUES ("); + sqlCmd.append(AD_Preference_ID).append(",").append(m_stdValues).append(","); + sqlCmd.append("'").append(Attribute).append("','").append(Value).append("',"); + if (AD_Window_ID == 0) + sqlCmd.append("NULL)"); + else + sqlCmd.append(AD_Window_ID).append(")"); + int no = DB.executeUpdate(sqlCmd.toString(), m_trx.getTrxName()); + if (no != 1) + log.log(Level.SEVERE, "Preference NOT inserted - " + Attribute); + } // createPreference + + + /************************************************************************** + * Get Next ID + * @param AD_Client_ID client + * @param TableName table name + * @return id + */ + private int getNextID (int AD_Client_ID, String TableName) + { + // TODO: Exception + return DB.getNextID (AD_Client_ID, TableName, m_trx.getTrxName()); + } // getNextID + + /** + * Get Client + * @return AD_Client_ID + */ + public int getAD_Client_ID() + { + return m_client.getAD_Client_ID(); + } + /** + * Get AD_Org_ID + * @return AD_Org_ID + */ + public int getAD_Org_ID() + { + return m_org.getAD_Org_ID(); + } + /** + * Get AD_User_ID + * @return AD_User_ID + */ + public int getAD_User_ID() + { + return AD_User_ID; + } + /** + * Get Info + * @return Info + */ + public String getInfo() + { + return m_info.toString(); + } +} // MSetup diff --git a/base/src/org/compiere/model/MShipper.java b/base/src/org/compiere/model/MShipper.java new file mode 100644 index 0000000000..1dd153ecc3 --- /dev/null +++ b/base/src/org/compiere/model/MShipper.java @@ -0,0 +1,53 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Shipper Model + * + * @author Jorg Janke + * @version $Id: MShipper.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MShipper extends X_M_Shipper +{ + /** + * Standard Constructor + * @param ctx context + * @param M_Shipper_ID id + * @param trxName transaction + */ + public MShipper (Properties ctx, int M_Shipper_ID, String trxName) + { + super (ctx, M_Shipper_ID, trxName); + } // MShipper + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MShipper (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MShipper + +} // MShipper diff --git a/base/src/org/compiere/model/MStatus.java b/base/src/org/compiere/model/MStatus.java new file mode 100644 index 0000000000..319897d231 --- /dev/null +++ b/base/src/org/compiere/model/MStatus.java @@ -0,0 +1,218 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Request Status Model + * @author Jorg Janke + * @version $Id: MStatus.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MStatus extends X_R_Status +{ + /** + * Get Request Status (cached) + * @param ctx context + * @param R_Status_ID id + * @return Request Status or null + */ + public static MStatus get (Properties ctx, int R_Status_ID) + { + if (R_Status_ID == 0) + return null; + Integer key = new Integer (R_Status_ID); + MStatus retValue = (MStatus)s_cache.get(key); + if (retValue == null) + { + retValue = new MStatus (ctx, R_Status_ID, null); + s_cache.put(key, retValue); + } + return retValue; + } // get + + /** + * Get Default Request Status + * @param ctx context + * @param R_RequestType_ID request type + * @return Request Type + */ + public static MStatus getDefault (Properties ctx, int R_RequestType_ID) + { + Integer key = new Integer(R_RequestType_ID); + MStatus retValue = (MStatus)s_cacheDefault.get(key); + if (retValue != null) + return retValue; + // Get New + String sql = "SELECT * FROM R_Status s " + + "WHERE EXISTS (SELECT * FROM R_RequestType rt " + + "WHERE rt.R_StatusCategory_ID=s.R_StatusCategory_ID" + + " AND rt.R_RequestType_ID=?)" + + " AND IsDefault='Y' " + + "ORDER BY SeqNo"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt(1, R_RequestType_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = new MStatus (ctx, rs, null); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (SQLException ex) + { + s_log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + if (retValue != null) + s_cacheDefault.put(key, retValue); + return retValue; + } // getDefault + + /** + * Get Closed Status + * @param ctx context + * @return Request Type + */ + public static MStatus[] getClosed (Properties ctx) + { + int AD_Client_ID = Env.getAD_Client_ID(ctx); + String sql = "SELECT * FROM R_Status " + + "WHERE AD_Client_ID=? AND IsActive='Y' AND IsClosed='Y' " + + "ORDER BY Value"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt(1, AD_Client_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + list.add(new MStatus (ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (SQLException ex) + { + s_log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + MStatus[] retValue = new MStatus[list.size()]; + list.toArray(retValue); + return retValue; + } // get + + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger(MStatus.class); + /** Cache */ + static private CCache s_cache + = new CCache ("R_Status", 10); + /** Default Cache (Key=Client) */ + static private CCache s_cacheDefault + = new CCache("R_Status", 10); + + + /************************************************************************** + * Default Constructor + * @param ctx context + * @param R_Status_ID is + * @param trxName trx + */ + public MStatus (Properties ctx, int R_Status_ID, String trxName) + { + super (ctx, R_Status_ID, trxName); + if (R_Status_ID == 0) + { + // setValue (null); + // setName (null); + setIsClosed (false); // N + setIsDefault (false); + setIsFinalClose (false); // N + setIsOpen (false); + setIsWebCanUpdate (true); + } + } // MStatus + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MStatus (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MStatus + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (isOpen() && isClosed()) + setIsClosed(false); + if (isFinalClose() && !isClosed()) + setIsFinalClose(false); + // + if (!isWebCanUpdate() && getUpdate_Status_ID() != 0) + setUpdate_Status_ID(0); + if (getTimeoutDays() == 0 && getNext_Status_ID() != 0) + setNext_Status_ID(0); + // + return true; + } // beforeSave + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MStatus["); + sb.append(get_ID()).append("-").append(getName()) + .append ("]"); + return sb.toString (); + } // toString + +} // MStatus diff --git a/base/src/org/compiere/model/MStatusCategory.java b/base/src/org/compiere/model/MStatusCategory.java new file mode 100644 index 0000000000..f1fc2117ee --- /dev/null +++ b/base/src/org/compiere/model/MStatusCategory.java @@ -0,0 +1,225 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Request Status Category Model + * + * @author Jorg Janke + * @version $Id: MStatusCategory.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MStatusCategory extends X_R_StatusCategory +{ + /** + * Get Default Status Categpru for Client + * @param ctx context + * @return status category or null + */ + public static MStatusCategory getDefault (Properties ctx) + { + int AD_Client_ID = Env.getAD_Client_ID(ctx); + String sql = "SELECT * FROM R_StatusCategory " + + "WHERE AD_Client_ID in (0,?) AND IsDefault='Y' " + + "ORDER BY AD_Client_ID DESC"; + MStatusCategory retValue = null; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, AD_Client_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = new MStatusCategory (ctx, rs, null); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return retValue; + } // getDefault + + /** + * Get Default Status Categpru for Client + * @param ctx context + * @return status category or null + */ + public static MStatusCategory createDefault (Properties ctx) + { + int AD_Client_ID = Env.getAD_Client_ID(ctx); + MStatusCategory retValue = new MStatusCategory(ctx, 0, null); + retValue.setClientOrg(AD_Client_ID, 0); + retValue.setName(Msg.getMsg(ctx, "Standard")); + retValue.setIsDefault(true); + if (!retValue.save()) + return null; + String sql = "UPDATE R_Status SET R_StatusCategory_ID=" + retValue.getR_StatusCategory_ID() + + " WHERE R_StatusCategory_ID IS NULL AND AD_Client_ID=" + AD_Client_ID; + int no = DB.executeUpdate(sql, null); + s_log.info("Default for AD_Client_ID=" + AD_Client_ID + " - Status #" + no); + return retValue; + } // createDefault + + /** + * Get Request Status Category from Cache + * @param ctx context + * @param R_StatusCategory_ID id + * @return RStatusCategory + */ + public static MStatusCategory get (Properties ctx, int R_StatusCategory_ID) + { + Integer key = new Integer (R_StatusCategory_ID); + MStatusCategory retValue = (MStatusCategory)s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MStatusCategory (ctx, R_StatusCategory_ID, null); + if (retValue.get_ID() != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache + = new CCache ("R_StatusCategory", 20); + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MStatusCategory.class); + + + /************************************************************************** + * Default Constructor + * @param ctx context + * @param R_StatusCategory_ID id + * @param trxName trx + */ + public MStatusCategory (Properties ctx, int R_StatusCategory_ID, String trxName) + { + super (ctx, R_StatusCategory_ID, trxName); + if (R_StatusCategory_ID == 0) + { + // setName (null); + setIsDefault (false); + } + } // RStatusCategory + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MStatusCategory (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // RStatusCategory + + /** The Status */ + private MStatus[] m_status = null; + + /** + * Get all Status + * @param reload reload + * @return Status array + */ + public MStatus[] getStatus(boolean reload) + { + if (m_status != null && !reload) + return m_status; + String sql = "SELECT * FROM R_Status " + + "WHERE R_StatusCategory_ID=? " + + "ORDER BY SeqNo"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getR_StatusCategory_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MStatus (getCtx(), rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + m_status = new MStatus[list.size ()]; + list.toArray (m_status); + return m_status; + } // getStatus + + /** + * Get Default R_Status_ID + * @return id or 0 + */ + public int getDefaultR_Status_ID() + { + if (m_status == null) + getStatus(false); + for (int i = 0; i < m_status.length; i++) + { + if (m_status[i].isDefault() && m_status[i].isActive()) + return m_status[i].getR_Status_ID(); + } + if (m_status.length > 0 + && m_status[0].isActive()) + return m_status[0].getR_Status_ID(); + return 0; + } // getDefaultR_Status_ID + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("RStatusCategory["); + sb.append (get_ID()).append ("-").append(getName()).append ("]"); + return sb.toString (); + } // toString + +} // RStatusCategory diff --git a/base/src/org/compiere/model/MStorage.java b/base/src/org/compiere/model/MStorage.java new file mode 100644 index 0000000000..367318cd7b --- /dev/null +++ b/base/src/org/compiere/model/MStorage.java @@ -0,0 +1,676 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Inventory Storage Model + * + * @author Jorg Janke + * @version $Id: MStorage.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MStorage extends X_M_Storage +{ + /** + * Get Storage Info + * @param ctx context + * @param M_Locator_ID locator + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID instance + * @param trxName transaction + * @return existing or null + */ + public static MStorage get (Properties ctx, int M_Locator_ID, + int M_Product_ID, int M_AttributeSetInstance_ID, String trxName) + { + MStorage retValue = null; + String sql = "SELECT * FROM M_Storage " + + "WHERE M_Locator_ID=? AND M_Product_ID=? AND "; + if (M_AttributeSetInstance_ID == 0) + sql += "(M_AttributeSetInstance_ID=? OR M_AttributeSetInstance_ID IS NULL)"; + else + sql += "M_AttributeSetInstance_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_Locator_ID); + pstmt.setInt (2, M_Product_ID); + pstmt.setInt (3, M_AttributeSetInstance_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = new MStorage (ctx, rs, trxName); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (SQLException ex) + { + s_log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + if (retValue == null) + s_log.fine("Not Found - M_Locator_ID=" + M_Locator_ID + + ", M_Product_ID=" + M_Product_ID + ", M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID); + else + s_log.fine("M_Locator_ID=" + M_Locator_ID + + ", M_Product_ID=" + M_Product_ID + ", M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID); + return retValue; + } // get + + /** + * Get all Storages for Product with ASI + * @param ctx context + * @param M_Product_ID product + * @param M_Locator_ID locator + * @param FiFo first in-first-out + * @param trxName transaction + * @return existing or null + */ + public static MStorage[] getAllWithASI (Properties ctx, int M_Product_ID, int M_Locator_ID, + boolean FiFo, String trxName) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_Storage " + + "WHERE M_Product_ID=? AND M_Locator_ID=?" + + " AND M_AttributeSetInstance_ID > 0" + + " AND QtyOnHand > 0 " + + "ORDER BY M_AttributeSetInstance_ID"; + if (!FiFo) + sql += " DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_Product_ID); + pstmt.setInt (2, M_Locator_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MStorage (ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (SQLException ex) + { + s_log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + MStorage[] retValue = new MStorage[list.size()]; + list.toArray(retValue); + return retValue; + } // getAllWithASI + + /** + * Get all Storages for Product + * @param ctx context + * @param M_Product_ID product + * @param M_Locator_ID locator + * @param trxName transaction + * @return existing or null + */ + public static MStorage[] getAll (Properties ctx, + int M_Product_ID, int M_Locator_ID, String trxName) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_Storage " + + "WHERE M_Product_ID=? AND M_Locator_ID=?" + + " AND QtyOnHand <> 0 " + + "ORDER BY M_AttributeSetInstance_ID"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_Product_ID); + pstmt.setInt (2, M_Locator_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MStorage (ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (SQLException ex) + { + s_log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + MStorage[] retValue = new MStorage[list.size()]; + list.toArray(retValue); + return retValue; + } // getAll + + + /** + * Get Storage Info for Product across warehouses + * @param ctx context + * @param M_Product_ID product + * @param trxName transaction + * @return existing or null + */ + public static MStorage[] getOfProduct (Properties ctx, int M_Product_ID, String trxName) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_Storage " + + "WHERE M_Product_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_Product_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + list.add(new MStorage (ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (SQLException ex) + { + s_log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + MStorage[] retValue = new MStorage[list.size()]; + list.toArray(retValue); + return retValue; + } // getOfProduct + + /** + * Get Storage Info for Warehouse + * @param ctx context + * @param M_Warehouse_ID + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID instance + * @param M_AttributeSet_ID attribute set + * @param allAttributeInstances if true, all attribute set instances + * @param minGuaranteeDate optional minimum guarantee date if all attribute instances + * @param FiFo first in-first-out + * @param trxName transaction + * @return existing - ordered by location priority (desc) and/or guarantee date + */ + public static MStorage[] getWarehouse (Properties ctx, int M_Warehouse_ID, + int M_Product_ID, int M_AttributeSetInstance_ID, int M_AttributeSet_ID, + boolean allAttributeInstances, Timestamp minGuaranteeDate, + boolean FiFo, String trxName) + { + if (M_Warehouse_ID == 0 || M_Product_ID == 0) + return new MStorage[0]; + + if (M_AttributeSet_ID == 0) + allAttributeInstances = true; + else + { + MAttributeSet mas = MAttributeSet.get(ctx, M_AttributeSet_ID); + if (!mas.isInstanceAttribute()) + allAttributeInstances = true; + } + + ArrayList list = new ArrayList(); + // Specific Attribute Set Instance + String sql = "SELECT s.M_Product_ID,s.M_Locator_ID,s.M_AttributeSetInstance_ID," + + "s.AD_Client_ID,s.AD_Org_ID,s.IsActive,s.Created,s.CreatedBy,s.Updated,s.UpdatedBy," + + "s.QtyOnHand,s.QtyReserved,s.QtyOrdered,s.DateLastInventory " + + "FROM M_Storage s" + + " INNER JOIN M_Locator l ON (l.M_Locator_ID=s.M_Locator_ID) " + + "WHERE l.M_Warehouse_ID=?" + + " AND s.M_Product_ID=?" + + " AND COALESCE(s.M_AttributeSetInstance_ID,0)=? " + + "ORDER BY l.PriorityNo DESC, M_AttributeSetInstance_ID"; + if (!FiFo) + sql += " DESC"; + // All Attribute Set Instances + if (allAttributeInstances) + { + sql = "SELECT s.M_Product_ID,s.M_Locator_ID,s.M_AttributeSetInstance_ID," + + "s.AD_Client_ID,s.AD_Org_ID,s.IsActive,s.Created,s.CreatedBy,s.Updated,s.UpdatedBy," + + "s.QtyOnHand,s.QtyReserved,s.QtyOrdered,s.DateLastInventory " + + "FROM M_Storage s" + + " INNER JOIN M_Locator l ON (l.M_Locator_ID=s.M_Locator_ID)" + + " LEFT OUTER JOIN M_AttributeSetInstance asi ON (s.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID) " + + "WHERE l.M_Warehouse_ID=?" + + " AND s.M_Product_ID=? "; + if (minGuaranteeDate != null) + { + sql += "AND (asi.GuaranteeDate IS NULL OR asi.GuaranteeDate>?) " + + "ORDER BY asi.GuaranteeDate, M_AttributeSetInstance_ID"; + if (!FiFo) + sql += " DESC"; + sql += ", l.PriorityNo DESC, s.QtyOnHand DESC"; + } + else + { + sql += "ORDER BY l.PriorityNo DESC, l.M_Locator_ID, s.M_AttributeSetInstance_ID"; + if (!FiFo) + sql += " DESC"; + sql += ", s.QtyOnHand DESC"; + } + } + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, M_Warehouse_ID); + pstmt.setInt(2, M_Product_ID); + if (!allAttributeInstances) + pstmt.setInt(3, M_AttributeSetInstance_ID); + else if (minGuaranteeDate != null) + pstmt.setTimestamp(3, minGuaranteeDate); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add (new MStorage (ctx, rs, trxName)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MStorage[] retValue = new MStorage[list.size()]; + list.toArray(retValue); + return retValue; + } // getWarehouse + + + /** + * Create or Get Storage Info + * @param ctx context + * @param M_Locator_ID locator + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID instance + * @param trxName transaction + * @return existing/new or null + */ + public static MStorage getCreate (Properties ctx, int M_Locator_ID, + int M_Product_ID, int M_AttributeSetInstance_ID, String trxName) + { + if (M_Locator_ID == 0) + throw new IllegalArgumentException("M_Locator_ID=0"); + if (M_Product_ID == 0) + throw new IllegalArgumentException("M_Product_ID=0"); + MStorage retValue = get(ctx, M_Locator_ID, M_Product_ID, M_AttributeSetInstance_ID, trxName); + if (retValue != null) + return retValue; + + // Insert row based on locator + MLocator locator = new MLocator (ctx, M_Locator_ID, trxName); + if (locator.get_ID() != M_Locator_ID) + throw new IllegalArgumentException("Not found M_Locator_ID=" + M_Locator_ID); + // + retValue = new MStorage (locator, M_Product_ID, M_AttributeSetInstance_ID); + retValue.save(trxName); + s_log.fine("New " + retValue); + return retValue; + } // getCreate + + + /** + * Update Storage Info add. + * Called from MProjectIssue + * @param ctx context + * @param M_Warehouse_ID warehouse + * @param M_Locator_ID locator + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID AS Instance + * @param reservationAttributeSetInstance_ID reservation AS Instance + * @param diffQtyOnHand add on hand + * @param diffQtyReserved add reserved + * @param diffQtyOrdered add order + * @param trxName transaction + * @return true if updated + */ + public static boolean add (Properties ctx, int M_Warehouse_ID, int M_Locator_ID, + int M_Product_ID, int M_AttributeSetInstance_ID, int reservationAttributeSetInstance_ID, + BigDecimal diffQtyOnHand, + BigDecimal diffQtyReserved, BigDecimal diffQtyOrdered, String trxName) + { + MStorage storage = null; + StringBuffer diffText = new StringBuffer("("); + + // Get Storage + if (storage == null) + storage = getCreate (ctx, M_Locator_ID, + M_Product_ID, M_AttributeSetInstance_ID, trxName); + // Verify + if (storage.getM_Locator_ID() != M_Locator_ID + && storage.getM_Product_ID() != M_Product_ID + && storage.getM_AttributeSetInstance_ID() != M_AttributeSetInstance_ID) + { + s_log.severe ("No Storage found - M_Locator_ID=" + M_Locator_ID + + ",M_Product_ID=" + M_Product_ID + ",ASI=" + M_AttributeSetInstance_ID); + return false; + } + MStorage storage0 = null; + if (M_AttributeSetInstance_ID != reservationAttributeSetInstance_ID) + { + storage0 = get(ctx, M_Locator_ID, + M_Product_ID, reservationAttributeSetInstance_ID, trxName); + if (storage0 == null) // create if not existing - should not happen + { + MWarehouse wh = MWarehouse.get(ctx, M_Warehouse_ID); + int xM_Locator_ID = wh.getDefaultLocator().getM_Locator_ID(); + storage0 = getCreate (ctx, xM_Locator_ID, + M_Product_ID, reservationAttributeSetInstance_ID, trxName); + } + } + boolean changed = false; + if (diffQtyOnHand != null && diffQtyOnHand.signum() != 0) + { + storage.setQtyOnHand (storage.getQtyOnHand().add (diffQtyOnHand)); + diffText.append("OnHand=").append(diffQtyOnHand); + changed = true; + } + if (diffQtyReserved != null && diffQtyReserved.signum() != 0) + { + if (storage0 == null) + storage.setQtyReserved (storage.getQtyReserved().add (diffQtyReserved)); + else + storage0.setQtyReserved (storage0.getQtyReserved().add (diffQtyReserved)); + diffText.append(" Reserved=").append(diffQtyReserved); + changed = true; + } + if (diffQtyOrdered != null && diffQtyOrdered.signum() != 0) + { + if (storage0 == null) + storage.setQtyOrdered (storage.getQtyOrdered().add (diffQtyOrdered)); + else + storage0.setQtyOrdered (storage0.getQtyOrdered().add (diffQtyOrdered)); + diffText.append(" Ordered=").append(diffQtyOrdered); + changed = true; + } + if (changed) + { + diffText.append(") -> ").append(storage.toString()); + s_log.fine(diffText.toString()); + if (storage0 != null) + storage0.save(trxName); // No AttributeSetInstance (reserved/ordered) + return storage.save (trxName); + } + + return true; + } // add + + + /************************************************************************** + * Get Location with highest Locator Priority and a sufficient OnHand Qty + * @param M_Warehouse_ID warehouse + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID asi + * @param Qty qty + * @param trxName transaction + * @return id + */ + public static int getM_Locator_ID (int M_Warehouse_ID, + int M_Product_ID, int M_AttributeSetInstance_ID, BigDecimal Qty, + String trxName) + { + int M_Locator_ID = 0; + int firstM_Locator_ID = 0; + String sql = "SELECT s.M_Locator_ID, s.QtyOnHand " + + "FROM M_Storage s" + + " INNER JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID)" + + " INNER JOIN M_Product p ON (s.M_Product_ID=p.M_Product_ID)" + + " LEFT OUTER JOIN M_AttributeSet mas ON (p.M_AttributeSet_ID=mas.M_AttributeSet_ID) " + + "WHERE l.M_Warehouse_ID=?" + + " AND s.M_Product_ID=?" + + " AND (mas.IsInstanceAttribute IS NULL OR mas.IsInstanceAttribute='N' OR s.M_AttributeSetInstance_ID=?)" + + " AND l.IsActive='Y' " + + "ORDER BY l.PriorityNo DESC, s.QtyOnHand DESC"; + + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, M_Warehouse_ID); + pstmt.setInt(2, M_Product_ID); + pstmt.setInt(3, M_AttributeSetInstance_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + BigDecimal QtyOnHand = rs.getBigDecimal(2); + if (QtyOnHand != null && Qty.compareTo(QtyOnHand) <= 0) + { + M_Locator_ID = rs.getInt(1); + break; + } + if (firstM_Locator_ID == 0) + firstM_Locator_ID = rs.getInt(1); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + s_log.log(Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close(); + } + catch (SQLException ex1) + { + } + pstmt = null; + if (M_Locator_ID != 0) + return M_Locator_ID; + return firstM_Locator_ID; + } // getM_Locator_ID + + /** + * Get Available Qty. + * The call is accurate only if there is a storage record + * and assumes that the product is stocked + * @param M_Warehouse_ID wh + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID masi + * @param trxName transaction + * @return qty available (QtyOnHand-QtyReserved) or null + */ + public static BigDecimal getQtyAvailable (int M_Warehouse_ID, + int M_Product_ID, int M_AttributeSetInstance_ID, String trxName) + { + BigDecimal retValue = null; + PreparedStatement pstmt = null; + String sql = "SELECT SUM(QtyOnHand-QtyReserved) " + + "FROM M_Storage s" + + " INNER JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID) " + + "WHERE s.M_Product_ID=?" // #1 + + " AND l.M_Warehouse_ID=?"; + if (M_AttributeSetInstance_ID != 0) + sql += " AND M_AttributeSetInstance_ID=?"; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, M_Product_ID); + pstmt.setInt (2, M_Warehouse_ID); + if (M_AttributeSetInstance_ID != 0) + pstmt.setInt(3, M_AttributeSetInstance_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + retValue = rs.getBigDecimal(1); + if (rs.wasNull()) + retValue = null; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + s_log.fine("M_Warehouse_ID=" + M_Warehouse_ID + + ",M_Product_ID=" + M_Product_ID + " = " + retValue); + return retValue; + } // getQtyAvailable + + + /************************************************************************** + * Persistency Constructor + * @param ctx context + * @param ignored ignored + * @param trxName transaction + */ + public MStorage (Properties ctx, int ignored, String trxName) + { + super(ctx, 0, trxName); + if (ignored != 0) + throw new IllegalArgumentException("Multi-Key"); + // + setQtyOnHand (Env.ZERO); + setQtyOrdered (Env.ZERO); + setQtyReserved (Env.ZERO); + } // MStorage + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MStorage (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MStorage + + /** + * Full NEW Constructor + * @param locator (parent) locator + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID attribute + */ + private MStorage (MLocator locator, int M_Product_ID, int M_AttributeSetInstance_ID) + { + this (locator.getCtx(), 0, locator.get_TrxName()); + setClientOrg(locator); + setM_Locator_ID (locator.getM_Locator_ID()); + setM_Product_ID (M_Product_ID); + setM_AttributeSetInstance_ID (M_AttributeSetInstance_ID); + } // MStorage + + /** Log */ + private static CLogger s_log = CLogger.getCLogger (MStorage.class); + /** Warehouse */ + private int m_M_Warehouse_ID = 0; + + /** + * Change Qty OnHand + * @param qty quantity + * @param add add if true + */ + public void changeQtyOnHand (BigDecimal qty, boolean add) + { + if (qty == null || qty.signum() == 0) + return; + if (add) + setQtyOnHand(getQtyOnHand().add(qty)); + else + setQtyOnHand(getQtyOnHand().subtract(qty)); + } // changeQtyOnHand + + /** + * Get M_Warehouse_ID of Locator + * @return warehouse + */ + public int getM_Warehouse_ID() + { + if (m_M_Warehouse_ID == 0) + { + MLocator loc = MLocator.get(getCtx(), getM_Locator_ID()); + m_M_Warehouse_ID = loc.getM_Warehouse_ID(); + } + return m_M_Warehouse_ID; + } // getM_Warehouse_ID + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("MStorage[") + .append("M_Locator_ID=").append(getM_Locator_ID()) + .append(",M_Product_ID=").append(getM_Product_ID()) + .append(",M_AttributeSetInstance_ID=").append(getM_AttributeSetInstance_ID()) + .append(": OnHand=").append(getQtyOnHand()) + .append(",Reserved=").append(getQtyReserved()) + .append(",Ordered=").append(getQtyOrdered()) + .append("]"); + return sb.toString(); + } // toString + +} // MStorage diff --git a/base/src/org/compiere/model/MStore.java b/base/src/org/compiere/model/MStore.java new file mode 100644 index 0000000000..b3d240a583 --- /dev/null +++ b/base/src/org/compiere/model/MStore.java @@ -0,0 +1,647 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.rmi.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.db.*; +import org.compiere.interfaces.*; +import org.compiere.util.*; + +/** + * Web Store + * @author Jorg Janke + * @version $Id: MStore.java,v 1.4 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MStore extends X_W_Store +{ + /** + * Get WStore from Cache + * @param ctx context + * @param W_Store_ID id + * @return WStore + */ + public static MStore get (Properties ctx, int W_Store_ID) + { + Integer key = new Integer (W_Store_ID); + MStore retValue = (MStore) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MStore (ctx, W_Store_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** + * Get WStore from Cache + * @param ctx context + * @param contextPath web server context path + * @return WStore + */ + public static MStore get (Properties ctx, String contextPath) + { + MStore wstore = null; + Iterator it = s_cache.values().iterator(); + while (it.hasNext()) + { + wstore = (MStore)it.next(); + if (wstore.getWebContext().equals(contextPath)) + return wstore; + } + + // Search by context + PreparedStatement pstmt = null; + String sql = "SELECT * FROM W_Store WHERE WebContext=?"; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setString(1, contextPath); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + wstore = new MStore (ctx, rs, null); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // Try client + if (wstore == null) + { + sql = "SELECT * FROM W_Store WHERE AD_Client_ID=? AND IsActive='Y' ORDER BY W_Store_ID"; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, Env.getAD_Client_ID(ctx)); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + wstore = new MStore (ctx, rs, null); + s_log.warning("Context " + contextPath + + " Not found - Found via AD_Client_ID=" + Env.getAD_Client_ID(ctx)); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + } + // Nothing + if (wstore == null) + return null; + + // Save + Integer key = new Integer (wstore.getW_Store_ID()); + s_cache.put (key, wstore); + return wstore; + } // get + + /** + * Get active Web Stores of Clieny + * @param client client + * @return array of web stores + */ + public static MStore[] getOfClient (MClient client) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM W_Store WHERE AD_Client_ID=? AND IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, client.get_TrxName()); + pstmt.setInt (1, client.getAD_Client_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MStore (client.getCtx(), rs, client.get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + MStore[] retValue = new MStore[list.size ()]; + list.toArray (retValue); + return retValue; + } // getOfClient + + /** + * Get Active Web Stores + * @return cached web stores + */ + public static MStore[] getActive() + { + s_log.info(""); + try + { + Collection cc = s_cache.values(); + Object[] oo = cc.toArray(); + for (int i = 0; i < oo.length; i++) + s_log.info(i + ": " + oo[i]); + MStore[] retValue = new MStore[oo.length]; + for (int i = 0; i < oo.length; i++) + retValue[i] = (MStore)oo[i]; + return retValue; + } + catch (Exception e) + { + s_log.severe(e.toString()); + } + return new MStore[]{}; + } // getActive + + /** Cache */ + private static CCache s_cache + = new CCache("W_Store", 2); + /** Logger */ + private static CLogger s_log = CLogger.getCLogger (MStore.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param W_Store_ID id + * @param trxName trx + */ + public MStore (Properties ctx, int W_Store_ID, String trxName) + { + super (ctx, W_Store_ID, trxName); + if (W_Store_ID == 0) + { + setIsDefault (false); + setIsMenuAssets (true); // Y + setIsMenuContact (true); // Y + setIsMenuInterests (true); // Y + setIsMenuInvoices (true); // Y + setIsMenuOrders (true); // Y + setIsMenuPayments (true); // Y + setIsMenuRegistrations (true); // Y + setIsMenuRequests (true); // Y + setIsMenuRfQs (true); // Y + setIsMenuShipments (true); // Y + + // setC_PaymentTerm_ID (0); + // setM_PriceList_ID (0); + // setM_Warehouse_ID (0); + // setName (null); + // setSalesRep_ID (0); + // setURL (null); + // setWebContext (null); + } + } // MWStore + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MStore (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MWStore + + /** The Messages */ + private MMailMsg[] m_msgs = null; + + /** + * Get Web Context + * @param full if true fully qualified + * @return web context + */ + public String getWebContext(boolean full) + { + if (!full) + return super.getURL(); + String url = super.getURL(); + if (url == null || url.length() == 0) + url = "http://localhost"; + if (url.endsWith("/")) + url += url.substring(0, url.length()-1); + return url + getWebContext(); // starts with / + } // getWebContext + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("WStore["); + sb.append(getWebContext(true)) + .append ("]"); + return sb.toString (); + } // toString + + + /** + * Before Save + * @param newRecord new + * @return true if can be saved + */ + protected boolean beforeSave (boolean newRecord) + { + // Context to start with / + if (!getWebContext().startsWith("/")) + setWebContext("/" + getWebContext()); + + // Org to Warehouse + if (newRecord || is_ValueChanged("M_Warehouse_ID") || getAD_Org_ID() == 0) + { + MWarehouse wh = new MWarehouse (getCtx(), getM_Warehouse_ID(), get_TrxName()); + setAD_Org_ID(wh.getAD_Org_ID()); + } + + String url = getURL(); + if (url == null) + url = ""; + boolean urlOK = url.startsWith("http://") || url.startsWith("https://"); + if (!urlOK) // || url.indexOf("localhost") != -1) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "URL") + + " - e.g. http://www.adempiere.org"); + return false; + } + + return true; + } // beforeSave + + + /************ + * Create EMail from Request User + * @param to recipient + * @param subject sunject + * @param message nessage + * @return EMail + */ + public EMail createEMail (String to, + String subject, String message) + { + if (to == null || to.length() == 0) + { + log.warning("No To"); + return null; + } + // + EMail email = null; + MClient client = MClient.get(getCtx(), getAD_Client_ID()); + if (client.isServerEMail() && Ini.isClient()) + { + Server server = CConnection.get().getServer(); + try + { + if (server != null) + { // See ServerBean + email = server.createEMail(getCtx(), getAD_Client_ID(), + to, subject, message); + } + else + log.log(Level.WARNING, "No AppsServer"); + } + catch (RemoteException ex) + { + log.log(Level.SEVERE, getName() + " - AppsServer error", ex); + } + } + String from = getWStoreEMail(); + if (from == null || from.length() == 0) + from = client.getRequestEMail(); + if (email == null) + email = new EMail (client, + from, to, + subject, message); + // Authorizetion + if (client.isSmtpAuthorization()) + { + if (getWStoreEMail() != null && getWStoreUser() != null && getWStoreUserPW() != null) + email.createAuthenticator (getWStoreUser(), getWStoreUserPW()); + else + email.createAuthenticator (client.getRequestUser(), client.getRequestUserPW()); + } + // Bcc + email.addBcc(from); + // + return email; + } // createEMail + + /** + * Send EMail from WebStore User + * @param to recipient email address + * @param subject subject + * @param message message - add header & footer + * @return true if sent + */ + public boolean sendEMail (String to, + String subject, String message) + { + if (message == null || message.length() == 0) + { + log.warning("No Message"); + return false; + } + StringBuffer msgText = new StringBuffer(); + if (getEMailHeader() != null) + msgText.append(getEMailHeader()); + msgText.append(message); + if (getEMailFooter() != null) + msgText.append(getEMailFooter()); + // + EMail email = createEMail(to, subject, msgText.toString()); + if (email == null) + return false; + + try + { + String msg = email.send(); + if (EMail.SENT_OK.equals (email.send ())) + { + log.info("Sent EMail " + subject + " to " + to); + return true; + } + else + { + log.warning("Could NOT Send Email: " + subject + + " to " + to + ": " + msg + + " (" + getName() + ")"); + return false; + } + } + catch (Exception ex) + { + log.severe(getName() + " - " + ex.getLocalizedMessage()); + return false; + } + } // sendEMail + + /** + * Test WebStore EMail + * @return OK or error + */ + public String testEMail() + { + if (getWStoreEMail() == null || getWStoreEMail().length() == 0) + return "No Web Store EMail for " + getName(); + // + EMail email = createEMail (getWStoreEMail(), + "Adempiere WebStore EMail Test", + "Adempiere WebStore EMail Test: " + toString()); + if (email == null) + return "Could not create Web Store EMail: " + getName(); + try + { + String msg = email.send(); + if (EMail.SENT_OK.equals (email.send ())) + { + log.info("Sent Test EMail to " + getWStoreEMail()); + return "OK"; + } + else + { + log.warning("Could NOT send Test Email to " + + getWStoreEMail() + ": " + msg); + return msg; + } + } + catch (Exception ex) + { + log.severe(getName() + " - " + ex.getLocalizedMessage()); + return ex.getLocalizedMessage(); + } + } // testEMail + + /** + * Get Messages + * @param reload reload data + * @return array of messages + */ + public MMailMsg[] getMailMsgs (boolean reload) + { + if (m_msgs != null && !reload) + return m_msgs; + ArrayList list = new ArrayList(); + // + String sql = "SELECT * FROM W_MailMsg WHERE W_Store_ID=? ORDER BY MailMsgType"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getW_Store_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MMailMsg (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + m_msgs = new MMailMsg[list.size ()]; + list.toArray (m_msgs); + return m_msgs; + } // getMailMsgs + + /** + * Get Mail Msg and if not found create it + * @param MailMsgType mail message type + * @return message + */ + public MMailMsg getMailMsg (String MailMsgType) + { + if (m_msgs == null) + getMailMsgs(false); + + // existing msg + for (int i = 0; i < m_msgs.length; i++) + { + if (m_msgs[i].getMailMsgType().equals(MailMsgType)) + return m_msgs[i]; + } + + // create missing + if (createMessages() == 0) + { + log.severe("Not created/found: " + MailMsgType); + return null; + } + getMailMsgs(true); + // try again + for (int i = 0; i < m_msgs.length; i++) + { + if (m_msgs[i].getMailMsgType().equals(MailMsgType)) + return m_msgs[i]; + } + + // nothing found + log.severe("Not found: " + MailMsgType); + return null; + } // getMailMsg + + + /************************************************************************** + * Create (missing) Messages + * @return number of messages created + */ + public int createMessages() + { + String[][] initMsgs = new String[][] + { + new String[]{MMailMsg.MAILMSGTYPE_UserVerification, + "EMail Verification", + "EMail Verification ", + "Dear ", + "\nYou requested the Verification Code: ", + "\nPlease enter the verification code to get access."}, + new String[]{MMailMsg.MAILMSGTYPE_UserPassword, + "Password Request", + "Password Request ", + "Dear ", + "\nWe received a 'Send Password' request from: ", + "\nYour password is: "}, + new String[]{MMailMsg.MAILMSGTYPE_Subscribe, + "Subscription New", + "New Subscription ", + "Dear ", + "\nYou requested to be added to the list: ", + "\nThanks for your interest."}, + new String[]{MMailMsg.MAILMSGTYPE_UnSubscribe, + "Subscription Removed", + "Remove Subscription ", + "Dear ", + "\nYou requested to be removed from the list: ", + "\nSorry to see you go. This is effictive immediately."}, + new String[]{MMailMsg.MAILMSGTYPE_OrderAcknowledgement, + "Order Acknowledgement", + "Adempiere Web - Order ", + "Dear ", + "\nThank you for your purchase: ", + "\nYou can view your Orders, Invoices, Payments in the Web Store." + + "\nFrom there, you also download your Assets (Documentation, etc.)"}, + new String[]{MMailMsg.MAILMSGTYPE_PaymentAcknowledgement, + "Payment Success", + "Adempiere Web - Payment ", + "Dear ", + "\nThank you for your payment of ", + "\nYou can view your Orders, Invoices, Payments in the Web Store." + + "\nFrom there you also download your Assets (Documentation, etc.)"}, + new String[]{MMailMsg.MAILMSGTYPE_PaymentError, + "Payment Error", + "Adempiere Web - Declined Payment ", + "Dear ", + "\nUnfortunately your payment was declined: ", + "\nPlease check and try again. You can pay later by going to 'My Orders' or 'My Invoices' - or by directly creating a payment in 'My Payments'"}, + new String[]{MMailMsg.MAILMSGTYPE_Request, + "Request", + "Request ", + "Dear ", + "\nThank you for your request: " + MRequest.SEPARATOR, + MRequest.SEPARATOR + "\nPlease check back for updates."}, + + new String[]{MMailMsg.MAILMSGTYPE_UserAccount, + "Welcome Message", + "Welcome", + "Welcome to our Web Store", + "This is the Validation Code to access information:", + ""}, + }; + + if (m_msgs == null) + getMailMsgs(false); + if (m_msgs.length == initMsgs.length) // may create a problem if user defined own ones - unlikely + return 0; // nothing to do + + int counter = 0; + for (int i = 0; i < initMsgs.length; i++) + { + boolean found = false; + for (int m = 0; m < m_msgs.length; m++) + { + if (initMsgs[i][0].equals(m_msgs[m].getMailMsgType())) + { + found = true; + break; + } + } // for all existing msgs + if (found) + continue; + MMailMsg msg = new MMailMsg(this, initMsgs[i][0], initMsgs[i][1], + initMsgs[i][2], initMsgs[i][3], initMsgs[i][4], initMsgs[i][5]); + if (msg.save()) + counter++; + else + log.severe("Not created MailMsgType=" + initMsgs[i][0]); + } // for all initMsgs + + log.info("#" + counter); + m_msgs = null; // reset + return counter; + } // createMessages + +} // MWStore diff --git a/base/src/org/compiere/model/MTask.java b/base/src/org/compiere/model/MTask.java new file mode 100644 index 0000000000..751c13d078 --- /dev/null +++ b/base/src/org/compiere/model/MTask.java @@ -0,0 +1,139 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Operating Task Model + * + * @author Jorg Janke + * @version $Id: MTask.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MTask extends X_AD_Task +{ + /** + * Standard Constructor + * @param ctx context + * @param AD_Task_ID id + * @param trxName trx + */ + public MTask (Properties ctx, int AD_Task_ID, String trxName) + { + super (ctx, AD_Task_ID, trxName); + } // MTask + + /** + * Load Cosntructor + * @param ctx ctx + * @param rs result set + * @param trxName trx + */ + public MTask (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MTask + + /** Actual Task */ + private Task m_task = null; + + /** + * Execute Task and wait + * @return execution info + */ + public String execute() + { + String cmd = Msg.parseTranslation(Env.getCtx(), getOS_Command()).trim(); + if (cmd == null || cmd.equals("")) + return "Cannot execute '" + getOS_Command() + "'"; + // + if (isServerProcess()) + return executeRemote(cmd); + return executeLocal(cmd); + } // execute + + /** + * Execute Task locally and wait + * @param cmd command + * @return execution info + */ + public String executeLocal(String cmd) + { + log.config(cmd); + if (m_task != null && m_task.isAlive()) + m_task.interrupt(); + + m_task = new Task(cmd); + m_task.start(); + + StringBuffer sb = new StringBuffer(); + while (true) + { + // Give it a bit of time + try + { + Thread.sleep(500); + } + catch (InterruptedException ioe) + { + log.log(Level.SEVERE, cmd, ioe); + } + // Info to user + sb.append(m_task.getOut()) + .append("\n-----------\n") + .append(m_task.getErr()) + .append("\n-----------"); + + // Are we done? + if (!m_task.isAlive()) + break; + } + log.config("done"); + return sb.toString(); + } // executeLocal + + /** + * Execute Task locally and wait + * @param cmd command + * @return execution info + */ + public String executeRemote(String cmd) + { + log.config(cmd); + return "Remote:\n"; + } // executeRemote + + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MTask["); + sb.append(get_ID()) + .append("-").append(getName()) + .append(";Server=").append(isServerProcess()) + .append(";").append(getOS_Command()) + .append ("]"); + return sb.toString (); + } // toString + +} // MTask diff --git a/base/src/org/compiere/model/MTax.java b/base/src/org/compiere/model/MTax.java new file mode 100644 index 0000000000..503ac43eca --- /dev/null +++ b/base/src/org/compiere/model/MTax.java @@ -0,0 +1,359 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Tax Model + * + * @author Jorg Janke + * @version $Id: MTax.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MTax extends X_C_Tax +{ + /** + * Get All Tax codes (for AD_Client) + * @param ctx context + * @return MTax + */ + public static MTax[] getAll (Properties ctx) + { + int AD_Client_ID = Env.getAD_Client_ID(ctx); + Integer key = new Integer (AD_Client_ID); + MTax[] retValue = (MTax[])s_cacheAll.get(key); + if (retValue != null) + return retValue; + + // Create it + String sql = "SELECT * FROM C_Tax WHERE AD_Client_ID=?" + + "ORDER BY C_Country_ID, C_Region_ID, To_Country_ID, To_Region_ID"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, AD_Client_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MTax tax = new MTax(ctx, rs, null); + s_cache.put (new Integer(tax.getC_Tax_ID()), tax); + list.add (tax); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + // Create Array + retValue = new MTax[list.size ()]; + list.toArray (retValue); + // + s_cacheAll.put(key, retValue); + return retValue; + } // getAll + + + /** + * Get Tax from Cache + * @param ctx context + * @param C_Tax_ID id + * @return MTax + */ + public static MTax get (Properties ctx, int C_Tax_ID) + { + Integer key = new Integer (C_Tax_ID); + MTax retValue = (MTax) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MTax (ctx, C_Tax_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("C_Tax", 5); + /** Cache of Client */ + private static CCache s_cacheAll = new CCache("C_Tax", 5); + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MTax.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param C_Tax_ID id + * @param trxName transaction + */ + public MTax (Properties ctx, int C_Tax_ID, String trxName) + { + super (ctx, C_Tax_ID, trxName); + if (C_Tax_ID == 0) + { + // setC_Tax_ID (0); PK + setIsDefault (false); + setIsDocumentLevel (true); + setIsSummary (false); + setIsTaxExempt (false); + // setName (null); + setRate (Env.ZERO); + setRequiresTaxCertificate (false); + // setC_TaxCategory_ID (0); // FK + setSOPOType (SOPOTYPE_Both); + setValidFrom (TimeUtil.getDay(1990,1,1)); + setIsSalesTax(false); + } + } // MTax + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MTax (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MTax + + /** + * New Constructor + * @param ctx + * @param Name + * @param Rate + * @param C_TaxCategory_ID + * @param trxName transaction + */ + public MTax (Properties ctx, String Name, BigDecimal Rate, int C_TaxCategory_ID, String trxName) + { + this (ctx, 0, trxName); + setName (Name); + setRate (Rate == null ? Env.ZERO : Rate); + setC_TaxCategory_ID (C_TaxCategory_ID); // FK + } // MTax + + /** 100 */ + private static BigDecimal ONEHUNDRED = new BigDecimal(100); + /** Child Taxes */ + private MTax[] m_childTaxes = null; + /** Postal Codes */ + private MTaxPostal[] m_postals = null; + + + /** + * Get Child Taxes + * @param requery reload + * @return array of taxes or null + */ + public MTax[] getChildTaxes (boolean requery) + { + if (!isSummary()) + return null; + if (m_childTaxes != null && !requery) + return m_childTaxes; + // + String sql = "SELECT * FROM C_Tax WHERE Parent_Tax_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_Tax_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MTax(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_childTaxes = new MTax[list.size ()]; + list.toArray (m_childTaxes); + return m_childTaxes; + } // getChildTaxes + + /** + * Get Postal Qualifiers + * @param requery requery + * @return array of postal codes + */ + public MTaxPostal[] getPostals (boolean requery) + { + if (m_postals != null && !requery) + return m_postals; + + String sql = "SELECT * FROM C_TaxPostal WHERE C_Tax_ID=? ORDER BY Postal, Postal_To"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_Tax_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + } + rs.close (); + pstmt.close (); + pstmt = null; + } catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } catch (Exception e) + { + pstmt = null; + } + + m_postals = new MTaxPostal[list.size ()]; + list.toArray (m_postals); + return m_postals; + } // getPostals + + /** + * Do we have Postal Codes + * @return true if postal codes exist + */ + public boolean isPostal() + { + return getPostals(false).length > 0; + } // isPostal + + /** + * Is Zero Tax + * @return true if tax rate is 0 + */ + public boolean isZeroTax() + { + return Env.ZERO.compareTo(getRate()) == 0; + } // isZeroTax + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("MTax["); + sb.append(get_ID()).append(",").append(getName()) + .append(", SO/PO=").append(getSOPOType()) + .append(",Rate=").append(getRate()) + .append(",C_TaxCategory_ID=").append(getC_TaxCategory_ID()) + .append(",Summary=").append(isSummary()) + .append(",Parent=").append(getParent_Tax_ID()) + .append(",Country=").append(getC_Country_ID()).append("|").append(getTo_Country_ID()) + .append(",Region=").append(getC_Region_ID()).append("|").append(getTo_Region_ID()) + .append("]"); + return sb.toString(); + } // toString + + + /** + * Calculate Tax - no rounding + * @param amount amount + * @param taxIncluded if true tax is calculated from gross otherwise from net + * @param scale scale + * @return tax amount + */ + public BigDecimal calculateTax (BigDecimal amount, boolean taxIncluded, int scale) + { + // Null Tax + if (isZeroTax()) + return Env.ZERO; + + BigDecimal multiplier = getRate().divide(ONEHUNDRED, 12, BigDecimal.ROUND_HALF_UP); + + BigDecimal tax = null; + if (!taxIncluded) // $100 * 6 / 100 == $6 == $100 * 0.06 + { + tax = amount.multiply (multiplier); + } + else // $106 - ($106 / (100+6)/100) == $6 == $106 - ($106/1.06) + { + multiplier = multiplier.add(Env.ONE); + BigDecimal base = amount.divide(multiplier, 12, BigDecimal.ROUND_HALF_UP); + tax = amount.subtract(base); + } + BigDecimal finalTax = tax.setScale(scale, BigDecimal.ROUND_HALF_UP); + log.fine("calculateTax " + amount + + " (incl=" + taxIncluded + ",mult=" + multiplier + ",scale=" + scale + + ") = " + finalTax + " [" + tax + "]"); + return finalTax; + } // calculateTax + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (newRecord & success) + insert_Accounting("C_Tax_Acct", "C_AcctSchema_Default", null); + + return success; + } // afterSave + + /** + * Before Delete + * @return true + */ + protected boolean beforeDelete () + { + return delete_Accounting("C_Tax_Acct"); + } // beforeDelete + +} // MTax diff --git a/base/src/org/compiere/model/MTaxCategory.java b/base/src/org/compiere/model/MTaxCategory.java new file mode 100644 index 0000000000..fd40293d5d --- /dev/null +++ b/base/src/org/compiere/model/MTaxCategory.java @@ -0,0 +1,57 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Tax Category Model + * + * @author Jorg Janke + * @version $Id: MTaxCategory.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MTaxCategory extends X_C_TaxCategory +{ + /** + * Standard Constructor + * @param ctx context + * @param C_TaxCategory_ID id + * @param trxName trx + */ + public MTaxCategory (Properties ctx, int C_TaxCategory_ID, String trxName) + { + super (ctx, C_TaxCategory_ID, trxName); + if (C_TaxCategory_ID == 0) + { + // setName (null); + setIsDefault (false); + } + } // MTaxCategory + + /** + * Load Constructor + * @param ctx context + * @param rs resukt set + * @param trxName trx + */ + public MTaxCategory (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MTaxCategory + +} // MTaxCategory diff --git a/base/src/org/compiere/model/MTaxDeclaration.java b/base/src/org/compiere/model/MTaxDeclaration.java new file mode 100644 index 0000000000..bb25f9c74c --- /dev/null +++ b/base/src/org/compiere/model/MTaxDeclaration.java @@ -0,0 +1,67 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Tax Declaration Model + * + * @author Jorg Janke + * @version $Id: MTaxDeclaration.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MTaxDeclaration extends X_C_TaxDeclaration +{ + /** + * Standard Constructors + * @param ctx context + * @param C_TaxDeclaration_ID ic + * @param trxName trx + */ + public MTaxDeclaration (Properties ctx, int C_TaxDeclaration_ID, String trxName) + { + super (ctx, C_TaxDeclaration_ID, trxName); + } // MTaxDeclaration + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MTaxDeclaration (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MTaxDeclaration + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (is_ValueChanged("DateFrom")) + setDateFrom(TimeUtil.getDay(getDateFrom())); + if (is_ValueChanged("DateTo")) + setDateTo(TimeUtil.getDay(getDateTo())); + return true; + } // beforeSave + +} // MTaxDeclaration diff --git a/base/src/org/compiere/model/MTaxDeclarationAcct.java b/base/src/org/compiere/model/MTaxDeclarationAcct.java new file mode 100644 index 0000000000..602ee5c686 --- /dev/null +++ b/base/src/org/compiere/model/MTaxDeclarationAcct.java @@ -0,0 +1,67 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Tax Tax Declaration Accounting Model + * + * @author Jorg Janke + * @version $Id: MTaxDeclarationAcct.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MTaxDeclarationAcct extends X_C_TaxDeclarationAcct +{ + /** + * Standard Constructor + * @param ctx ctx + * @param C_TaxDeclarationAcct_ID id + * @param trxName trc + */ + public MTaxDeclarationAcct (Properties ctx, int C_TaxDeclarationAcct_ID, String trxName) + { + super (ctx, C_TaxDeclarationAcct_ID, trxName); + } // MTaxDeclarationAcct + + /** + * Load Constructor + * @param ctx ctx + * @param rs result set + * @param trxName trx + */ + public MTaxDeclarationAcct (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MTaxDeclarationAcct + + /** + * Parent Constructor + * @param parent parent + * @param fact fact + */ + public MTaxDeclarationAcct (MTaxDeclaration parent, MFactAcct fact) + { + super (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(fact); + setC_TaxDeclaration_ID(parent.getC_TaxDeclaration_ID()); + // + setFact_Acct_ID (fact.getFact_Acct_ID()); + setC_AcctSchema_ID (fact.getC_AcctSchema_ID()); + } // MTaxDeclarationAcct + +} // MTaxDeclarationAcct diff --git a/base/src/org/compiere/model/MTaxDeclarationLine.java b/base/src/org/compiere/model/MTaxDeclarationLine.java new file mode 100644 index 0000000000..e01cac990f --- /dev/null +++ b/base/src/org/compiere/model/MTaxDeclarationLine.java @@ -0,0 +1,116 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import org.compiere.util.*; + +/** + * Tax Declaration Line Model + * + * @author Jorg Janke + * @version $Id: MTaxDeclarationLine.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MTaxDeclarationLine extends X_C_TaxDeclarationLine +{ + /** + * Standard Constructor + * @param ctx ctx + * @param C_TaxDeclarationLine_ID id + * @param trxName trx + */ + public MTaxDeclarationLine (Properties ctx, int C_TaxDeclarationLine_ID, String trxName) + { + super (ctx, C_TaxDeclarationLine_ID, trxName); + if (C_TaxDeclarationLine_ID == 0) + { + setIsManual(true); + setTaxAmt (Env.ZERO); + setTaxBaseAmt (Env.ZERO); + } + } // MTaxDeclarationLine + + /** + * Load Constructor + * @param ctx context + * @param rs rs + * @param trxName trx + */ + public MTaxDeclarationLine (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MTaxDeclarationLine + + /** + * Parent Constructor + * @param parent parent + * @param invoice invoice + * @param iLine invoice line + */ + public MTaxDeclarationLine (MTaxDeclaration parent, MInvoice invoice, MInvoiceLine iLine) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(invoice); + setC_TaxDeclaration_ID(parent.getC_TaxDeclaration_ID()); + setIsManual(false); + // + setC_Invoice_ID(invoice.getC_Invoice_ID()); + setC_BPartner_ID (invoice.getC_BPartner_ID()); + setC_Currency_ID (invoice.getC_Currency_ID()); + setDateAcct (invoice.getDateAcct()); + // + setC_InvoiceLine_ID(iLine.getC_InvoiceLine_ID()); + setC_Tax_ID (iLine.getC_Tax_ID()); + if (invoice.isTaxIncluded()) + { + setTaxBaseAmt (iLine.getLineNetAmt()); + setTaxAmt (iLine.getTaxAmt()); + } + else + { + setTaxBaseAmt (iLine.getLineNetAmt()); + setTaxAmt (iLine.getTaxAmt()); + } + } // MTaxDeclarationLine + + /** + * Parent Constructor + * @param parent parent + * @param invoice invoice + * @param tLine tax line + */ + public MTaxDeclarationLine (MTaxDeclaration parent, MInvoice invoice, MInvoiceTax tLine) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(invoice); + setC_TaxDeclaration_ID(parent.getC_TaxDeclaration_ID()); + setIsManual(false); + // + setC_Invoice_ID(invoice.getC_Invoice_ID()); + setC_BPartner_ID (invoice.getC_BPartner_ID()); + setC_Currency_ID (invoice.getC_Currency_ID()); + setDateAcct (invoice.getDateAcct()); + // + setC_Tax_ID (tLine.getC_Tax_ID()); + setTaxBaseAmt (tLine.getTaxBaseAmt()); + setTaxAmt (tLine.getTaxAmt()); + } // MTaxDeclarationLine + + +} // MTaxDeclarationLine diff --git a/base/src/org/compiere/model/MTaxPostal.java b/base/src/org/compiere/model/MTaxPostal.java new file mode 100644 index 0000000000..52b01455ef --- /dev/null +++ b/base/src/org/compiere/model/MTaxPostal.java @@ -0,0 +1,53 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Tax Postal Model + * + * @author Jorg Janke + * @version $Id: MTaxPostal.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MTaxPostal extends X_C_TaxPostal +{ + /** + * Standard Constructor + * @param ctx context + * @param C_TaxPostal_ID id + * @param trxName transaction + */ + public MTaxPostal (Properties ctx, int C_TaxPostal_ID, String trxName) + { + super (ctx, C_TaxPostal_ID, trxName); + } // MTaxPostal + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MTaxPostal (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MTaxPostal + +} // MTaxPostal diff --git a/base/src/org/compiere/model/MTemplate.java b/base/src/org/compiere/model/MTemplate.java new file mode 100644 index 0000000000..2b06e5ffeb --- /dev/null +++ b/base/src/org/compiere/model/MTemplate.java @@ -0,0 +1,333 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.Level; +import org.compiere.util.*; + +/** + * Web Template Model + * + * @author Yves Sandfort + * @version $Id: MTemplate.java,v 1.12 2006/08/08 18:56:05 comdivision Exp $ + */ +@SuppressWarnings("serial") +public class MTemplate extends X_CM_Template +{ + /** + * Get MTemplate from Cache + * + * @param ctx context + * @param CM_Template_ID id + * @param trxName Transaction + * @return MWebProject + */ + public static MTemplate get (Properties ctx, int CM_Template_ID, String trxName) + { + MTemplate retValue = new MTemplate (ctx, CM_Template_ID, trxName); + if (retValue != null) + return retValue; + retValue = new MTemplate (ctx, CM_Template_ID, null); + return retValue; + } // get + + /** + * Standard Constructor + * + * @param ctx context + * @param CM_Template_ID id + * @param trxName transaction + */ + public MTemplate (Properties ctx, int CM_Template_ID, String trxName) + { + super (ctx, CM_Template_ID, trxName); + } // MTemplate + + /** + * Load Constructor + * + * @param ctx + * context + * @param rs + * result set + * @param trxName + * transaction + */ + public MTemplate (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MTemplate + + /** Web Project */ + private MWebProject m_project = null; + /** + * preBuildTemplate contains a preset Version including needed Subtemplates + */ + private StringBuffer m_preBuildTemplate; + + + /** + * Get Web Project + * @return web project + */ + public MWebProject getWebProject () + { + if (m_project == null) + m_project = MWebProject.get (getCtx (), getCM_WebProject_ID ()); + return m_project; + } // getWebProject + + /** + * Get AD_Tree_ID + * @return tree + */ + public int getAD_Tree_ID () + { + return getWebProject ().getAD_TreeCMT_ID (); + } // getAD_Tree_ID; + + /** + * Get the Template we prebuild (this means with added subtemplates) + * @return StringBuffer with complete XSL Template + */ + public StringBuffer getPreBuildTemplate () + { + if (m_preBuildTemplate != null) + { + // Check whether the prebuild exists (i.e. we are from cache) + return m_preBuildTemplate; + } + else + { + // We will build the prebuild code, so we check which subs are + // needed and build it depending on them + m_preBuildTemplate = new StringBuffer (getTemplateXST ()); + // Let's see whether the template calls Subtemplates... + if (m_preBuildTemplate.indexOf ("= 0) + { + StringBuffer subTemplates = new StringBuffer (); + int pos = 0; + // JJ: if you don't use the value, could you use ArrayList ? + Hashtable subTemplateNames = new Hashtable (); + while (m_preBuildTemplate.indexOf ("= 0) + { + String thisName = null; + int beginPos = m_preBuildTemplate.indexOf ( + "", beginPos); + if (m_preBuildTemplate.indexOf (">", beginPos) < endPos) + { + endPos = m_preBuildTemplate.indexOf (">", beginPos) + 1; + } + String tempTemplate = m_preBuildTemplate.substring (beginPos, + endPos); + pos = m_preBuildTemplate.indexOf ("")) + + subTemplates.toString () + "\n"); + } + return m_preBuildTemplate; + } + } // getPreBuildTemplate + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + return true; + } // beforeSave + + /** + * After Save. Insert - create tree + * @param newRecord insert + * @param success save success + * @return true if saved + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + if (newRecord) + { + StringBuffer sb = new StringBuffer ( + "INSERT INTO AD_TreeNodeCMT " + + "(AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, " + + "AD_Tree_ID, Node_ID, Parent_ID, SeqNo) " + "VALUES (") + .append (getAD_Client_ID ()).append ( + ",0, 'Y', SysDate, 0, SysDate, 0,").append ( + getAD_Tree_ID ()).append (",").append (get_ID ()).append ( + ", 0, 999)"); + int no = DB.executeUpdate (sb.toString (), get_TrxName ()); + if (no > 0) + log.fine ("#" + no + " - TreeType=CMT"); + else + log.warning ("#" + no + " - TreeType=CMT"); + return no > 0; + } + if (!newRecord) + { + org.compiere.cm.CacheHandler thisHandler = new org.compiere.cm.CacheHandler ( + org.compiere.cm.CacheHandler.convertJNPURLToCacheURL (getCtx () + .getProperty ("java.naming.provider.url")), log, getCtx (), + get_TrxName ()); + if (!isInclude ()) + { + // Clean Main Templates on a single level. + thisHandler.cleanTemplate (this.get_ID ()); + } + else + { + // Since we not know which main templates we will clean up all! + thisHandler.emptyTemplate (); + } + } + return success; + } // afterSave + + /** + * After Delete + * + * @param success + * @return deleted + */ + protected boolean afterDelete (boolean success) + { + if (!success) + return success; + // + StringBuffer sb = new StringBuffer ("DELETE FROM AD_TreeNodeCMT ") + .append (" WHERE Node_ID=").append (get_IDOld ()).append ( + " AND AD_Tree_ID=").append (getAD_Tree_ID ()); + int no = DB.executeUpdate (sb.toString (), get_TrxName ()); + if (no > 0) + log.fine ("#" + no + " - TreeType=CMT"); + else + log.warning ("#" + no + " - TreeType=CMT"); + return no > 0; + } // afterDelete + + /** + * Get's all the Ads from Template AD Cat + * @return Array of MAds + */ + public MAd[] getAds () + { + int[] AdCats = null; + String sql = "SELECT count(*) FROM CM_Template_AD_Cat WHERE CM_Template_ID=?"; + PreparedStatement pstmt = null; + try + { + int numberAdCats = 0; + pstmt = DB.prepareStatement (sql, get_TrxName ()); + pstmt.setInt (1, get_ID ()); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + numberAdCats = rs.getInt (1); + } + rs.close (); + AdCats = new int[numberAdCats]; + int i = 0; + sql = "SELECT CM_Ad_Cat_ID FROM CM_Template_AD_Cat WHERE CM_Template_ID=?"; + pstmt = DB.prepareStatement (sql, get_TrxName ()); + pstmt.setInt (1, get_ID ()); + rs = pstmt.executeQuery (); + while (rs.next ()) + { + AdCats[i] = rs.getInt (1); + i++; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (SQLException ex) + { + log.log (Level.SEVERE, sql, ex); + } + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + if (AdCats != null && AdCats.length > 0) + { + MAd[] returnAds = new MAd[AdCats.length]; + for (int i = 0; i < AdCats.length; i++) + { + returnAds[i] = MAd.getNext (getCtx (), AdCats[i], + get_TrxName ()); + } + return returnAds; + } + else + { + return null; + } + } // getAds + +} // MTemplate diff --git a/base/src/org/compiere/model/MTimeExpense.java b/base/src/org/compiere/model/MTimeExpense.java new file mode 100644 index 0000000000..eb4a4c321e --- /dev/null +++ b/base/src/org/compiere/model/MTimeExpense.java @@ -0,0 +1,503 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Time + Expense Model + * + * @author Jorg Janke + * @version $Id: MTimeExpense.java,v 1.4 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MTimeExpense extends X_S_TimeExpense implements DocAction +{ + /** + * Default Constructor + * @param ctx context + * @param S_TimeExpense_ID id + * @param trxName transaction + */ + public MTimeExpense (Properties ctx, int S_TimeExpense_ID, String trxName) + { + super (ctx, S_TimeExpense_ID, trxName); + if (S_TimeExpense_ID == 0) + { + // setC_BPartner_ID (0); + setDateReport (new Timestamp (System.currentTimeMillis ())); + // setDocumentNo (null); + setIsApproved (false); + // setM_PriceList_ID (0); + // setM_Warehouse_ID (0); + super.setProcessed (false); + setProcessing(false); + } + } // MTimeExpense + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MTimeExpense (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MTimeExpense + + /** Default Locator */ + private int m_M_Locator_ID = 0; + /** Lines */ + private MTimeExpenseLine[] m_lines = null; + /** Cached User */ + private int m_AD_User_ID = 0; + + + /** + * Get Lines Convenience Wrapper + * @return array of lines + */ + public MTimeExpenseLine[] getLines () + { + return getLines(true); + } + + /** + * Get Lines + * @param requery true requeries + * @return array of lines + */ + public MTimeExpenseLine[] getLines (boolean requery) + { + if (m_lines != null && !requery) + return m_lines; + // + int C_Currency_ID = getC_Currency_ID(); + ArrayList list = new ArrayList(); + // + String sql = "SELECT * FROM S_TimeExpenseLine WHERE S_TimeExpense_ID=? ORDER BY Line"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getS_TimeExpense_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MTimeExpenseLine te = new MTimeExpenseLine(getCtx(), rs, get_TrxName()); + te.setC_Currency_Report_ID(C_Currency_ID); + list.add(te); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, "getLines", ex); + } + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + // + m_lines = new MTimeExpenseLine[list.size()]; + list.toArray(m_lines); + return m_lines; + } // getLines + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * Get Default Locator (from Warehouse) + * @return locator + */ + public int getM_Locator_ID() + { + if (m_M_Locator_ID != 0) + return m_M_Locator_ID; + // + String sql = "SELECT M_Locator_ID FROM M_Locator " + + "WHERE M_Warehouse_ID=? AND IsActive='Y' ORDER BY IsDefault DESC, Created"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, getM_Warehouse_ID()); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + m_M_Locator_ID = rs.getInt(1); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, "getM_Locator_ID", ex); + } + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + // + return m_M_Locator_ID; + } // getM_Locator_ID + + /** + * Set Processed. + * Propergate to Lines/Taxes + * @param processed processed + */ + public void setProcessed (boolean processed) + { + super.setProcessed (processed); + if (get_ID() == 0) + return; + String sql = "UPDATE S_TimeExpenseLine SET Processed='" + + (processed ? "Y" : "N") + + "' WHERE S_TimeExpense_ID=" + getS_TimeExpense_ID(); + int noLine = DB.executeUpdate(sql, get_TrxName()); + m_lines = null; + log.fine(processed + " - Lines=" + noLine); + } // setProcessed + + /** + * Get Document Info + * @return document info + */ + public String getDocumentInfo() + { + return Msg.getElement(getCtx(), "S_TimeExpense_ID") + " " + getDocumentNo(); + } // getDocumentInfo + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + // ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.INVOICE, getC_Invoice_ID()); + // if (re == null) + return null; + // return re.getPDF(file); + } // createPDF + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // processIt + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info("unlockIt - " + toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info("invalidateIt - " + toString()); + setDocAction(DOCACTION_Prepare); + return true; + } // invalidateIt + + /** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + + // Std Period open? - AP (Reimbursement) Invoice + if (!MPeriod.isOpen(getCtx(), getDateReport(), MDocType.DOCBASETYPE_APInvoice)) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + + MTimeExpenseLine[] lines = getLines(false); + if (lines.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + // Add up Amounts + BigDecimal amt = Env.ZERO; + for (int i = 0; i < lines.length; i++) + { + MTimeExpenseLine line = lines[i]; + amt = amt.add(line.getApprovalAmt()); + } + setApprovalAmt(amt); + + // Invoiced but no BP + for (int i = 0; i < lines.length; i++) + { + MTimeExpenseLine line = lines[i]; + if (line.isInvoiced() && line.getC_BPartner_ID() == 0) + { + m_processMsg = "@Line@ " + line.getLine() + ": Invoiced, but no Business Partner"; + return DocAction.STATUS_Invalid; + } + } + + m_justPrepared = true; + if (!DOCACTION_Complete.equals(getDocAction())) + setDocAction(DOCACTION_Complete); + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info("approveIt - " + toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info("rejectIt - " + toString()); + setIsApproved(false); + return true; + } // rejectIt + + /** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + // Implicit Approval + if (!isApproved()) + approveIt(); + log.info("completeIt - " + toString()); + + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + m_processMsg = valid; + return DocAction.STATUS_Invalid; + } + + // + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + /** + * Void Document. + * Same as Close. + * @return true if success + */ + public boolean voidIt() + { + log.info("voidIt - " + toString()); + return closeIt(); + } // voidIt + + /** + * Close Document. + * Cancel not delivered Qunatities + * @return true if success + */ + public boolean closeIt() + { + log.info("closeIt - " + toString()); + + // Close Not delivered Qty + // setDocAction(DOCACTION_None); + return true; + } // closeIt + + /** + * Reverse Correction + * @return false + */ + public boolean reverseCorrectIt() + { + log.info("reverseCorrectIt - " + toString()); + return false; + } // reverseCorrectionIt + + /** + * Reverse Accrual - none + * @return false + */ + public boolean reverseAccrualIt() + { + log.info("reverseAccrualIt - " + toString()); + return false; + } // reverseAccrualIt + + /** + * Re-activate + * @return true if success + */ + public boolean reActivateIt() + { + log.info("reActivateIt - " + toString()); + // setProcessed(false); + return false; + } // reActivateIt + + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getDocumentNo()); + // : Total Lines = 123.00 (#1) + sb.append(": ") + .append(Msg.translate(getCtx(),"ApprovalAmt")).append("=").append(getApprovalAmt()) + .append(" (#").append(getLines(false).length).append(")"); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner (Responsible) + * @return AD_User_ID + */ + public int getDoc_User_ID() + { + if (m_AD_User_ID != 0) + return m_AD_User_ID; + if (getC_BPartner_ID() != 0) + { + MUser[] users = MUser.getOfBPartner(getCtx(), getC_BPartner_ID()); + if (users.length > 0) + { + m_AD_User_ID = users[0].getAD_User_ID(); + return m_AD_User_ID; + } + } + return getCreatedBy(); + } // getDoc_User_ID + + + /** + * Get Document Currency + * @return C_Currency_ID + */ + public int getC_Currency_ID() + { + MPriceList pl = MPriceList.get(getCtx(), getM_PriceList_ID(), get_TrxName()); + return pl.getC_Currency_ID(); + } // getC_Currency_ID + +} // MTimeExpense diff --git a/base/src/org/compiere/model/MTimeExpenseLine.java b/base/src/org/compiere/model/MTimeExpenseLine.java new file mode 100644 index 0000000000..583f473521 --- /dev/null +++ b/base/src/org/compiere/model/MTimeExpenseLine.java @@ -0,0 +1,282 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Time + Expense Line Model + * + * @author Jorg Janke + * @version $Id: MTimeExpenseLine.java,v 1.4 2006/09/25 00:59:41 jjanke Exp $ + */ +public class MTimeExpenseLine extends X_S_TimeExpenseLine +{ + /** + * Standard Constructor + * @param ctx context + * @param S_TimeExpenseLine_ID id + * @param trxName transaction + */ + public MTimeExpenseLine (Properties ctx, int S_TimeExpenseLine_ID, String trxName) + { + super (ctx, S_TimeExpenseLine_ID, trxName); + if (S_TimeExpenseLine_ID == 0) + { + // setS_TimeExpenseLine_ID (0); // PK + // setS_TimeExpense_ID (0); // Parent + setQty(Env.ONE); + setQtyInvoiced(Env.ZERO); + setQtyReimbursed(Env.ZERO); + // + setExpenseAmt(Env.ZERO); + setConvertedAmt(Env.ZERO); + setPriceReimbursed(Env.ZERO); + setInvoicePrice(Env.ZERO); + setPriceInvoiced(Env.ZERO); + // + setDateExpense (new Timestamp(System.currentTimeMillis())); + setIsInvoiced (false); + setIsTimeReport (false); + setLine (10); + setProcessed(false); + } + } // MTimeExpenseLine + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MTimeExpenseLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MTimeExpenseLine + + /** Currency of Report */ + private int m_C_Currency_Report_ID = 0; + + + /** + * Get Qty Invoiced + * @return entered or qty + */ + public BigDecimal getQtyInvoiced () + { + BigDecimal bd = super.getQtyInvoiced (); + if (Env.ZERO.compareTo(bd) == 0) + return getQty(); + return bd; + } // getQtyInvoiced + + /** + * Get Qty Reimbursed + * @return entered or qty + */ + public BigDecimal getQtyReimbursed () + { + BigDecimal bd = super.getQtyReimbursed (); + if (Env.ZERO.compareTo(bd) == 0) + return getQty(); + return bd; + } // getQtyReimbursed + + + /** + * Get Price Invoiced + * @return entered or invoice price + */ + public BigDecimal getPriceInvoiced () + { + BigDecimal bd = super.getPriceInvoiced (); + if (Env.ZERO.compareTo(bd) == 0) + return getInvoicePrice(); + return bd; + } // getPriceInvoiced + + /** + * Get Price Reimbursed + * @return entered or converted amt + */ + public BigDecimal getPriceReimbursed () + { + BigDecimal bd = super.getPriceReimbursed (); + if (Env.ZERO.compareTo(bd) == 0) + return getConvertedAmt(); + return bd; + } // getPriceReimbursed + + + /** + * Get Approval Amt + * @return qty * converted amt + */ + public BigDecimal getApprovalAmt() + { + return getQty().multiply(getConvertedAmt()); + } // getApprovalAmt + + + /** + * Get C_Currency_ID of Report (Price List) + * @return currency + */ + public int getC_Currency_Report_ID() + { + if (m_C_Currency_Report_ID != 0) + return m_C_Currency_Report_ID; + // Get it from header + MTimeExpense te = new MTimeExpense (getCtx(), getS_TimeExpense_ID(), get_TrxName()); + m_C_Currency_Report_ID = te.getC_Currency_ID(); + return m_C_Currency_Report_ID; + } // getC_Currency_Report_ID + + /** + * Set C_Currency_ID of Report (Price List) + * @param C_Currency_ID currency + */ + protected void setC_Currency_Report_ID (int C_Currency_ID) + { + m_C_Currency_Report_ID = C_Currency_ID; + } // getC_Currency_Report_ID + + + /** + * Before Save. + * Calculate converted amt + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Calculate Converted Amount + if (newRecord || is_ValueChanged("ExpenseAmt") || is_ValueChanged("C_Currency_ID")) + { + if (getC_Currency_ID() == getC_Currency_Report_ID()) + setConvertedAmt(getExpenseAmt()); + else + { + setConvertedAmt(MConversionRate.convert (getCtx(), + getExpenseAmt(), getC_Currency_ID(), getC_Currency_Report_ID(), + getDateExpense(), 0, getAD_Client_ID(), getAD_Org_ID()) ); + } + } + if (isTimeReport()) + { + setExpenseAmt(Env.ZERO); + setConvertedAmt(Env.ZERO); + } + return true; + } // beforeSave + + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (success) + { + updateHeader(); + if (newRecord || is_ValueChanged("S_ResourceAssignment_ID")) + { + int S_ResourceAssignment_ID = getS_ResourceAssignment_ID(); + int old_S_ResourceAssignment_ID = 0; + if (!newRecord) + { + Object ii = get_ValueOld("S_ResourceAssignment_ID"); + if (ii instanceof Integer) + { + old_S_ResourceAssignment_ID = ((Integer)ii).intValue(); + // Changed Assignment + if (old_S_ResourceAssignment_ID != S_ResourceAssignment_ID + && old_S_ResourceAssignment_ID != 0) + { + MResourceAssignment ra = new MResourceAssignment (getCtx(), + old_S_ResourceAssignment_ID, get_TrxName()); + ra.delete(false); + } + } + } + // Sync Assignment + if (S_ResourceAssignment_ID != 0) + { + MResourceAssignment ra = new MResourceAssignment (getCtx(), + S_ResourceAssignment_ID, get_TrxName()); + if (getQty().compareTo(ra.getQty()) != 0) + { + ra.setQty(getQty()); + if (getDescription() != null && getDescription().length() > 0) + ra.setDescription(getDescription()); + ra.save(); + } + } + } + } + return success; + } // afterSave + + + /** + * After Delete + * @param success success + * @return success + */ + protected boolean afterDelete (boolean success) + { + if (success) + { + updateHeader(); + // + Object ii = get_ValueOld("S_ResourceAssignment_ID"); + if (ii instanceof Integer) + { + int old_S_ResourceAssignment_ID = ((Integer)ii).intValue(); + // Deleted Assignment + if (old_S_ResourceAssignment_ID != 0) + { + MResourceAssignment ra = new MResourceAssignment (getCtx(), + old_S_ResourceAssignment_ID, get_TrxName()); + ra.delete(false); + } + } + } + return success; + } // afterDelete + + /** + * Update Header. + * Set Approved Amount + */ + private void updateHeader() + { + String sql = "UPDATE S_TimeExpense te" + + " SET ApprovalAmt = " + + "(SELECT SUM(Qty*ConvertedAmt) FROM S_TimeExpenseLine tel " + + "WHERE te.S_TimeExpense_ID=tel.S_TimeExpense_ID) " + + "WHERE S_TimeExpense_ID=" + getS_TimeExpense_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + } // updateHeader + +} // MTimeExpenseLine diff --git a/base/src/org/compiere/model/MTransaction.java b/base/src/org/compiere/model/MTransaction.java new file mode 100644 index 0000000000..b442340017 --- /dev/null +++ b/base/src/org/compiere/model/MTransaction.java @@ -0,0 +1,115 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Material Transaction Model + * + * @author Jorg Janke + * @version $Id: MTransaction.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MTransaction extends X_M_Transaction +{ + /** + * Standard Constructor + * @param ctx context + * @param M_Transaction_ID id + * @param trxName transaction + */ + public MTransaction (Properties ctx, int M_Transaction_ID, String trxName) + { + super (ctx, M_Transaction_ID, trxName); + if (M_Transaction_ID == 0) + { + // setM_Transaction_ID (0); // PK + // setM_Locator_ID (0); + // setM_Product_ID (0); + setMovementDate (new Timestamp(System.currentTimeMillis())); + setMovementQty (Env.ZERO); + // setMovementType (MOVEMENTTYPE_CustomerShipment); + } + } // MTransaction + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MTransaction (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MTransaction + + /** + * Detail Constructor + * @param ctx context + * @param AD_Org_ID org + * @param MovementType movement type + * @param M_Locator_ID locator + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID attribute + * @param MovementQty qty + * @param MovementDate optional date + * @param trxName transaction + */ + public MTransaction (Properties ctx, int AD_Org_ID, + String MovementType, + int M_Locator_ID, int M_Product_ID, int M_AttributeSetInstance_ID, + BigDecimal MovementQty, Timestamp MovementDate, String trxName) + { + super(ctx, 0, trxName); + setAD_Org_ID(AD_Org_ID); + setMovementType (MovementType); + if (M_Locator_ID == 0) + throw new IllegalArgumentException("No Locator"); + setM_Locator_ID (M_Locator_ID); + if (M_Product_ID == 0) + throw new IllegalArgumentException("No Product"); + setM_Product_ID (M_Product_ID); + setM_AttributeSetInstance_ID (M_AttributeSetInstance_ID); + // + if (MovementQty != null) // Can be 0 + setMovementQty (MovementQty); + if (MovementDate == null) + setMovementDate (new Timestamp(System.currentTimeMillis())); + else + setMovementDate(MovementDate); + } // MTransaction + + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MTransaction["); + sb.append(get_ID()).append(",").append(getMovementType()) + .append(",Qty=").append(getMovementQty()) + .append(",M_Product_ID=").append(getM_Product_ID()) + .append(",ASI=").append(getM_AttributeSetInstance_ID()) + .append ("]"); + return sb.toString (); + } // toString + +} // MTransaction diff --git a/base/src/org/compiere/model/MTree.java b/base/src/org/compiere/model/MTree.java new file mode 100644 index 0000000000..7cd8f1fce6 --- /dev/null +++ b/base/src/org/compiere/model/MTree.java @@ -0,0 +1,582 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.awt.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import javax.sql.*; +import org.compiere.print.*; +import org.compiere.util.*; + +/** + * Builds Tree. + * Creates tree structure - maintained in VTreePanel + * + * @author Jorg Janke + * @version $Id: MTree.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MTree extends MTree_Base +{ + /** + * Default Constructor. + * Need to call loadNodes explicitly + * @param ctx context for security + * @param AD_Tree_ID The tree to build + * @param trxName transaction + */ + public MTree (Properties ctx, int AD_Tree_ID, String trxName) + { + super (ctx, AD_Tree_ID, trxName); + } // MTree + + /** + * Construct & Load Tree + * @param AD_Tree_ID The tree to build + * @param editable True, if tree can be modified + * - includes inactive and empty summary nodes + * @param ctx context for security + * @param clientTree the tree is displayed on the java client (not on web) + * @param trxName transaction + */ + public MTree (Properties ctx, int AD_Tree_ID, + boolean editable, boolean clientTree, String trxName) + { + this (ctx, AD_Tree_ID, trxName); + m_editable = editable; + int AD_User_ID = Env.getContextAsInt(ctx, "AD_User_ID"); + m_clientTree = clientTree; + log.info("AD_Tree_ID=" + AD_Tree_ID + + ", AD_User_ID=" + AD_User_ID + + ", Editable=" + editable + + ", OnClient=" + clientTree); + // + loadNodes(AD_User_ID); + } // MTree + + + /** Is Tree editable */ + private boolean m_editable = false; + /** Root Node */ + private MTreeNode m_root = null; + /** Buffer while loading tree */ + private ArrayList m_buffer = new ArrayList(); + /** Prepared Statement for Node Details */ + private RowSet m_nodeRowSet; + /** The tree is displayed on the Java Client (i.e. not web) */ + private boolean m_clientTree = true; + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger(MTree.class); + + + /************************************************************************** + * Get default (oldest) complete AD_Tree_ID for KeyColumn. + * Called from GridController + * @param keyColumnName key column name, eg. C_Project_ID + * @param AD_Client_ID client + * @return AD_Tree_ID + */ + public static int getDefaultAD_Tree_ID (int AD_Client_ID, String keyColumnName) + { + s_log.config(keyColumnName); + if (keyColumnName == null || keyColumnName.length() == 0) + return 0; + + String TreeType = null; + if (keyColumnName.equals("AD_Menu_ID")) + TreeType = TREETYPE_Menu; + else if (keyColumnName.equals("C_ElementValue_ID")) + TreeType = TREETYPE_ElementValue; + else if (keyColumnName.equals("M_Product_ID")) + TreeType = TREETYPE_Product; + else if (keyColumnName.equals("C_BPartner_ID")) + TreeType = TREETYPE_BPartner; + else if (keyColumnName.equals("AD_Org_ID")) + TreeType = TREETYPE_Organization; + else if (keyColumnName.equals("C_Project_ID")) + TreeType = TREETYPE_Project; + else if (keyColumnName.equals("M_ProductCategory_ID")) + TreeType = TREETYPE_ProductCategory; + else if (keyColumnName.equals("M_BOM_ID")) + TreeType = TREETYPE_BoM; + else if (keyColumnName.equals("C_SalesRegion_ID")) + TreeType = TREETYPE_SalesRegion; + else if (keyColumnName.equals("C_Campaign_ID")) + TreeType = TREETYPE_Campaign; + else if (keyColumnName.equals("C_Activity_ID")) + TreeType = TREETYPE_Activity; + // + else if (keyColumnName.equals("CM_CStage_ID")) + TreeType = TREETYPE_CMContainerStage; + else if (keyColumnName.equals("CM_Container_ID")) + TreeType = TREETYPE_CMContainer; + else if (keyColumnName.equals("CM_Media_ID")) + TreeType = TREETYPE_CMMedia; + else if (keyColumnName.equals("CM_Template_ID")) + TreeType = TREETYPE_CMTemplate; + else + { + s_log.log(Level.SEVERE, "Could not map " + keyColumnName); + return 0; + } + + int AD_Tree_ID = 0; + String sql = "SELECT AD_Tree_ID, Name FROM AD_Tree " + + "WHERE AD_Client_ID=? AND TreeType=? AND IsActive='Y' AND IsAllNodes='Y' " + + "ORDER BY IsDefault DESC, AD_Tree_ID"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Client_ID); + pstmt.setString(2, TreeType); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + AD_Tree_ID = rs.getInt(1); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + s_log.log(Level.SEVERE, sql, e); + } + + return AD_Tree_ID; + } // getDefaultAD_Tree_ID + + + + /************************************************************************* + * Load Nodes and Bar + * @param AD_User_ID user for tree bar + */ + private void loadNodes (int AD_User_ID) + { + // SQL for TreeNodes + StringBuffer sql = new StringBuffer("SELECT " + + "tn.Node_ID,tn.Parent_ID,tn.SeqNo,tb.IsActive " + + "FROM ").append(getNodeTableName()).append(" tn" + + " LEFT OUTER JOIN AD_TreeBar tb ON (tn.AD_Tree_ID=tb.AD_Tree_ID" + + " AND tn.Node_ID=tb.Node_ID AND tb.AD_User_ID=?) " // #1 + + "WHERE tn.AD_Tree_ID=?"); // #2 + if (!m_editable) + sql.append(" AND tn.IsActive='Y'"); + sql.append(" ORDER BY COALESCE(tn.Parent_ID, -1), tn.SeqNo"); + log.finest(sql.toString()); + + // The Node Loop + try + { + // load Node details - addToTree -> getNodeDetail + getNodeDetails(); + // + PreparedStatement pstmt = DB.prepareStatement(sql.toString(), get_TrxName()); + pstmt.setInt(1, AD_User_ID); + pstmt.setInt(2, getAD_Tree_ID()); + // Get Tree & Bar + ResultSet rs = pstmt.executeQuery(); + m_root = new MTreeNode (0, 0, getName(), getDescription(), 0, true, null, false, null); + while (rs.next()) + { + int node_ID = rs.getInt(1); + int parent_ID = rs.getInt(2); + int seqNo = rs.getInt(3); + boolean onBar = (rs.getString(4) != null); + // + if (node_ID == 0 && parent_ID == 0) + ; + else + addToTree (node_ID, parent_ID, seqNo, onBar); // calls getNodeDetail + } + rs.close(); + pstmt.close(); + // + m_nodeRowSet.close(); + m_nodeRowSet = null; + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql.toString(), e); + m_nodeRowSet = null; + } + + // Done with loading - add remainder from buffer + if (m_buffer.size() != 0) + { + log.finest("clearing buffer - Adding to: " + m_root); + for (int i = 0; i < m_buffer.size(); i++) + { + MTreeNode node = (MTreeNode)m_buffer.get(i); + MTreeNode parent = m_root.findNode(node.getParent_ID()); + if (parent != null && parent.getAllowsChildren()) + { + parent.add(node); + checkBuffer(node); + m_buffer.remove(i); + i = -1; // start again with i=0 + } + } + } + + // Nodes w/o parent + if (m_buffer.size() != 0) + { + log.severe ("Nodes w/o parent - adding to root - " + m_buffer); + for (int i = 0; i < m_buffer.size(); i++) + { + MTreeNode node = (MTreeNode)m_buffer.get(i); + m_root.add(node); + checkBuffer(node); + m_buffer.remove(i); + i = -1; + } + if (m_buffer.size() != 0) + log.severe ("Still nodes in Buffer - " + m_buffer); + } // nodes w/o parents + + // clean up + if (!m_editable && m_root.getChildCount() > 0) + trimTree(); +// diagPrintTree(); + if (CLogMgt.isLevelFinest() || m_root.getChildCount() == 0) + log.fine("ChildCount=" + m_root.getChildCount()); + } // loadNodes + + /** + * Add Node to Tree. + * If not found add to buffer + * @param node_ID Node_ID + * @param parent_ID Parent_ID + * @param seqNo SeqNo + * @param onBar on bar + */ + private void addToTree (int node_ID, int parent_ID, int seqNo, boolean onBar) + { + // Create new Node + MTreeNode child = getNodeDetail (node_ID, parent_ID, seqNo, onBar); + if (child == null) + return; + + // Add to Tree + MTreeNode parent = null; + if (m_root != null) + parent = m_root.findNode (parent_ID); + // Parent found + if (parent != null && parent.getAllowsChildren()) + { + parent.add(child); + // see if we can add nodes from buffer + if (m_buffer.size() > 0) + checkBuffer(child); + } + else + m_buffer.add(child); + } // addToTree + + /** + * Check the buffer for nodes which have newNode as Parents + * @param newNode new node + */ + private void checkBuffer (MTreeNode newNode) + { + // Ability to add nodes + if (!newNode.isSummary() || !newNode.getAllowsChildren()) + return; + // + for (int i = 0; i < m_buffer.size(); i++) + { + MTreeNode node = (MTreeNode)m_buffer.get(i); + if (node.getParent_ID() == newNode.getNode_ID()) + { + try + { + newNode.add(node); + } + catch (Exception e) + { + log.severe("Adding " + node.getName() + + " to " + newNode.getName() + ": " + e.getMessage()); + } + m_buffer.remove(i); + i--; + } + } + } // checkBuffer + + + + /************************************************************************** + * Get Node Detail. + * Loads data into RowSet m_nodeRowSet + * Columns: + * - ID + * - Name + * - Description + * - IsSummary + * - ImageIndicator + * - additional for Menu + * Parameter: + * - Node_ID + * The SQL contains security/access control + */ + private void getNodeDetails () + { + // SQL for Node Info + StringBuffer sqlNode = new StringBuffer(); + String sourceTable = "t"; + String fromClause = getSourceTableName(false); // fully qualified + String columnNameX = getSourceTableName(true); + String color = getActionColorName(); + if (getTreeType().equals(TREETYPE_Menu)) + { + boolean base = Env.isBaseLanguage(p_ctx, "AD_Menu"); + sourceTable = "m"; + if (base) + sqlNode.append("SELECT m.AD_Menu_ID, m.Name,m.Description,m.IsSummary,m.Action, " + + "m.AD_Window_ID, m.AD_Process_ID, m.AD_Form_ID, m.AD_Workflow_ID, m.AD_Task_ID, m.AD_Workbench_ID " + + "FROM AD_Menu m"); + else + sqlNode.append("SELECT m.AD_Menu_ID, t.Name,t.Description,m.IsSummary,m.Action, " + + "m.AD_Window_ID, m.AD_Process_ID, m.AD_Form_ID, m.AD_Workflow_ID, m.AD_Task_ID, m.AD_Workbench_ID " + + "FROM AD_Menu m, AD_Menu_Trl t"); + if (!base) + sqlNode.append(" WHERE m.AD_Menu_ID=t.AD_Menu_ID AND t.AD_Language='") + .append(Env.getAD_Language(p_ctx)).append("'"); + if (!m_editable) + { + boolean hasWhere = sqlNode.indexOf(" WHERE ") != -1; + sqlNode.append(hasWhere ? " AND " : " WHERE ").append("m.IsActive='Y' "); + } + // Do not show Beta + if (!MClient.get(getCtx()).isUseBetaFunctions()) + { + boolean hasWhere = sqlNode.indexOf(" WHERE ") != -1; + sqlNode.append(hasWhere ? " AND " : " WHERE "); + sqlNode.append("(m.AD_Window_ID IS NULL OR EXISTS (SELECT * FROM AD_Window w WHERE m.AD_Window_ID=w.AD_Window_ID AND w.IsBetaFunctionality='N'))") + .append(" AND (m.AD_Process_ID IS NULL OR EXISTS (SELECT * FROM AD_Process p WHERE m.AD_Process_ID=p.AD_Process_ID AND p.IsBetaFunctionality='N'))") + .append(" AND (m.AD_Form_ID IS NULL OR EXISTS (SELECT * FROM AD_Form f WHERE m.AD_Form_ID=f.AD_Form_ID AND f.IsBetaFunctionality='N'))"); + } + // In R/O Menu - Show only defined Forms + if (!m_editable) + { + boolean hasWhere = sqlNode.indexOf(" WHERE ") != -1; + sqlNode.append(hasWhere ? " AND " : " WHERE "); + sqlNode.append("(m.AD_Form_ID IS NULL OR EXISTS (SELECT * FROM AD_Form f WHERE m.AD_Form_ID=f.AD_Form_ID AND "); + if (m_clientTree) + sqlNode.append("f.Classname"); + else + sqlNode.append("f.JSPURL"); + sqlNode.append(" IS NOT NULL))"); + } + } + else + { + if (columnNameX == null) + throw new IllegalArgumentException("Unknown TreeType=" + getTreeType()); + sqlNode.append("SELECT t.").append(columnNameX) + .append("_ID,t.Name,t.Description,t.IsSummary,").append(color) + .append(" FROM ").append(fromClause); + if (!m_editable) + sqlNode.append(" WHERE t.IsActive='Y'"); + } + String sql = sqlNode.toString(); + if (!m_editable) // editable = menu/etc. window + sql = MRole.getDefault(getCtx(), false).addAccessSQL(sql, + sourceTable, MRole.SQL_FULLYQUALIFIED, m_editable); + log.fine(sql); + m_nodeRowSet = DB.getRowSet (sql, true); + } // getNodeDetails + + /** + * Get Menu Node Details. + * As SQL contains security access, not all nodes will be found + * @param node_ID Key of the record + * @param parent_ID Parent ID of the record + * @param seqNo Sort index + * @param onBar Node also on Shortcut bar + * @return Node + */ + private MTreeNode getNodeDetail (int node_ID, int parent_ID, int seqNo, boolean onBar) + { + MTreeNode retValue = null; + try + { + m_nodeRowSet.beforeFirst(); + while (m_nodeRowSet.next()) + { + int node = m_nodeRowSet.getInt(1); + if (node_ID != node) // search for correct one + continue; + // ID,Name,Description,IsSummary,Action/Color + int index = 2; + String name = m_nodeRowSet.getString(index++); + String description = m_nodeRowSet.getString(index++); + boolean isSummary = "Y".equals(m_nodeRowSet.getString(index++)); + String actionColor = m_nodeRowSet.getString(index++); + // Menu only + if (getTreeType().equals(TREETYPE_Menu) && !isSummary) + { + int AD_Window_ID = m_nodeRowSet.getInt(index++); + int AD_Process_ID = m_nodeRowSet.getInt(index++); + int AD_Form_ID = m_nodeRowSet.getInt(index++); + int AD_Workflow_ID = m_nodeRowSet.getInt(index++); + int AD_Task_ID = m_nodeRowSet.getInt(index++); + int AD_Workbench_ID = m_nodeRowSet.getInt(index++); + // + MRole role = MRole.getDefault(getCtx(), false); + Boolean access = null; + if (X_AD_Menu.ACTION_Window.equals(actionColor)) + access = role.getWindowAccess(AD_Window_ID); + else if (X_AD_Menu.ACTION_Process.equals(actionColor) + || X_AD_Menu.ACTION_Report.equals(actionColor)) + access = role.getProcessAccess(AD_Process_ID); + else if (X_AD_Menu.ACTION_Form.equals(actionColor)) + access = role.getFormAccess(AD_Form_ID); + else if (X_AD_Menu.ACTION_WorkFlow.equals(actionColor)) + access = role.getWorkflowAccess(AD_Workflow_ID); + else if (X_AD_Menu.ACTION_Task.equals(actionColor)) + access = role.getTaskAccess(AD_Task_ID); + // else if (X_AD_Menu.ACTION_Workbench.equals(action)) + // access = role.getWorkbenchAccess(AD_Window_ID); + // log.fine("getNodeDetail - " + name + " - " + actionColor + " - " + access); + // + if (access != null // rw or ro for Role + || m_editable) // Menu Window can see all + { + retValue = new MTreeNode (node_ID, seqNo, + name, description, parent_ID, isSummary, + actionColor, onBar, null); // menu has no color + } + } + else // always add + { + Color color = null; // action + if (actionColor != null && !getTreeType().equals(TREETYPE_Menu)) + { + MPrintColor printColor = MPrintColor.get(getCtx(), actionColor); + if (printColor != null) + color = printColor.getColor(); + } + // + retValue = new MTreeNode (node_ID, seqNo, + name, description, parent_ID, isSummary, + null, onBar, color); // no action + } + } + } + catch (SQLException e) + { + log.log(Level.SEVERE, "", e); + } + return retValue; + } // getNodeDetails + + + /************************************************************************** + * Trim tree of empty summary nodes + */ + public void trimTree() + { + boolean needsTrim = m_root != null; + while (needsTrim) + { + needsTrim = false; + Enumeration en = m_root.preorderEnumeration(); + while (m_root.getChildCount() > 0 && en.hasMoreElements()) + { + MTreeNode nd = (MTreeNode)en.nextElement(); + if (nd.isSummary() && nd.getChildCount() == 0) + { + nd.removeFromParent(); + needsTrim = true; + } + } + } + } // trimTree + + /** + * Diagnostics: Print tree + */ + private void dumpTree() + { + Enumeration en = m_root.preorderEnumeration(); + int count = 0; + while (en.hasMoreElements()) + { + StringBuffer sb = new StringBuffer(); + MTreeNode nd = (MTreeNode)en.nextElement(); + for (int i = 0; i < nd.getLevel(); i++) + sb.append(" "); + sb.append("ID=").append(nd.getNode_ID()) + .append(", SeqNo=").append(nd.getSeqNo()) + .append(" ").append(nd.getName()); + System.out.println(sb.toString()); + count++; + } + System.out.println("Count=" + count); + } // diagPrintTree + + /** + * Get Root node + * @return root + */ + public MTreeNode getRoot() + { + return m_root; + } // getRoot + + /** + * Is Menu Tree + * @return true if menu + */ + public boolean isMenu() + { + return TREETYPE_Menu.equals(getTreeType()); + } // isMenu + + /** + * Is Product Tree + * @return true if product + */ + public boolean isProduct() + { + return TREETYPE_Product.equals(getTreeType()); + } // isProduct + + /** + * Is Business Partner Tree + * @return true if partner + */ + public boolean isBPartner() + { + return TREETYPE_BPartner.equals(getTreeType()); + } // isBPartner + + /** + * String representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("MTree["); + sb.append("AD_Tree_ID=").append(getAD_Tree_ID()) + .append(", Name=").append(getName()); + sb.append("]"); + return sb.toString(); + } +} // MTree diff --git a/base/src/org/compiere/model/MTreeNode.java b/base/src/org/compiere/model/MTreeNode.java new file mode 100644 index 0000000000..c3e6522ac4 --- /dev/null +++ b/base/src/org/compiere/model/MTreeNode.java @@ -0,0 +1,419 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.awt.*; +import java.util.*; +import javax.swing.*; +import javax.swing.tree.*; +import java.util.logging.*; +import org.compiere.util.*; +import org.compiere.wf.*; + +/** + * Mutable Tree Node (not a PO). + * + * @author Jorg Janke + * @version $Id: MTreeNode.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public final class MTreeNode extends DefaultMutableTreeNode +{ + /** + * Construct Model TreeNode + * @param node_ID node + * @param seqNo sequence + * @param name name + * @param description description + * @param parent_ID parent + * @param isSummary summary + * @param imageIndicator image indicator + * @param onBar on bar + * @param color color + */ + public MTreeNode (int node_ID, int seqNo, String name, String description, + int parent_ID, boolean isSummary, String imageIndicator, boolean onBar, Color color) + { + super(); + // log.fine( "MTreeNode Node_ID=" + node_ID + ", Parent_ID=" + parent_ID + " - " + name); + m_node_ID = node_ID; + m_seqNo = seqNo; + m_name = name; + m_description = description; + if (m_description == null) + m_description = ""; + m_parent_ID = parent_ID; + setSummary(isSummary); + setImageIndicator(imageIndicator); + m_onBar = onBar; + m_color = color; + } // MTreeNode + + /** Node ID */ + private int m_node_ID; + /** SeqNo */ + private int m_seqNo; + /** Name */ + private String m_name; + /** Description */ + private String m_description; + /** Parent ID */ + private int m_parent_ID; + /** Summaty */ + private boolean m_isSummary; + /** Image Indicator */ + private String m_imageIndicator; + /** Index to Icon */ + private int m_imageIndex = 0; + /** On Bar */ + private boolean m_onBar; + /** Color */ + private Color m_color; + + /** Logger */ + private static CLogger log = CLogger.getCLogger(MTreeNode.class); + + /*************************************************************************/ + + /** Window - 1 */ + public static int TYPE_WINDOW = 1; + /** Report - 2 */ + public static int TYPE_REPORT = 2; + /** Process - 3 */ + public static int TYPE_PROCESS = 3; + /** Workflow - 4 */ + public static int TYPE_WORKFLOW = 4; + /** Workbench - 5 */ + public static int TYPE_WORKBENCH = 5; + /** Variable - 6 */ + public static int TYPE_SETVARIABLE = 6; + /** Choice - 7 */ + public static int TYPE_USERCHOICE = 7; + /** Action - 8 */ + public static int TYPE_DOCACTION = 8; + + /** 16* 16 Icons */ + public static Icon[] IMAGES = new Icon[] + { + null, + Env.getImageIcon("mWindow.gif"), + Env.getImageIcon("mReport.gif"), + Env.getImageIcon("mProcess.gif"), + Env.getImageIcon("mWorkFlow.gif"), + Env.getImageIcon("mWorkbench.gif"), + Env.getImageIcon("mSetVariable.gif"), + Env.getImageIcon("mUserChoice.gif"), + Env.getImageIcon("mDocAction.gif") + }; + + + /************************************************************************** + * Get Node ID + * @return node id (e.g. AD_Menu_ID) + */ + public int getNode_ID() + { + return m_node_ID; + } // getID + + /** + * Set Name + * @param name name + */ + public void setName (String name) + { + if (name == null) + m_name = ""; + else + m_name = name; + } // setName + + /** + * Get Name + * @return name + */ + public String getName() + { + return m_name; + } // setName + + /** + * Get SeqNo (Index) as formatted String 0000 for sorting + * @return SeqNo as String + */ + public String getSeqNo() + { + String retValue = "0000" + m_seqNo; // not more than 100,000 nodes + if (m_seqNo > 99999) + log.log(Level.SEVERE, "MTreeNode.getIndex - TreeNode Index is higher than 99999"); + if (retValue.length() > 5) + retValue = retValue.substring(retValue.length()-5); // last 5 + return retValue; + } // getSeqNo + + /** + * Return parent + * @return Parent_ID (e.g. AD_Menu_ID) + */ + public int getParent_ID() + { + return m_parent_ID; + } // getParent + + /** + * Print Name + * @return info + */ + public String toString() + { + return // m_node_ID + "/" + m_parent_ID + " " + m_seqNo + " - " + + m_name; + } // toString + + /** + * Get Description + * @return description + */ + public String getDescription() + { + return m_description; + } // getDescription + + + /************************************************************************** + * Set Summary (allow children) + * @param isSummary summary node + */ + public void setSummary (boolean isSummary) + { + m_isSummary = isSummary; + super.setAllowsChildren(isSummary); + } // setSummary + + /** + * Set Summary (allow children) + * @param isSummary true if summary + */ + public void setAllowsChildren (boolean isSummary) + { + super.setAllowsChildren (isSummary); + m_isSummary = isSummary; + } // setAllowsChildren + + /** + * Allow children to be added to this node + * @return true if summary node + */ + public boolean isSummary() + { + return m_isSummary; + } // isSummary + + + /************************************************************************** + * Get Image Indicator/Index + * @param imageIndicator image indicator (W/X/R/P/F/T/B) MWFNode.ACTION_ + * @return index of image + */ + public static int getImageIndex (String imageIndicator) + { + int imageIndex = 0; + if (imageIndicator == null) + ; + else if (imageIndicator.equals(MWFNode.ACTION_UserWindow) // Window + || imageIndicator.equals(MWFNode.ACTION_UserForm)) + imageIndex = TYPE_WINDOW; + else if (imageIndicator.equals(MWFNode.ACTION_AppsReport)) // Report + imageIndex = TYPE_REPORT; + else if (imageIndicator.equals(MWFNode.ACTION_AppsProcess) // Process + || imageIndicator.equals(MWFNode.ACTION_AppsTask)) + imageIndex = TYPE_PROCESS; + else if (imageIndicator.equals(MWFNode.ACTION_SubWorkflow)) // WorkFlow + imageIndex = TYPE_WORKFLOW; + else if (imageIndicator.equals(MWFNode.ACTION_UserWorkbench)) // Workbench + imageIndex = TYPE_WORKBENCH; + else if (imageIndicator.equals(MWFNode.ACTION_SetVariable)) // Set Variable + imageIndex = TYPE_SETVARIABLE; + else if (imageIndicator.equals(MWFNode.ACTION_UserChoice)) // User Choice + imageIndex = TYPE_USERCHOICE; + else if (imageIndicator.equals(MWFNode.ACTION_DocumentAction)) // Document Action + imageIndex = TYPE_DOCACTION; + else if (imageIndicator.equals(MWFNode.ACTION_WaitSleep)) // Sleep + ; + return imageIndex; + } // getImageIndex + + /** + * Set Image Indicator and Index + * @param imageIndicator image indicator (W/X/R/P/F/T/B) MWFNode.ACTION_ + */ + public void setImageIndicator (String imageIndicator) + { + if (imageIndicator != null) + { + m_imageIndicator = imageIndicator; + m_imageIndex = getImageIndex(m_imageIndicator); + } + } // setImageIndicator + + /** + * Get Image Indicator + * @return image indicator + */ + public String getImageIndiactor() + { + return m_imageIndicator; + } // getImageIndiactor + + /** + * Get Image Icon + * @param index image index + * @return Icon + */ + public static Icon getIcon (int index) + { + if (index == 0 || IMAGES == null || index > IMAGES.length) + return null; + return IMAGES[index]; + } // getIcon + + /** + * Get Image Icon + * @return Icon + */ + public Icon getIcon() + { + return getIcon(m_imageIndex); + } // getIcon + + /** + * Get Shortcut Bar info + * @return true if node on bar + */ + public boolean isOnBar() + { + return m_onBar; + } // isOnBar + + /** + * Is Process + * @return true if Process + */ + public boolean isProcess() + { + return X_AD_Menu.ACTION_Process.equals(m_imageIndicator); + } // isProcess + + /** + * Is Report + * @return true if report + */ + public boolean isReport() + { + return X_AD_Menu.ACTION_Report.equals(m_imageIndicator); + } // isReport + + /** + * Is Window + * @return true if Window + */ + public boolean isWindow() + { + return X_AD_Menu.ACTION_Window.equals(m_imageIndicator); + } // isWindow + + /** + * Is Workbench + * @return true if Workbench + */ + public boolean isWorkbench() + { + return X_AD_Menu.ACTION_Workbench.equals(m_imageIndicator); + } // isWorkbench + + /** + * Is Workflow + * @return true if Workflow + */ + public boolean isWorkFlow() + { + return X_AD_Menu.ACTION_WorkFlow.equals(m_imageIndicator); + } // isWorkFlow + + /** + * Is Form + * @return true if Form + */ + public boolean isForm() + { + return X_AD_Menu.ACTION_Form.equals(m_imageIndicator); + } // isForm + + /** + * Is Task + * @return true if Task + */ + public boolean isTask() + { + return X_AD_Menu.ACTION_Task.equals(m_imageIndicator); + } // isTask + + /** + * Get Color + * @return color or black if not set + */ + public Color getColor() + { + if (m_color != null) + return m_color; + return Color.black; + } // getColor + + /*************************************************************************/ + + /** Last found ID */ + private int m_lastID = -1; + /** Last found Node */ + private MTreeNode m_lastNode = null; + + /** + * Return the Node with ID in list of children + * @param ID id + * @return VTreeNode with ID or null + */ + public MTreeNode findNode (int ID) + { + if (m_node_ID == ID) + return this; + // + if (ID == m_lastID && m_lastNode != null) + return m_lastNode; + // + Enumeration en = preorderEnumeration(); + while (en.hasMoreElements()) + { + MTreeNode nd = (MTreeNode)en.nextElement(); + if (ID == nd.getNode_ID()) + { + m_lastID = ID; + m_lastNode = nd; + return nd; + } + } + return null; + } // findNode + +} // MTreeNode diff --git a/base/src/org/compiere/model/MUOM.java b/base/src/org/compiere/model/MUOM.java new file mode 100644 index 0000000000..fe945602e5 --- /dev/null +++ b/base/src/org/compiere/model/MUOM.java @@ -0,0 +1,295 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Unit Of Measure Model + * + * @author Jorg Janke + * @version $Id: MUOM.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MUOM extends X_C_UOM +{ + /** X12 Element 355 Code Minute */ + static final String X12_MINUTE = "MJ"; + /** X12 Element 355 Code Hour */ + static final String X12_HOUR = "HR"; + /** X12 Element 355 Code Day */ + static final String X12_DAY = "DA"; + /** X12 Element 355 Code Work Day (8 hours / 5days) */ + static final String X12_DAY_WORK = "WD"; + /** X12 Element 355 Code Week */ + static final String X12_WEEK = "WK"; + /** X12 Element 355 Code Month */ + static final String X12_MONTH = "MO"; + /** X12 Element 355 Code Work Month (20 days / 4 weeks) */ + static final String X12_MONTH_WORK = "WM"; + /** X12 Element 355 Code Year */ + static final String X12_YEAR = "YR"; + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger(MUOM.class); + + /** + * Get Minute C_UOM_ID + * @param ctx context + * @return C_UOM_ID for Minute + */ + public static int getMinute_UOM_ID (Properties ctx) + { + if (Ini.isClient()) + { + Iterator it = s_cache.values().iterator(); + while (it.hasNext()) + { + MUOM uom = (MUOM)it.next(); + if (uom.isMinute()) + return uom.getC_UOM_ID(); + } + } + // Server + int C_UOM_ID = 0; + String sql = "SELECT C_UOM_ID FROM C_UOM " + + "WHERE IsActive='Y' AND X12DE355='MJ'"; // HardCoded + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + C_UOM_ID = rs.getInt(1); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + s_log.log(Level.SEVERE, sql, e); + } + return C_UOM_ID; + } // getMinute_UOM_ID + + /** + * Get Default C_UOM_ID + * @param ctx context for AD_Client + * @return C_UOM_ID + */ + public static int getDefault_UOM_ID (Properties ctx) + { + String sql = "SELECT C_UOM_ID " + + "FROM C_UOM " + + "WHERE AD_Client_ID IN (0,?) " + + "ORDER BY IsDefault DESC, AD_Client_ID DESC, C_UOM_ID"; + return DB.getSQLValue(null, sql, Env.getAD_Client_ID(ctx)); + } // getDefault_UOM_ID + + /*************************************************************************/ + + /** UOM Cache */ + private static CCache s_cache + = new CCache("C_UOM", 30); + + /** + * Get UOM from Cache + * @param ctx context + * @param C_UOM_ID ID + * @return UOM + */ + public static MUOM get (Properties ctx, int C_UOM_ID) + { + if (s_cache.size() == 0) + loadUOMs (ctx); + // + Integer ii = new Integer (C_UOM_ID); + MUOM uom = (MUOM)s_cache.get(ii); + if (uom != null) + return uom; + // + uom = new MUOM (ctx, C_UOM_ID, null); + s_cache.put(new Integer(C_UOM_ID), uom); + return uom; + } // getUOMfromCache + + /** + * Get Precision + * @param ctx context + * @param C_UOM_ID ID + * @return Precision + */ + public static int getPrecision (Properties ctx, int C_UOM_ID) + { + MUOM uom = get(ctx, C_UOM_ID); + return uom.getStdPrecision(); + } // getPrecision + + /** + * Load All UOMs + * @param ctx context + */ + private static void loadUOMs (Properties ctx) + { + String sql = MRole.getDefault(ctx, false).addAccessSQL( + "SELECT * FROM C_UOM " + + "WHERE IsActive='Y'", + "C_UOM", MRole.SQL_NOTQUALIFIED, MRole.SQL_RO); + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + MUOM uom = new MUOM(ctx, rs, null); + s_cache.put (new Integer(uom.getC_UOM_ID()), uom); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + s_log.log(Level.SEVERE, sql, e); + } + } // loadUOMs + + + /************************************************************************** + * Constructor. + * @param ctx context + * @param C_UOM_ID UOM ID + * @param trxName transaction + */ + public MUOM (Properties ctx, int C_UOM_ID, String trxName) + { + super (ctx, C_UOM_ID, trxName); + if (C_UOM_ID == 0) + { + // setName (null); + // setX12DE355 (null); + setIsDefault (false); + setStdPrecision (2); + setCostingPrecision (6); + } + } // UOM + + /** + * Load Constructor. + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MUOM (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // UOM + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("UOM["); + sb.append("ID=").append(get_ID()) + .append(", Name=").append(getName()); + return sb.toString(); + } // toString + + /** + * Round qty + * @param qty quantity + * @param stdPrecision true if std precisison + * @return rounded quantity + */ + public BigDecimal round (BigDecimal qty, boolean stdPrecision) + { + int precision = getStdPrecision(); + if (!stdPrecision) + precision = getCostingPrecision(); + if (qty.scale() > precision) + return qty.setScale(getStdPrecision(), BigDecimal.ROUND_HALF_UP); + return qty; + } // round + + /** + * Minute + * @return true if UOM is minute + */ + public boolean isMinute() + { + return X12_MINUTE.equals(getX12DE355()); + } + /** + * Hour + * @return true if UOM is hour + */ + public boolean isHour() + { + return X12_HOUR.equals(getX12DE355()); + } + /** + * Day + * @return true if UOM is Day + */ + public boolean isDay() + { + return X12_DAY.equals(getX12DE355()); + } + /** + * WorkDay + * @return true if UOM is work day + */ + public boolean isWorkDay() + { + return X12_DAY_WORK.equals(getX12DE355()); + } + /** + * Week + * @return true if UOM is Week + */ + public boolean isWeek() + { + return X12_WEEK.equals(getX12DE355()); + } + /** + * Month + * @return true if UOM is Month + */ + public boolean isMonth() + { + return X12_MONTH.equals(getX12DE355()); + } + /** + * WorkMonth + * @return true if UOM is Work Month + */ + public boolean isWorkMonth() + { + return X12_MONTH_WORK.equals(getX12DE355()); + } + /** + * Year + * @return true if UOM is year + */ + public boolean isYear() + { + return X12_YEAR.equals(getX12DE355()); + } + +} // MUOM diff --git a/base/src/org/compiere/model/MUOMConversion.java b/base/src/org/compiere/model/MUOMConversion.java new file mode 100644 index 0000000000..2ae3808bb2 --- /dev/null +++ b/base/src/org/compiere/model/MUOMConversion.java @@ -0,0 +1,736 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.awt.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Unit of Measure Conversion Model + * + * @author Jorg Janke + * @version $Id: MUOMConversion.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MUOMConversion extends X_C_UOM_Conversion +{ + /** + * Convert qty to target UOM and round. + * @param ctx context + * @param C_UOM_ID from UOM + * @param C_UOM_To_ID to UOM + * @param qty qty + * @return converted qty (std precision) + */ + static public BigDecimal convert (Properties ctx, + int C_UOM_ID, int C_UOM_To_ID, BigDecimal qty) + { + if (qty == null || qty.equals(Env.ZERO) || C_UOM_ID == C_UOM_To_ID) + return qty; + BigDecimal retValue = getRate (ctx, C_UOM_ID, C_UOM_To_ID); + if (retValue != null) + { + MUOM uom = MUOM.get (ctx, C_UOM_To_ID); + if (uom != null) + return uom.round(retValue.multiply(qty), true); + return retValue.multiply(qty); + } + return null; + } // convert + + /** + * Get Multiplier Rate to target UOM + * @param ctx context + * @param C_UOM_ID from UOM + * @param C_UOM_To_ID to UOM + * @return multiplier + */ + static public BigDecimal getRate (Properties ctx, + int C_UOM_ID, int C_UOM_To_ID) + { + // nothing to do + if (C_UOM_ID == C_UOM_To_ID) + return Env.ONE; + // + Point p = new Point(C_UOM_ID, C_UOM_To_ID); + // get conversion + BigDecimal retValue = getRate (ctx, p); + return retValue; + } // convert + + + /** + * Convert qty to target UOM and round. + * @param ctx context + * @param C_UOM_ID from UOM + * @param qty qty + * @return minutes - 0 if not found + */ + static public int convertToMinutes (Properties ctx, + int C_UOM_ID, BigDecimal qty) + { + if (qty == null) + return 0; + int C_UOM_To_ID = MUOM.getMinute_UOM_ID(ctx); + if (C_UOM_ID == C_UOM_To_ID) + return qty.intValue(); + // + BigDecimal result = convert (ctx, C_UOM_ID, C_UOM_To_ID, qty); + if (result == null) + return 0; + return result.intValue(); + } // convert + + /** + * Calculate End Date based on start date and qty + * @param ctx context + * @param startDate date + * @param C_UOM_ID UOM + * @param qty qty + * @return end date + */ + static public Timestamp getEndDate (Properties ctx, Timestamp startDate, int C_UOM_ID, BigDecimal qty) + { + GregorianCalendar endDate = new GregorianCalendar(); + endDate.setTime(startDate); + // + int minutes = MUOMConversion.convertToMinutes (ctx, C_UOM_ID, qty); + endDate.add(Calendar.MINUTE, minutes); + // + Timestamp retValue = new Timestamp(endDate.getTimeInMillis()); + // log.config( "TimeUtil.getEndDate", "Start=" + startDate + // + ", Qty=" + qty + ", End=" + retValue); + return retValue; + } // startDate + + /************************************************************************** + * Get Conversion Multiplier Rate, try to derive it if not found directly + * @param ctx context + * @param p Point with from(x) - to(y) C_UOM_ID + * @return conversion multiplier or null + */ + static private BigDecimal getRate (Properties ctx, Point p) + { + BigDecimal retValue = null; + if (Ini.isClient()) + { + if (s_conversions == null) + createRates(ctx); + retValue = (BigDecimal)s_conversions.get(p); + } + else + retValue = getRate (p.x, p.y); + if (retValue != null) + return retValue; + // try to derive + return deriveRate (ctx, p.x, p.y); + } // getConversion + + /** + * Create Conversion Matrix (Client) + * @param ctx context + */ + private static void createRates (Properties ctx) + { + s_conversions = new CCache("C_UOMConversion", 20); + // + String sql = MRole.getDefault(ctx, false).addAccessSQL ( + "SELECT C_UOM_ID, C_UOM_To_ID, MultiplyRate, DivideRate " + + "FROM C_UOM_Conversion " + + "WHERE IsActive='Y' AND M_Product_ID IS NULL", + "C_UOM_Conversion", MRole.SQL_NOTQUALIFIED, MRole.SQL_RO); + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + Point p = new Point (rs.getInt(1), rs.getInt(2)); + BigDecimal mr = rs.getBigDecimal(3); + BigDecimal dr = rs.getBigDecimal(4); + if (mr != null) + s_conversions.put(p, mr); + // reverse + if (dr == null && mr != null) + dr = Env.ONE.divide(mr, BigDecimal.ROUND_HALF_UP); + if (dr != null) + s_conversions.put(new Point(p.y,p.x), dr); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + s_log.log(Level.SEVERE, sql, e); + } + } // createRatess + + /** + * Derive Standard Conversions + * @param ctx context + * @param C_UOM_ID from UOM + * @param C_UOM_To_ID to UOM + * @return Conversion or null + */ + public static BigDecimal deriveRate (Properties ctx, + int C_UOM_ID, int C_UOM_To_ID) + { + if (C_UOM_ID == C_UOM_To_ID) + return Env.ONE; + // get Info + MUOM from = MUOM.get (ctx, C_UOM_ID); + MUOM to = MUOM.get (ctx, C_UOM_To_ID); + if (from == null || to == null) + return null; + + // Time - Minute + if (from.isMinute()) + { + if (to.isHour()) + return new BigDecimal(1.0/60.0); + if (to.isDay()) + return new BigDecimal(1.0/1440.0); // 24 * 60 + if (to.isWorkDay()) + return new BigDecimal(1.0/480.0); // 8 * 60 + if (to.isWeek()) + return new BigDecimal(1.0/10080.0); // 7 * 24 * 60 + if (to.isMonth()) + return new BigDecimal(1.0/43200.0); // 30 * 24 * 60 + if (to.isWorkMonth()) + return new BigDecimal(1.0/9600.0); // 4 * 5 * 8 * 60 + if (to.isYear()) + return new BigDecimal(1.0/525600.0); // 365 * 24 * 60 + } + // Time - Hour + if (from.isHour()) + { + if (to.isMinute()) + return new BigDecimal(60.0); + if (to.isDay()) + return new BigDecimal(1.0/24.0); + if (to.isWorkDay()) + return new BigDecimal(1.0/8.0); + if (to.isWeek()) + return new BigDecimal(1.0/168.0); // 7 * 24 + if (to.isMonth()) + return new BigDecimal(1.0/720.0); // 30 * 24 + if (to.isWorkMonth()) + return new BigDecimal(1.0/160.0); // 4 * 5 * 8 + if (to.isYear()) + return new BigDecimal(1.0/8760.0); // 365 * 24 + } + // Time - Day + if (from.isDay()) + { + if (to.isMinute()) + return new BigDecimal(1440.0); // 24 * 60 + if (to.isHour()) + return new BigDecimal(24.0); + if (to.isWorkDay()) + return new BigDecimal(3.0); // 24 / 8 + if (to.isWeek()) + return new BigDecimal(1.0/7.0); // 7 + if (to.isMonth()) + return new BigDecimal(1.0/30.0); // 30 + if (to.isWorkMonth()) + return new BigDecimal(1.0/20.0); // 4 * 5 + if (to.isYear()) + return new BigDecimal(1.0/365.0); // 365 + } + // Time - WorkDay + if (from.isWorkDay()) + { + if (to.isMinute()) + return new BigDecimal(480.0); // 8 * 60 + if (to.isHour()) + return new BigDecimal(8.0); // 8 + if (to.isDay()) + return new BigDecimal(1.0/3.0); // 24 / 8 + if (to.isWeek()) + return new BigDecimal(1.0/5); // 5 + if (to.isMonth()) + return new BigDecimal(1.0/20.0); // 4 * 5 + if (to.isWorkMonth()) + return new BigDecimal(1.0/20.0); // 4 * 5 + if (to.isYear()) + return new BigDecimal(1.0/240.0); // 4 * 5 * 12 + } + // Time - Week + if (from.isWeek()) + { + if (to.isMinute()) + return new BigDecimal(10080.0); // 7 * 24 * 60 + if (to.isHour()) + return new BigDecimal(168.0); // 7 * 24 + if (to.isDay()) + return new BigDecimal(7.0); + if (to.isWorkDay()) + return new BigDecimal(5.0); + if (to.isMonth()) + return new BigDecimal(1.0/4.0); // 4 + if (to.isWorkMonth()) + return new BigDecimal(1.0/4.0); // 4 + if (to.isYear()) + return new BigDecimal(1.0/50.0); // 50 + } + // Time - Month + if (from.isMonth()) + { + if (to.isMinute()) + return new BigDecimal(43200.0); // 30 * 24 * 60 + if (to.isHour()) + return new BigDecimal(720.0); // 30 * 24 + if (to.isDay()) + return new BigDecimal(30.0); // 30 + if (to.isWorkDay()) + return new BigDecimal(20.0); // 4 * 5 + if (to.isWeek()) + return new BigDecimal(4.0); // 4 + if (to.isWorkMonth()) + return new BigDecimal(1.5); // 30 / 20 + if (to.isYear()) + return new BigDecimal(1.0/12.0); // 12 + } + // Time - WorkMonth + if (from.isWorkMonth()) + { + if (to.isMinute()) + return new BigDecimal(9600.0); // 4 * 5 * 8 * 60 + if (to.isHour()) + return new BigDecimal(160.0); // 4 * 5 * 8 + if (to.isDay()) + return new BigDecimal(20.0); // 4 * 5 + if (to.isWorkDay()) + return new BigDecimal(20.0); // 4 * 5 + if (to.isWeek()) + return new BigDecimal(4.0); // 4 + if (to.isMonth()) + return new BigDecimal(20.0/30.0); // 20 / 30 + if (to.isYear()) + return new BigDecimal(1.0/12.0); // 12 + } + // Time - Year + if (from.isYear()) + { + if (to.isMinute()) + return new BigDecimal(518400.0); // 12 * 30 * 24 * 60 + if (to.isHour()) + return new BigDecimal(8640.0); // 12 * 30 * 24 + if (to.isDay()) + return new BigDecimal(365.0); // 365 + if (to.isWorkDay()) + return new BigDecimal(240.0); // 12 * 4 * 5 + if (to.isWeek()) + return new BigDecimal(50.0); // 52 + if (to.isMonth()) + return new BigDecimal(12.0); // 12 + if (to.isWorkMonth()) + return new BigDecimal(12.0); // 12 + } + // + return null; + } // deriveRate + + /************************************************************************** + * Get Conversion Multiplier Rate from Server + * @param C_UOM_ID from UOM + * @param C_UOM_To_ID to UOM + * @return conversion multiplier or null + */ + public static BigDecimal getRate (int C_UOM_ID, int C_UOM_To_ID) + { + return convert (C_UOM_ID, C_UOM_To_ID, GETRATE, false); + } // getConversion + + /** + * Get Converted Qty from Server (no cache) + * @param qty The quantity to be converted + * @param C_UOM_From_ID The C_UOM_ID of the qty + * @param C_UOM_To_ID The targeted UOM + * @param StdPrecision if true, standard precision, if false costing precision + * @return amount + * @depreciated should not be used + */ + public static BigDecimal convert (int C_UOM_From_ID, int C_UOM_To_ID, + BigDecimal qty, boolean StdPrecision) + { + // Nothing to do + if (qty == null || qty.equals(Env.ZERO) + || C_UOM_From_ID == C_UOM_To_ID) + return qty; + // + BigDecimal retValue = null; + int precision = 2; + String sql = "SELECT c.MultiplyRate, uomTo.StdPrecision, uomTo.CostingPrecision " + + "FROM C_UOM_Conversion c" + + " INNER JOIN C_UOM uomTo ON (c.C_UOM_TO_ID=uomTo.C_UOM_ID) " + + "WHERE c.IsActive='Y' AND c.C_UOM_ID=? AND c.C_UOM_TO_ID=? " // #1/2 + + " AND c.M_Product_ID IS NULL" + + "ORDER BY c.AD_Client_ID DESC, c.AD_Org_ID DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, C_UOM_From_ID); + pstmt.setInt(2, C_UOM_To_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + retValue = rs.getBigDecimal(1); + precision = rs.getInt(StdPrecision ? 2 : 3); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (retValue == null) + { + s_log.info ("NOT found - FromUOM=" + C_UOM_From_ID + + ", ToUOM=" + C_UOM_To_ID); + return null; + } + + // Just get Rate + if (GETRATE.equals(qty)) + return retValue; + + // Calculate & Scale + retValue = retValue.multiply(qty); + if (retValue.scale() > precision) + retValue = retValue.setScale(precision, BigDecimal.ROUND_HALF_UP); + return retValue; + } // convert + + + /************************************************************************** + * Convert Qty/Amt from entered UOM TO product UoM and round. + * @param ctx context + * @param M_Product_ID product + * @param C_UOM_To_ID entered UOM + * @param qtyPrice entered quantity or price + * @return Product: Qty/Amt in product UoM (precision rounded) + */ + static public BigDecimal convertProductTo (Properties ctx, + int M_Product_ID, int C_UOM_To_ID, BigDecimal qtyPrice) + { + if (qtyPrice == null || qtyPrice.signum() == 0 + || M_Product_ID == 0 || C_UOM_To_ID == 0) + return qtyPrice; + + BigDecimal retValue = getProductRateTo (ctx, M_Product_ID, C_UOM_To_ID); + if (retValue != null) + { + if (Env.ONE.compareTo(retValue) == 0) + return qtyPrice; + MUOM uom = MUOM.get (ctx, C_UOM_To_ID); + if (uom != null) + return uom.round(retValue.multiply(qtyPrice), true); + return retValue.multiply(qtyPrice); + } + return null; + } // convertProductTo + + /** + * Get Multiplier Rate from entered UOM TO product UoM + * @param ctx context + * @param M_Product_ID product + * @param C_UOM_To_ID entered UOM + * @return multiplier or null + */ + static public BigDecimal getProductRateTo (Properties ctx, + int M_Product_ID, int C_UOM_To_ID) + { + if (M_Product_ID == 0) + return null; + MUOMConversion[] rates = getProductConversions(ctx, M_Product_ID); + if (rates.length == 0) + { + s_log.fine("None found"); + return null; + } + + for (int i = 0; i < rates.length; i++) + { + MUOMConversion rate = rates[i]; + if (rate.getC_UOM_To_ID() == C_UOM_To_ID) + return rate.getMultiplyRate(); + } + s_log.fine("None applied"); + return null; + } // getProductRateTo + + /** + * Convert Qty/Amt FROM product UOM to entered UOM and round. + * @param ctx context + * @param M_Product_ID product + * @param C_UOM_To_ID entered UOM + * @param qtyPrice quantity or price + * @return Entered: Qty in entered UoM (precision rounded) + */ + static public BigDecimal convertProductFrom (Properties ctx, + int M_Product_ID, int C_UOM_To_ID, BigDecimal qtyPrice) + { + // No conversion + if (qtyPrice == null || qtyPrice.equals(Env.ZERO) + || C_UOM_To_ID == 0|| M_Product_ID == 0) + { + s_log.fine("No Conversion - QtyPrice=" + qtyPrice); + return qtyPrice; + } + + BigDecimal retValue = getProductRateFrom (ctx, M_Product_ID, C_UOM_To_ID); + if (retValue != null) + { + if (Env.ONE.compareTo(retValue) == 0) + return qtyPrice; + MUOM uom = MUOM.get (ctx, C_UOM_To_ID); + if (uom != null) + return uom.round(retValue.multiply(qtyPrice), true); + return retValue.multiply(qtyPrice); + } + s_log.fine("No Rate M_Product_ID=" + M_Product_ID); + return null; + } // convertProductFrom + + /** + * Get Divide Rate FROM product UOM to entered UOM and round. + * @param ctx context + * @param M_Product_ID product + * @param C_UOM_To_ID entered UOM + * @return divisor or null + */ + static public BigDecimal getProductRateFrom (Properties ctx, + int M_Product_ID, int C_UOM_To_ID) + { + MUOMConversion[] rates = getProductConversions(ctx, M_Product_ID); + if (rates.length == 0) + { + s_log.fine("getProductRateFrom - none found"); + return null; + } + + for (int i = 0; i < rates.length; i++) + { + MUOMConversion rate = rates[i]; + if (rate.getC_UOM_To_ID() == C_UOM_To_ID) + return rate.getDivideRate(); + } + s_log.fine("None applied"); + return null; + } // getProductRateFrom + + + /** + * Get Product Conversions (cached) + * @param ctx context + * @param M_Product_ID product + * @return array of conversions + */ + static public MUOMConversion[] getProductConversions (Properties ctx, int M_Product_ID) + { + if (M_Product_ID == 0) + return new MUOMConversion[0]; + Integer key = new Integer (M_Product_ID); + MUOMConversion[] result = (MUOMConversion[])s_conversionProduct.get(key); + if (result != null) + return result; + + ArrayList list = new ArrayList(); + // Add default conversion + MUOMConversion defRate = new MUOMConversion (MProduct.get(ctx, M_Product_ID)); + list.add(defRate); + // + String sql = "SELECT * FROM C_UOM_Conversion c " + + "WHERE c.M_Product_ID=?" + + " AND EXISTS (SELECT * FROM M_Product p " + + "WHERE c.M_Product_ID=p.M_Product_ID AND c.C_UOM_ID=p.C_UOM_ID)" + + " AND c.IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, M_Product_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MUOMConversion(ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + // Convert & save + result = new MUOMConversion[list.size ()]; + list.toArray (result); + s_conversionProduct.put(key, result); + s_log.fine("getProductConversions - M_Product_ID=" + M_Product_ID + " #" + result.length); + return result; + } // getProductConversions + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger(MUOMConversion.class); + /** Indicator for Rate */ + private static BigDecimal GETRATE = new BigDecimal(123.456); + /** Conversion Map: Key=Point(from,to) Value=BigDecimal */ + private static CCache s_conversions = null; + /** Product Conversion Map */ + private static CCache s_conversionProduct + = new CCache("C_UOMConversion", 20); + + + /************************************************************************** + * Default Constructor + * @param ctx context + * @param C_UOM_Conversion_ID id + * @param trxName transaction + */ + public MUOMConversion (Properties ctx, int C_UOM_Conversion_ID, String trxName) + { + super(ctx, C_UOM_Conversion_ID, trxName); + } // MUOMConversion + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MUOMConversion(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MUOMConversion + + /** + * Parent Constructor + * @param parent uom parent + */ + public MUOMConversion (MUOM parent) + { + this(parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg (parent); + setC_UOM_ID (parent.getC_UOM_ID()); + setM_Product_ID(0); + // + setC_UOM_To_ID (parent.getC_UOM_ID()); + setMultiplyRate(Env.ONE); + setDivideRate(Env.ONE); + } // MUOMConversion + + /** + * Parent Constructor + * @param parent product parent + */ + public MUOMConversion (MProduct parent) + { + this(parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg (parent); + setC_UOM_ID (parent.getC_UOM_ID()); + setM_Product_ID(parent.getM_Product_ID()); + // + setC_UOM_To_ID (parent.getC_UOM_ID()); + setMultiplyRate(Env.ONE); + setDivideRate(Env.ONE); + } // MUOMConversion + + /** + * Before Save + * @param newRecord new + * @return true if can be saved + */ + protected boolean beforeSave (boolean newRecord) + { + // From - To is the same + if (getC_UOM_ID() == getC_UOM_To_ID()) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@C_UOM_ID@ = @C_UOM_ID@")); + return false; + } + // Nothing to convert + if (getMultiplyRate().compareTo(Env.ZERO) <= 0) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@MultiplyRate@ <= 0")); + return false; + } + // Enforce Product UOM + if (getM_Product_ID() != 0 + && (newRecord || is_ValueChanged("M_Product_ID"))) + { + MProduct product = MProduct.get(getCtx(), getM_Product_ID()); + if (product.getC_UOM_ID() != getC_UOM_ID()) + { + MUOM uom = MUOM.get(getCtx(), product.getC_UOM_ID()); + log.saveError("ProductUOMConversionUOMError", uom.getName()); + return false; + } + } + + // The Product UoM needs to be the smallest UoM - Multiplier must be > 0 + if (getM_Product_ID() != 0 && getDivideRate().compareTo(Env.ONE) < 0) + { + log.saveError("ProductUOMConversionRateError", ""); + return false; + } + return true; + } // beforeSave + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MUOMConversion["); + sb.append(get_ID()).append("-C_UOM_ID=").append(getC_UOM_ID()) + .append(",C_UOM_To_ID=").append(getC_UOM_To_ID()) + .append(",M_Product_ID=").append(getM_Product_ID()) + .append("-Multiply=").append(getMultiplyRate()) + .append("/Divide=").append(getDivideRate()) + .append ("]"); + return sb.toString (); + } // toString + +} // UOMConversion diff --git a/base/src/org/compiere/model/MUserMail.java b/base/src/org/compiere/model/MUserMail.java new file mode 100644 index 0000000000..f66caefefe --- /dev/null +++ b/base/src/org/compiere/model/MUserMail.java @@ -0,0 +1,153 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import org.compiere.util.*; + +/** + * User Mail Model + * @author Jorg Janke + * @version $Id: MUserMail.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MUserMail extends X_AD_UserMail +{ + /** + * Standard Constructor + * @param ctx context + * @param AD_UserMail_ID id + * @param trxName trx + */ + public MUserMail (Properties ctx, int AD_UserMail_ID, String trxName) + { + super (ctx, AD_UserMail_ID, trxName); + } // MUserMail + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName trx + */ + public MUserMail (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MUserMail + + /** + * User Mail + * @param parent Request Mail Text + * @param AD_User_ID recipient user + * @param mail email + */ + public MUserMail (MMailText parent, int AD_User_ID, EMail mail) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setAD_User_ID(AD_User_ID); + setR_MailText_ID(parent.getR_MailText_ID()); + // + if (mail.isSentOK()) + setMessageID(mail.getMessageID()); + else + { + setMessageID(mail.getSentMsg()); + setIsDelivered(ISDELIVERED_No); + } + } // MUserMail + + /** + * Parent Constructor + * @param parent Mail message + * @param AD_User_ID recipient user + * @param mail email + */ + public MUserMail (MMailMsg parent, int AD_User_ID, EMail mail) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setAD_User_ID(AD_User_ID); + setW_MailMsg_ID(parent.getW_MailMsg_ID()); + // + if (mail.isSentOK()) + setMessageID(mail.getMessageID()); + else + { + setMessageID(mail.getSentMsg()); + setIsDelivered(ISDELIVERED_No); + } + } // MUserMail + + /** + * New User Mail (no trx) + * @param po persistent object + * @param AD_User_ID recipient user + * @param mail email + */ + public MUserMail (PO po, int AD_User_ID, EMail mail) + { + this (po.getCtx(), 0, null); + setClientOrg(po); + setAD_User_ID(AD_User_ID); + setSubject(mail.getSubject()); + setMailText(mail.getMessageCRLF()); + // + if (mail.isSentOK()) + setMessageID(mail.getMessageID()); + else + { + setMessageID(mail.getSentMsg()); + setIsDelivered(ISDELIVERED_No); + } + } // MUserMail + + + /** + * Is it Delivered + * @return true if yes + */ + public boolean isDelivered() + { + String s = getIsDelivered(); + return s != null + && ISDELIVERED_Yes.equals(s); + } // isDelivered + + /** + * Is it not Delivered + * @return true if null or no + */ + public boolean isDeliveredNo() + { + String s = getIsDelivered(); + return s == null + || ISDELIVERED_No.equals(s); + } // isDelivered + + /** + * Is Delivered unknown + * @return true if null + */ + public boolean isDeliveredUnknown() + { + String s = getIsDelivered(); + return s == null; + } // isDeliveredUnknown + +} // MUserMail diff --git a/base/src/org/compiere/model/MWarehousePrice.java b/base/src/org/compiere/model/MWarehousePrice.java new file mode 100644 index 0000000000..18d078111c --- /dev/null +++ b/base/src/org/compiere/model/MWarehousePrice.java @@ -0,0 +1,238 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Product Warehouse Availability and Price Model. + * The Ownership (Client, Org) is determined by the Warehouse + * Active is determined if the product is discontinued (the product/price/warehouse need to be active) + * Created.. is determined by the price list version + * + * @author Jorg Janke + * @version $Id: MWarehousePrice.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MWarehousePrice extends X_RV_WarehousePrice +{ + /** + * Find Products in Warehouse with Price + * @param ctx context + * @param M_PriceList_Version_ID mandatory price list + * @param M_Warehouse_ID mandatory warehouse + * @param Value optional value + * @param Name optional name + * @param UPC optional full match upc + * @param SKU optional full match ski + * @param trxName transaction + * @return array of product prices and warehouse availability + */ + public static MWarehousePrice[] find (Properties ctx, + int M_PriceList_Version_ID, int M_Warehouse_ID, + String Value, String Name, String UPC, String SKU, String trxName) + { + StringBuffer sql = new StringBuffer ("SELECT * FROM RV_WarehousePrice " + + "WHERE M_PriceList_Version_ID=? AND M_Warehouse_ID=?"); + StringBuffer sb = new StringBuffer(); + Value = getFindParameter (Value); + if (Value != null) + sb.append("UPPER(Value) LIKE ?"); + Name = getFindParameter (Name); + if (Name != null) + { + if (sb.length() > 0) + sb.append(" OR "); + sb.append("UPPER(Name) LIKE ?"); + } + if (UPC != null && UPC.length() > 0) + { + if (sb.length() > 0) + sb.append(" OR "); + sb.append("UPC=?"); + } + if (SKU != null && SKU.length() > 0) + { + if (sb.length() > 0) + sb.append(" OR "); + sb.append("SKU=?"); + } + if (sb.length() > 0) + sql.append(" AND (").append(sb).append(")"); + sql.append(" ORDER BY Value"); + // + String finalSQL = MRole.getDefault().addAccessSQL(sql.toString(), + "RV_WarehousePrice", MRole.SQL_NOTQUALIFIED, MRole.SQL_RO); + s_log.fine("find - M_PriceList_Version_ID=" + M_PriceList_Version_ID + + ", M_Warehouse_ID=" + M_Warehouse_ID + + " - " + finalSQL); + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(finalSQL, trxName); + int index = 1; + pstmt.setInt(index++, M_PriceList_Version_ID); + pstmt.setInt(index++, M_Warehouse_ID); + if (Value != null) + pstmt.setString(index++, Value); + if (Name != null) + pstmt.setString(index++, Name); + if (UPC != null && UPC.length() > 0) + pstmt.setString(index++, UPC); + if (SKU != null && SKU.length() > 0) + pstmt.setString(index++, SKU); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MWarehousePrice(ctx, rs, trxName)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, finalSQL, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + s_log.fine("find - #" + list.size()); + MWarehousePrice[] retValue = new MWarehousePrice[list.size()]; + list.toArray(retValue); + return retValue; + } // find + + /** + * Find Products in Warehouse with Price for customer + * @param bPartner business partner + * @param IsSOTrx if true SO + * @param valid the date the price must be valid + * @param M_Warehouse_ID mandatory warehouse + * @param Value optional value + * @param Name optional name + * @param UPC optional upc + * @param SKU optional ski + * @param trxName transaction + * @return array of product prices and warehouse availability or null + */ + public static MWarehousePrice[] find (MBPartner bPartner, + boolean IsSOTrx, Timestamp valid, int M_Warehouse_ID, + String Value, String Name, String UPC, String SKU, String trxName) + { + int M_PriceList_ID = IsSOTrx ? bPartner.getM_PriceList_ID() : bPartner.getPO_PriceList_ID(); + MPriceList pl = null; + if (M_PriceList_ID == 0) + pl = MPriceList.getDefault(bPartner.getCtx(), IsSOTrx); + else + pl = MPriceList.get(bPartner.getCtx(), M_PriceList_ID, trxName); + if (pl == null) + { + s_log.severe ("No PriceList found"); + return null; + } + MPriceListVersion plv = pl.getPriceListVersion (valid); + if (plv == null) + { + s_log.severe ("No PriceListVersion found for M_PriceList_ID=" + pl.getM_PriceList_ID()); + return null; + } + // + return find (bPartner.getCtx(), plv.getM_PriceList_Version_ID(), M_Warehouse_ID, + Value, Name, UPC, SKU, trxName); + } // find + + /** + * Get MWarehouse Price + * @param product product + * @param M_PriceList_Version_ID plv + * @param M_Warehouse_ID wh + * @param trxName transaction + * @return warehouse price + */ + public static MWarehousePrice get (MProduct product, + int M_PriceList_Version_ID, int M_Warehouse_ID, String trxName) + { + MWarehousePrice retValue = null; + String sql = "SELECT * FROM RV_WarehousePrice " + + "WHERE M_Product_ID=? AND M_PriceList_Version_ID=? AND M_Warehouse_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, product.getM_Product_ID()); + pstmt.setInt(2, M_PriceList_Version_ID); + pstmt.setInt(3, M_Warehouse_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = new MWarehousePrice(product.getCtx(), rs, trxName); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return retValue; + } // get + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger(MWarehousePrice.class); + + + /************************************************************************* + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MWarehousePrice (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MWarehousePrice + + /** + * Is Product Available + * @return true if available qty > 0 + */ + public boolean isAvailable() + { + return getQtyAvailable().signum() == 1; // > 0 + } // isAvailable + +} // MWarehousePrice diff --git a/base/src/org/compiere/model/MWebProject.java b/base/src/org/compiere/model/MWebProject.java new file mode 100644 index 0000000000..fd2cf718d3 --- /dev/null +++ b/base/src/org/compiere/model/MWebProject.java @@ -0,0 +1,132 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Web Project Model + * + * @author Jorg Janke + * @version $Id: MWebProject.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class MWebProject extends X_CM_WebProject +{ + /** + * Get MWebProject from Cache + * @param ctx context + * @param CM_WebProject_ID id + * @return MWebProject + */ + public static MWebProject get (Properties ctx, int CM_WebProject_ID) + { + Integer key = new Integer (CM_WebProject_ID); + MWebProject retValue = (MWebProject)s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MWebProject (ctx, CM_WebProject_ID, null); + if (retValue.get_ID () == CM_WebProject_ID) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache + = new CCache ("CM_WebProject", 5); + + + /************************************************************************** + * Web Project + * @param ctx context + * @param CM_WebProject_ID id + * @param trxName transaction + */ + public MWebProject (Properties ctx, int CM_WebProject_ID, String trxName) + { + super (ctx, CM_WebProject_ID, trxName); + } // MWebProject + + /** + * Web Project + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MWebProject (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MWebProject + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + // Create Trees + if (newRecord) + { + MTree_Base tree = new MTree_Base (getCtx(), + getName()+MTree_Base.TREETYPE_CMContainer, MTree_Base.TREETYPE_CMContainer, get_TrxName()); + if (!tree.save()) + return false; + setAD_TreeCMC_ID(tree.getAD_Tree_ID()); + // + tree = new MTree_Base (getCtx(), + getName()+MTree_Base.TREETYPE_CMContainerStage, MTree_Base.TREETYPE_CMContainerStage, get_TrxName()); + if (!tree.save()) + return false; + setAD_TreeCMS_ID(tree.getAD_Tree_ID()); + // + tree = new MTree_Base (getCtx(), + getName()+MTree_Base.TREETYPE_CMTemplate, MTree_Base.TREETYPE_CMTemplate, get_TrxName()); + if (!tree.save()) + return false; + setAD_TreeCMT_ID(tree.getAD_Tree_ID()); + // + tree = new MTree_Base (getCtx(), + getName()+MTree_Base.TREETYPE_CMMedia, MTree_Base.TREETYPE_CMMedia, get_TrxName()); + if (!tree.save()) + return false; + setAD_TreeCMM_ID(tree.getAD_Tree_ID()); + } + return true; + } // beforeSave + + /** + * After Save. + * Insert + * - create tree + * @param newRecord insert + * @param success save success + * @return true if saved + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + if (!newRecord) + { + // Clean Web Project Cache + } + return success; + } // afterSave + +} // MWebProject diff --git a/base/src/org/compiere/model/MWebProjectDomain.java b/base/src/org/compiere/model/MWebProjectDomain.java new file mode 100644 index 0000000000..8c56db29bb --- /dev/null +++ b/base/src/org/compiere/model/MWebProjectDomain.java @@ -0,0 +1,52 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + +/** + * Web Project Domain + * + * @author Jorg Janke + * @version $Id: MWebProjectDomain.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MWebProjectDomain extends X_CM_WebProject_Domain +{ + /** + * Web Project Domain Constructor + * @param ctx context + * @param CM_WebProject_Domain_ID id + * @param trxName transaction + */ + public MWebProjectDomain (Properties ctx, int CM_WebProject_Domain_ID, String trxName) + { + super (ctx, CM_WebProject_Domain_ID, trxName); + } // MWebProjectDomain + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MWebProjectDomain (Properties ctx, ResultSet rs, String trxName) + { + super (ctx, rs, trxName); + } // MWebProjectDomain + +} // MWebProjectDomain diff --git a/base/src/org/compiere/model/MWithholding.java b/base/src/org/compiere/model/MWithholding.java new file mode 100644 index 0000000000..7764b8a334 --- /dev/null +++ b/base/src/org/compiere/model/MWithholding.java @@ -0,0 +1,76 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; + + +/** + * Withholding Model + * + * @author Jorg Janke + * @version $Id: MWithholding.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MWithholding extends X_C_Withholding +{ + /** + * Standard Constructor + * @param ctx context + * @param C_Withholding_ID id + * @param trxName transaction + */ + public MWithholding (Properties ctx, int C_Withholding_ID, String trxName) + { + super (ctx, C_Withholding_ID, trxName); + } // MWithholding + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MWithholding (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MWithholding + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (newRecord & success) + insert_Accounting("C_Withholding_Acct", "C_AcctSchema_Default", null); + + return success; + } // afterSave + + /** + * Before Delete + * @return true + */ + protected boolean beforeDelete () + { + return delete_Accounting("C_Withholding_Acct"); + } // beforeDelete + +} // MWithholding diff --git a/base/src/org/compiere/model/MYear.java b/base/src/org/compiere/model/MYear.java new file mode 100644 index 0000000000..aaca4c5e06 --- /dev/null +++ b/base/src/org/compiere/model/MYear.java @@ -0,0 +1,224 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.text.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.process.*; +import org.compiere.util.*; + + +/** + * Year Model + * + * @author Jorg Janke + * @version $Id: MYear.java,v 1.5 2006/10/11 04:12:39 jjanke Exp $ + */ +public class MYear extends X_C_Year +{ + + /** + * Standard Constructor + * @param ctx context + * @param C_Year_ID id + * @param trxName transaction + */ + public MYear (Properties ctx, int C_Year_ID, String trxName) + { + super (ctx, C_Year_ID, trxName); + if (C_Year_ID == 0) + { + // setC_Calendar_ID (0); + // setYear (null); + setProcessing (false); // N + } + } // MYear + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MYear (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MYear + + /** + * Parent Constructor + * @param calendar parent + */ + public MYear (MCalendar calendar) + { + this (calendar.getCtx(), 0, calendar.get_TrxName()); + setClientOrg(calendar); + setC_Calendar_ID(calendar.getC_Calendar_ID()); + setYear(); + } // MYear + + + /** + * Set current Year + */ + private void setYear () + { + GregorianCalendar cal = new GregorianCalendar(Language.getLoginLanguage().getLocale()); + String Year = String.valueOf(cal.get(Calendar.YEAR)); + super.setFiscalYear(Year); + } // setYear + + /** + * Get Year As Int + * @return year as int or 0 + */ + public int getYearAsInt() + { + String year = getFiscalYear(); + try + { + return Integer.parseInt(year); + } + catch (Exception e) + { + StringTokenizer st = new StringTokenizer(year, "/-, \t\n\r\f"); + if (st.hasMoreTokens()) + { + String year2 = st.nextToken(); + try + { + return Integer.parseInt(year2); + } + catch (Exception e2) + { + log.log(Level.WARNING, year + "->" + year2 + " - " + e2.toString()); + } + } + else + log.log(Level.WARNING, year + " - " + e.toString()); + } + return 0; + } // getYearAsInt + + /** + * Get last two characters of year + * @return 01 + */ + public String getYY() + { + int yy = getYearAsInt(); + String year = String.valueOf(yy); + if (year.length() == 4) + return year.substring(2, 4); + return getFiscalYear(); + } // getYY + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MYear["); + sb.append(get_ID()).append("-") + .append(getFiscalYear()) + .append ("]"); + return sb.toString (); + } // toString + + + /** + * Before Save + * @param newRecord new + * @return true if can be saved + */ + protected boolean beforeSave (boolean newRecord) + { + int yy = getYearAsInt(); + if (yy == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "Year") + + " -> " + yy + " (2006 - 2006/07 - 2006-07 - ...)"); + return false; + } + return true; + } // beforeSave + + /** + * Create 12 Standard (Jan-Dec) Periods. + * Creates also Period Control from DocType. + * @see DocumentTypeVerify#createPeriodControls(Properties, int, SvrProcess, String) + * @param locale locale + * @return true if created + */ + public boolean createStdPeriods(Locale locale) + { + if (locale == null) + { + MClient client = MClient.get(getCtx()); + locale = client.getLocale(); + } + + if (locale == null && Language.getLoginLanguage() != null) + locale = Language.getLoginLanguage().getLocale(); + if (locale == null) + locale = Env.getLanguage(getCtx()).getLocale(); + // + String[] months = null; + try + { + DateFormatSymbols symbols = new DateFormatSymbols(locale); + months = symbols.getShortMonths(); + } + catch (Exception e) + { + months = new String[]{"Jan", "Feb", "Nar", + "Apr", "May", "Jun", + "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec"}; + } + // + int year = getYearAsInt(); + GregorianCalendar cal = new GregorianCalendar(locale); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + // + for (int month = 0; month < 12; month++) + { + cal.set(Calendar.YEAR, year); + cal.set(Calendar.MONTH, month); + cal.set(Calendar.DAY_OF_MONTH, 1); + Timestamp start = new Timestamp(cal.getTimeInMillis()); + String name = months[month] + "-" + getYY(); + // + cal.add(Calendar.MONTH, 1); + cal.add(Calendar.DAY_OF_YEAR, -1); + Timestamp end = new Timestamp(cal.getTimeInMillis()); + // + MPeriod period = new MPeriod (this, month+1, name, start, end); + if (!period.save(get_TrxName())) // Creates Period Control + return false; + } + return true; + } // createStdPeriods + +} // MYear diff --git a/base/src/org/compiere/model/Measure.java b/base/src/org/compiere/model/Measure.java new file mode 100644 index 0000000000..48bd4c4686 --- /dev/null +++ b/base/src/org/compiere/model/Measure.java @@ -0,0 +1,51 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.BigDecimal; + +/** + * Performance Key Indicator Interface + * + * @author Jorg Janke + * @version $Id: Measure.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public interface Measure +{ + /** + * Create new Measures for the Performance Goal? + * @param measure measure + * @return true if measure not created via MeasureCalc (sql) + */ + public boolean isCreateMeasures (MMeasure measure); + + /** + * Create new Measures for the Performance Goal. + * Called only if isCreateMeasures is true + * @param measure measure + * @return number created + */ + public int createMeasures (MMeasure measure); + + /** + * Calculate Parformance Goal Actual + * @param measure measure + * @return new Actual Measure + */ + public BigDecimal calculateMeasure (MMeasure measure); + +} // Measure diff --git a/base/src/org/compiere/model/MultiMap.java b/base/src/org/compiere/model/MultiMap.java new file mode 100644 index 0000000000..df8a4e9000 --- /dev/null +++ b/base/src/org/compiere/model/MultiMap.java @@ -0,0 +1,253 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.util.*; +import org.compiere.util.*; + +/** + * MultiMap allows multiple keys with their values. + * It accepts null values as keys and values. + * (implemented as two array lists) + * + * @author Jorg Janke + * @version $Id: MultiMap.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + * @param Key + * @param Value + */ +public final class MultiMap implements Map, Serializable +{ + /** + * Constructor with 10 initial Capacity (same as ArrayList) + */ + public MultiMap() + { + this(10); + } // MultiMap + + /** + * Constructor + * @param initialCapacity initial capacity + */ + public MultiMap(int initialCapacity) + { + m_keys = new ArrayList(initialCapacity); + m_values = new ArrayList(initialCapacity); + } // MultiMap + + private ArrayList m_keys = null; + private ArrayList m_values = null; + + /** + * Return number of elements + * @return size + */ + public int size() + { + return m_keys.size(); + } // size + + /** + * Is Empty + * @return true if empty + */ + public boolean isEmpty() + { + return (m_keys.size() == 0); + } // isEmpty + + /** + * Contains Key + * @param key test key + * @return true if key exist + */ + public boolean containsKey(Object key) + { + return m_keys.contains(key); + } // containsKey + + /** + * Contains Value + * @param value test value + * @return true if value exists + */ + public boolean containsValue(Object value) + { + return m_values.contains(value); + } // containsKey + + /** + * Return ArrayList of Values of Key + * @param key key + * @return value + */ + @SuppressWarnings("unchecked") + public V get(Object key) + { + return (V)getValues(key); + } // get + + /** + * Return ArrayList of Values of Key + * @param key key + * @return array list of values + */ + public ArrayList getValues (Object key) + { + ArrayList list = new ArrayList(); + // We don't have it + if (!m_keys.contains(key)) + return list; + // go through keys + int size = m_keys.size(); + for (int i = 0; i < size; i++) + { + if (m_keys.get(i).equals(key)) + if (!list.contains(m_values.get(i))) + list.add(m_values.get(i)); + } + return list; + } // getValues + + /** + * Return ArrayList of Keys with Value + * @param value value + * @return array list of keys + */ + public ArrayList getKeys (Object value) + { + ArrayList list = new ArrayList(); + // We don't have it + if (!m_values.contains(value)) + return list; + // go through keys + int size = m_values.size(); + for (int i = 0; i < size; i++) + { + if (m_values.get(i).equals(value)) + if (!list.contains(m_keys.get(i))) + list.add(m_keys.get(i)); + } + return list; + } // getKeys + + /** + * Put Key & Value + * @param key + * @param value + * @return always null + */ + public V put (K key, V value) + { + m_keys.add(key); + m_values.add(value); + return null; + } // put + + /** + * Remove key + * @param key key + * @return removed value + */ + public V remove (Object key) + { + throw new java.lang.UnsupportedOperationException("Method remove() not implemented."); + } // remove + + /** + * Put all + * @param t + */ + public void putAll(Map t) + { + throw new java.lang.UnsupportedOperationException("Method putAll() not implemented."); + } // putAll + + /** + * Clear content + */ + public void clear() + { + m_keys.clear(); + m_values.clear(); + } // clear + + /** + * Return HashSet of Keys + * @return key set + */ + public Set keySet() + { + HashSet keys = new HashSet(m_keys); + return keys; + } // keySet + + /** + * Return Collection of values + * @return values + */ + public Collection values() + { + return m_values; + } // values + + /** + * Get entry set - not implemented + * @return entry set + */ + public Set> entrySet() + { + throw new java.lang.UnsupportedOperationException("Method entrySet() not implemented."); + } + + /** + * Equals - not implemented + * @param o test object + * @return true if equal + */ + public boolean equals(Object o) + { + throw new java.lang.UnsupportedOperationException("Method equals() not implemented."); + } + + /************************************************************************** + * Returns class name and number of entries + * @return info + */ + public String toString() + { + return "MultiMap #" + m_keys.size(); + } // toString + + /** + * dump all keys - values to log + */ + public void printToLog() + { + CLogger log = CLogger.getCLogger(getClass()); + log.fine("MultiMap.printToLog"); + int size = m_keys.size(); + for (int i = 0; i < size; i++) + { + Object k = m_keys.get(i); + Object v = m_values.get(i); + log.finest(k==null ? "null" : k.toString() + "=" + v==null ? "null" : v.toString()); + } + } // printToLog + +} // MultiMap diff --git a/base/src/org/compiere/model/NaturalAccountMap.java b/base/src/org/compiere/model/NaturalAccountMap.java new file mode 100644 index 0000000000..db6b84796c --- /dev/null +++ b/base/src/org/compiere/model/NaturalAccountMap.java @@ -0,0 +1,280 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Natural Account (HashMap) Management. + * + *
+ *  The key is a String of the column name (e.g. SUSPENSEBALANCING_ACCT)
+ *  The value is an NaturalAccount
+ *
+ *  a) Account information are loaded via the parse functions
+ *  b) Accounts are created via the createAccounts function
+ *  c) retrieve the C_ElementValue_ID for the given key
+ *  
+ * + * @author Jorg Janke + * @version $Id: NaturalAccountMap.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + * @param key + * @param value + */ +public final class NaturalAccountMap extends CCache +{ + /** + * Constructor. + * Parse File does the processing + * @param ctx context + * @param trxName transaction + */ + public NaturalAccountMap(Properties ctx, String trxName) + { + super("NaturalAccountMap", 100); + m_ctx = ctx; + m_trxName = trxName; + } // NaturalAccountMap + + /** Delimiter */ + private String m_delim = ","; + /** KeyNo */ + private static int s_keyNo = 0; + /** Context */ + private Properties m_ctx = null; + /** Transaction */ + private String m_trxName = null; + /** Map of Values and Element */ + private HashMap m_valueMap = new HashMap(); + /** Logger */ + private static CLogger log = CLogger.getCLogger(NaturalAccountMap.class); + + /** + * Read and Parse File + * @param file Accounts file + * @return error message or "" if OK + */ + public String parseFile (File file) + { + log.config(file.getAbsolutePath()); + String line = null; + try + { + // see FileImport + BufferedReader in = new BufferedReader(new FileReader(file), 10240); + // not safe see p108 Network pgm + String errMsg = ""; + + // read lines + while ((line = in.readLine()) != null && errMsg.length() == 0) + errMsg = parseLine(line); + line = ""; + in.close(); + + // Error + if (errMsg.length() != 0) + return errMsg; + } + catch (Exception ioe) + { + String s = ioe.getLocalizedMessage(); + if (s == null || s.length() == 0) + s = ioe.toString(); + return "Parse Error: Line=" + line + " - " + s; + } + return ""; + } // parse + + /** + * Create Account Entry for Default Accounts only. + * @param line line with info + * Line format (9 fields) + * 1 A [Account Value] + * 2 B [Account Name] + * 3 C [Description] + * 4 D [Account Type] + * 5 E [Account Sign] + * 6 F [Document Controlled] + * 7 G [Summary Account] + * 8 H [Default_Account] + * 9 I [Parent Value] - ignored + * + * @return error message or "" if OK + * @throws Exception + */ + @SuppressWarnings("unchecked") + public String parseLine (String line) throws Exception + { + log.config(line); + + // Fields with ',' are enclosed in " + StringBuffer newLine = new StringBuffer(); + StringTokenizer st = new StringTokenizer(line, "\"", false); + newLine.append(st.nextToken()); // first part + while (st.hasMoreElements()) + { + String s = st.nextToken(); // enclosed part + newLine.append(s.replace(',',' ')); // remove ',' with space + if (st.hasMoreTokens()) + newLine.append(st.nextToken()); // unenclosed + } + // add space at the end - tokenizer does not count empty fields + newLine.append(" "); + + // Parse Line - replace ",," with ", ," - tokenizer does not count empty fields + String pLine = Util.replace(newLine.toString(), ",,", ", ,"); + pLine = Util.replace(pLine, ",,", ", ,"); + st = new StringTokenizer(pLine, ",", false); + // All fields there ? + if (st.countTokens() == 1) + { + log.log(Level.SEVERE, "Ignored: Require ',' as separator - " + pLine); + return ""; + } + if (st.countTokens() < 9) + { + log.log(Level.SEVERE, "Ignored: FieldNumber wrong: " + st.countTokens() + " - " + pLine); + return ""; + } + + // Fill variables + String Value = null, Name = null, Description = null, + AccountType = null, AccountSign = null, IsDocControlled = null, + IsSummary = null, Default_Account = null; + // + for (int i = 0; i < 8 && st.hasMoreTokens(); i++) + { + String s = st.nextToken().trim(); + // Ignore, if is it header line + if (s.startsWith("[") && s.endsWith("]")) + return ""; + if (s == null) + s = ""; + // + if (i == 0) // A - Value + Value = s; + else if (i == 1) // B - Name + Name = s; + else if (i == 2) // C - Description + Description = s; + else if (i == 3) // D - Type + AccountType = s.length()>0 ? String.valueOf(s.charAt(0)) : "E"; + else if (i == 4) // E - Sign + AccountSign = s.length()>0 ? String.valueOf(s.charAt(0)) : "N"; + else if (i == 5) // F - DocControlled + IsDocControlled = s.length()>0 ? String.valueOf(s.charAt(0)) : "N"; + else if (i == 6) // G - IsSummary + IsSummary = s.length()>0 ? String.valueOf(s.charAt(0)) : "N"; + else if (i == 7) // H - Default_Account + Default_Account = s; + } + + // Ignore if Value & Name are empty (no error message) + if ((Value == null || Value.length() == 0) && (Name == null || Name.length() == 0)) + return ""; + + // Default Account may be blank + if (Default_Account == null || Default_Account.length() == 0) + // Default_Account = String.valueOf(s_keyNo++); + return ""; + + // No Summary Account + if (IsSummary == null || IsSummary.length() == 0) + IsSummary = "N"; + if (!IsSummary.equals("N")) + return ""; + + // Validation + if (AccountType == null || AccountType.length() == 0) + AccountType = "E"; + + if (AccountSign == null || AccountSign.length() == 0) + AccountSign = "N"; + if (IsDocControlled == null || IsDocControlled.length() == 0) + IsDocControlled = "N"; + + + // log.config( "Value=" + Value + ", AcctType=" + AccountType + // + ", Sign=" + AccountSign + ", Doc=" + docControlled + // + ", Summary=" + summary + " - " + Name + " - " + Description); + + try + { + // Try to find - allows to use same natutal account for multiple default accounts + MElementValue na = (MElementValue)m_valueMap.get(Value); + if (na == null) + { + // Create Account - save later + na = new MElementValue(m_ctx, Value, Name, Description, + AccountType, AccountSign, + IsDocControlled.toUpperCase().startsWith("Y"), + IsSummary.toUpperCase().startsWith("Y"), m_trxName); + m_valueMap.put(Value, na); + } + + // Add to Cache + put((K)Default_Account.toUpperCase(), (V)na); + } + catch (Exception e) + { + return (e.getMessage()); + } + + return ""; + } // parseLine + + /** + * Save all Accounts + * + * @param AD_Client_ID client + * @param AD_Org_ID org + * @param C_Element_ID element + * @return true if created + */ + public boolean saveAccounts (int AD_Client_ID, int AD_Org_ID, int C_Element_ID) + { + log.config(""); + Iterator iterator = this.values().iterator(); + while (iterator.hasNext()) + { + MElementValue na = (MElementValue)iterator.next(); + na.setAD_Client_ID(AD_Client_ID); + na.setAD_Org_ID(AD_Org_ID); + na.setC_Element_ID(C_Element_ID); + if (!na.save()) + return false; + } + return true; + } // saveAccounts + + /** + * Get ElementValue + * @param key key + * @return 0 if error + */ + public int getC_ElementValue_ID (String key) + { + MElementValue na = (MElementValue)this.get(key); + if (na == null) + return 0; + return na.getC_ElementValue_ID(); + } // getC_ElementValue_ID + +} // NaturalAccountMap diff --git a/base/src/org/compiere/model/PP_Authorize.java b/base/src/org/compiere/model/PP_Authorize.java new file mode 100644 index 0000000000..42c2cd8c4f --- /dev/null +++ b/base/src/org/compiere/model/PP_Authorize.java @@ -0,0 +1,54 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; + +/** + * Authorize.net Payment Processor Services Interface + * + * @author Jorg Janke + * @version $Id: PP_Authorize.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class PP_Authorize extends PaymentProcessor + implements Serializable +{ + /** Status */ + private boolean m_ok = false; + + /** + * Process CC + * @return processed ok + * @throws IllegalArgumentException + */ + public boolean processCC () + throws IllegalArgumentException + { + setEncoded(true); + return m_ok; + } // processCC + + /** + * Is Processed OK + * @return true if OK + */ + public boolean isProcessedOK () + { + return m_ok; + } // isProcessedOK + +} // PP_Authorize diff --git a/base/src/org/compiere/model/PP_Optimal.java b/base/src/org/compiere/model/PP_Optimal.java new file mode 100644 index 0000000000..a0a2e7aabc --- /dev/null +++ b/base/src/org/compiere/model/PP_Optimal.java @@ -0,0 +1,339 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Optimal Payment Processor Services Interface. + * + * @author Jorg Janke + * @version $Id: PP_Optimal.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class PP_Optimal extends PaymentProcessor + implements Serializable +{ + /** + * PP_Optimal + */ + public PP_Optimal () + { + super (); + } // PP_Optimal + + /** Status */ + private boolean m_ok = false; + /** Optimal Client Version */ + private static final String _CLIENT_VERSION = "1.1"; + + // Mandatory parameters + protected static final String MERCHANT_ID = "merchantId"; + protected static final String MERCHANT_PWD = "merchantPwd"; + protected static final String ACCOUNT_ID = "account"; + protected static final String CIPHER = "Cipher"; + protected static final String PAYMENT_SERVER = "PaymentServerURL"; + protected static final String PAYMENT_SERVER_PORT = "PaymentServerPort"; + protected static final String PROXY_SERVER = "ProxyServer"; + protected static final String PROXY_PORT = "ProxyPort"; + protected static final String PROXY_USERID = "ProxyUserId"; + protected static final String PROXY_PWD = "ProxyPwd"; + protected static final String ACTIVE_RECOVERY = "ActiveRecovery"; + protected static final String HTTPVERSION = "HTTPVersion"; + + // Optional parameters + protected static final String RETRIES = "Retries"; + protected static final String TIMEOUT = "Timeout"; + protected static final String LOGLEVEL = "LogLevel"; + protected static final String LOG_BASE_PATH = "LogBasePath"; + protected static final String LOG_FILENAME = "LogFilename"; + protected static final String LOG_MAX_SIZE = "LogMaxSize"; + protected static final String LOG_MAX_BACKUP = "LogMaxBackupFiles"; + + // some request parameters + protected static final String MERCHANT_TXN = "merchantTxn"; + protected static final String MERCHANT_DATA = "merchantData"; + protected static final String CLIENT_VERSION = "clientVersion"; + protected static final String TXN_NUMBER = "txnNumber"; + protected static final String CARD_NUMBER = "cardNumber"; + protected static final String CARD_EXPIRATION = "cardExp"; + protected static final String CARD_TYPE = "cardType"; + protected static final String STREET = "streetAddr"; + protected static final String STREET2 = "streetAddr2"; + protected static final String EMAIL = "email"; + protected static final String PHONE = "phone"; + protected static final String PROVINCE = "province"; + protected static final String COUNTRY = "country"; + protected static final String CITY = "city"; + protected static final String ZIP = "zip"; + protected static final String CVD_INDICATOR = "cvdIndicator"; + protected static final String CVD_INDICATOR_None = "0"; + protected static final String CVD_INDICATOR_Provided = "1"; + protected static final String CVD_VALUE = "cvdValue"; + protected static final String CVD_INFO = "cvdInfo"; + protected static final String CUST_NAME1 = "custName1"; + protected static final String CUST_NAME2 = "custName2"; + + // some response parameters + protected static final String STATUS = "status"; + protected static final String TXN_TYPE = "txnType"; + protected static final String AMOUNT = "amount"; + protected static final String CURRENT_AMOUNT = "curAmount"; + protected static final String ERROR_CODE = "errCode"; + protected static final String ERROR_STRING = "errString"; + protected static final String SUB_ERROR = "subError"; + protected static final String SUB_ERROR_STRING = "subErrorString"; + + protected static final String AUTH_CODE = "authCode"; + protected static final String AUTH_TIME = "authTime"; + protected static final String AVS_INFO = "avsInfo"; + + + // some useful constants + protected static final String QUERY_OPERATION = "Q"; + protected static final String FAILURE_LOOKUP_OPERATION = "FT"; + /** Operation p1-8 */ + protected static final String OPERATION = "operation"; + protected static final String OPERATION_Purchase = "P"; + protected static final String OPERATION_Authorization = "A"; + protected static final String OPERATION_Settlement = "S"; + + + + // Stratus returned by Failure Lookup Request + protected static final String STATUS_SEARCH_COMPLETED = "status=C" ; + // Status returned by a Query Request + protected static final String REQUEST_PENDING = "status=P"; + protected static final String REQUEST_COMPLETE = "status=C"; + protected static final String REQUEST_FAILED = "status=F"; + protected static final String AUTHORIZATION_COMPLETE = "status=A"; + protected static final String AUTHORIZATION_FAILED = "status=AF"; + protected static final String SETTLEMENT_COMPLETE = "status=S"; + protected static final String SETTLEMENT_FAILED = "status=SF"; + protected static final String MANUAL_INTERVENTION = "status=M"; + protected static final String REQUEST_ABORTED = "status=AB"; + protected static final String REQUEST_NOT_FOUND = "status=NF"; + protected static final String UNKNOWN_TYPE = "status=U"; + protected static final String REQUEST_ERROR = "status=E"; + /** AVS Codes */ + protected static Properties AVSCodes = new Properties(); + /** Card Types */ + protected static Properties CARDTypes = new Properties(); + /** CVD Info */ + protected static Properties CVDInfo = new Properties(); + + static + { + // Page 1-9 + AVSCodes.put("X", "Exact. Nine digit zip and address match"); + AVSCodes.put("Y", "Yes. Five digit zip and address match"); + AVSCodes.put("A", "Address matches, Zip not"); + AVSCodes.put("W", "Nine digit zip matches, address not"); + AVSCodes.put("Z", "Five digit zip matches, address not"); + AVSCodes.put("N", "No Part matches"); + AVSCodes.put("U", "Address info unabailable"); + AVSCodes.put("R", "Retry"); + AVSCodes.put("S", "AVS not supported"); + AVSCodes.put("E", "AVS not supported for this industry"); + AVSCodes.put("B", "AVS not performed"); + AVSCodes.put("Q", "Unknown response from issuer"); + // Page 1-14 + CARDTypes.put("AMEX", "AM"); + CARDTypes.put("DINERS", "DI"); + CARDTypes.put("VISA", "VI"); + // CVD Info 1-20 + CVDInfo.put("M", "Match"); + CVDInfo.put("N", "No Match"); + CVDInfo.put("P", "Not Processed"); + CVDInfo.put("S", "Not Present"); + CVDInfo.put("U", "Issuer not certified"); + } + + /** + * Get Version + * @return version + */ + public String getVersion() + { + return "Optimal " + _CLIENT_VERSION; + } // getVersion + + /** + * Process CC + * @return true if OK + * @throws IllegalArgumentException + */ + public boolean processCC () + throws IllegalArgumentException + { + log.fine(p_mpp.getHostAddress() + ":" + p_mpp.getHostPort() + ", Timeout=" + getTimeout() + + "; Proxy=" + p_mpp.getProxyAddress() + ":" + p_mpp.getProxyPort() + " " + p_mpp.getProxyLogon() + " " + p_mpp.getProxyPassword()); + setEncoded(true); + + String urlString = p_mpp.getHostAddress(); + // "https://realtime.firepay.com/servlet/DPServlet"; + // "https://realtime.test.firepay.com/servlet/DPServlet"; + if (p_mpp.getHostPort() != 0) + urlString += ":" + p_mpp.getHostPort(); + + /** General Parameters */ + StringBuffer param = new StringBuffer(200); + // Merchant username and password. + param.append(createPair(MERCHANT_ID, p_mpp.getUserID(), 80)) + .append(AMP).append(createPair(MERCHANT_PWD, p_mpp.getPassword(), 20)) + .append(AMP).append(createPair(ACCOUNT_ID, p_mpp.getPartnerID(), 10)); + // param.append(AMP).append(createPair(MERCHANT_DATA, "comment", 255)); + + /** Cipher supported : SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5 + param.append("&Cipher=SSL_RSA_WITH_RC4_128_MD5"); + // HTTP Version + param.append("&HTTPVersion=1.0"); + // Path to the keystore (cacerts) file. + **/ + + param.append(AMP).append(createPair(CARD_TYPE, "VI", 6)); + param.append(AMP).append(createPair(CARD_NUMBER, p_mp.getCreditCardNumber(), 19)); + param.append(AMP).append(createPair(CARD_EXPIRATION, p_mp.getCreditCardExp("/"), 5)); + param.append(AMP).append(createPair(AMOUNT, p_mp.getPayAmtInCents(), 10)); + param.append(AMP).append(createPair(OPERATION, OPERATION_Purchase, 1)); + param.append(AMP).append(createPair(MERCHANT_TXN, p_mp.getC_Payment_ID(), 255)); + param.append(AMP).append(createPair(CLIENT_VERSION, _CLIENT_VERSION, 4)); + param.append(AMP).append(createPair(CUST_NAME1, p_mp.getA_Name(), 255)); + param.append(AMP).append(createPair(STREET, p_mp.getA_Street(), 255)); + param.append(AMP).append(createPair(CITY, p_mp.getA_City(), 255)); + param.append(AMP).append(createPair(PROVINCE, p_mp.getA_State(), 2)); + param.append(AMP).append(createPair(ZIP, p_mp.getA_Zip(), 10)); + param.append(AMP).append(createPair(COUNTRY, p_mp.getA_Country(), 2)); + // param.append(AMP).append(createPair("&phone", p_mp.getA_Phone(), 40)); + param.append(AMP).append(createPair("&email", p_mp.getA_EMail(), 40)); + param.append(AMP).append(createPair(CVD_INDICATOR, CVD_INDICATOR_Provided, 1)); + param.append(AMP).append(createPair(CVD_VALUE, "123", 4)); + + try + { + log.fine("-> " + param.toString()); + Properties prop = getConnectPostProperties(urlString, param.toString()); + m_ok = prop != null; + // authCode=, authTime=1132330817, subErrorString=Card has expired: 04/04, errCode=91, clientVersion=1.1, status=E, subError=0, actionCode=CP, errString=Invalid Payment Information. Please verify request parameters. + // authCode=197705, authTime=1132336527, curAmount=0, avsInfo=B, clientVersion=1.1, status=SP, amount=200, cvdInfo=M, txnNumber=1000000 + if (m_ok) + { + String status = prop.getProperty(STATUS); + m_ok = status != null && status.equals("SP"); // Successful Purchase + String authCode = prop.getProperty(AUTH_CODE); + String authTime = prop.getProperty(AUTH_TIME); + // + String errCode = prop.getProperty(ERROR_CODE); + String errString = prop.getProperty(ERROR_STRING); + String subError = prop.getProperty(SUB_ERROR); + String subErrorString = prop.getProperty(SUB_ERROR_STRING); + String actionCode = prop.getProperty("actionCode"); + // + String authorisedAmount = prop.getProperty(CURRENT_AMOUNT); + String amount = prop.getProperty(AMOUNT); + String avsInfo = prop.getProperty(AVS_INFO); + String cvdInfo = prop.getProperty(CVD_INFO); + + log.fine("<- Status=" + status + ", AuthCode=" + authCode + ", Error=" + errString); + } + if (!m_ok) + log.warning("<- " + prop); + } + catch (Exception e) + { + log.log(Level.SEVERE, param.toString(), e); + m_ok = false; + } + return m_ok; + } // processCC + + /** + * Is Processed OK + * @return true of ok + */ + public boolean isProcessedOK () + { + return m_ok; + } // isProcessedOK + + + + /** + * Test + * @param args ifnored + */ + public static void main (String[] args) + { +/** +> Test Administration Server and Login +> ----------------------------------- +> The information you require to access the TEST administration server +> is (case sensitivity matters): +> +> Web Site: https://admin.test.firepay.com +> +> Test Account #2 +> Username: sparctwo001 +> User password: abcd1234 +> +> Test Payment Server URL +> ----------------------- +> To connect your web site to our TEST payment service, your technical +> people will use the following URL: +> +> https://realtime.test.firepay.com/servlet/DPServlet +> +> Test Cards +> ---------- +> Below are the cards you can use in the test environment. Transactions +> done with these cards will either be successful or fail depending on +> the amount provided with the transaction (see below). +> +> Visa: +> 4387751111011 +> 4387751111029 +> 4387751111111038 +> 4387751111111053 +> +> MasterCard: +> 5442981111111015 +> 5442981111111023 +> 5442981111111031 +> 5442981111111056 +> +> The following amounts will cause either approval or various declines +> with the cards mentioned above: +> Amount less than 20.00 = Approval +> 20.00 to 29.99 = (221, 1002) Reenter +> 30.00 to 39.99 = (221, 1003) Referral +> 40.00 to 49.99 = (221, 1004) PickUp +> 50.00 to 59.99 = (34, 1005) Decline +> 60.00 to 69.99 = (2) Timeout +> Amount greater than 69.99 = Approval +**/ + CLogMgt.initialize(true); + CLogMgt.setLevel(Level.ALL); + PP_Optimal pp = new PP_Optimal(); + pp.processCC(); + pp.isProcessedOK(); + + } // main + +} // PP_Optimal diff --git a/base/src/org/compiere/model/PP_PayFlowPro.java b/base/src/org/compiere/model/PP_PayFlowPro.java new file mode 100644 index 0000000000..cc43ec751e --- /dev/null +++ b/base/src/org/compiere/model/PP_PayFlowPro.java @@ -0,0 +1,209 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; +import com.Verisign.payment.*; + +/** + * Payment Processor for VeriSign PayFlow Pro. + * Needs Certification File (get from VeriSign) + * + * @author Jorg Janke + * @version $Id: PP_PayFlowPro.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public final class PP_PayFlowPro extends PaymentProcessor + implements Serializable +{ + /** + * PayFowPro Constructor + */ + public PP_PayFlowPro() + { + super(); + m_pp = new PFProAPI(); + String path = Ini.getAdempiereHome() + File.separator + "lib"; + // Needs Certification File (not dustributed) + File file = new File (path, "f73e89fd.0"); + if (!file.exists()) + log.log(Level.SEVERE, "No cert file " + file.getAbsolutePath()); + m_pp.SetCertPath (path); + } // PP_PayFowPro + + // Payment System */ + private PFProAPI m_pp = null; + private boolean m_ok = false; + + protected final static String RESULT_OK = "0"; + protected final static String RESULT_DECLINED = "12"; + protected final static String RESULT_INVALID_NO = "23"; + protected final static String RESULT_INVALID_EXP = "24"; + protected final static String RESULT_INSUFFICIENT_FUNDS = "50"; + protected final static String RESULT_TIMEOUT_PROCESSOR = "104"; + protected final static String RESULT_TIMEOUT_HOST = "109"; + + /** + * Get Version + * @return version + */ + public String getVersion() + { + return "PayFlowPro " + m_pp.Version(); + } // getVersion + + /** + * Process CreditCard (no date check) + * @return true if processed successfully + * @throws IllegalArgumentException + */ + public boolean processCC () throws IllegalArgumentException + { + log.fine(p_mpp.getHostAddress() + " " + p_mpp.getHostPort() + ", Timeout=" + getTimeout() + + "; Proxy=" + p_mpp.getProxyAddress() + " " + p_mpp.getProxyPort() + " " + p_mpp.getProxyLogon() + " " + p_mpp.getProxyPassword()); + // + StringBuffer param = new StringBuffer(); + // Transaction Type + if (p_mp.getTrxType().equals(MPayment.TRXTYPE_Sales)) + param.append("TRXTYPE=").append(p_mp.getTrxType()); + else + throw new IllegalArgumentException("PP_PayFlowPro TrxType not supported - " + p_mp.getTrxType()); + + // Mandatory Fields + param.append("&TENDER=C") // CreditCard + .append("&ACCT=").append(MPaymentValidate.checkNumeric(p_mp.getCreditCardNumber())); // CreditCard No + param.append("&EXPDATE="); // ExpNo + String month = String.valueOf(p_mp.getCreditCardExpMM()); + if (month.length() == 1) + param.append("0"); + param.append(month); + int expYY = p_mp.getCreditCardExpYY(); + if (expYY > 2000) + expYY -= 2000; + String year = String.valueOf(expYY); + if (year.length() == 1) + param.append("0"); + param.append(year); + param.append("&AMT=").append(p_mp.getPayAmt()); // Amount + + // Optional Control Fields - AuthCode & Orig ID + param.append(createPair("&AUTHCODE", p_mp.getVoiceAuthCode(), 6)); + param.append(createPair("&ORIGID", p_mp.getOrig_TrxID(), 12)); // PNREF - returned + // CVV + param.append(createPair("&CVV2", p_mp.getCreditCardVV(), 4)); + // param.append(createPair("&SWIPE", p_mp.getXXX(), 80)); // Track 1+2 + + // Address + param.append(createPair("&NAME", p_mp.getA_Name(), 30)); + param.append(createPair("&STREET", p_mp.getA_Street(), 30)); // Street + param.append(createPair("&ZIP", p_mp.getA_Zip(), 9)); // Zip 5-9 + // CITY 20, STATE 2, + param.append(createPair("&EMAIL", p_mp.getA_EMail(), 64)); // EMail + + // Amex Fields + // DESC, SHIPTOZIP, TAXAMT + // param.append(createPair("&DESC", p_mp.getXXX(), 23)); // Description + param.append(createPair("&SHIPTOZIP", p_mp.getA_Zip(), 6)); // Zip 6 + param.append(createPair("&TAXAMT", p_mp.getTaxAmt(), 10)); // Tax + + // Invoice No + param.append(createPair("&INVNUM", p_mp.getC_Invoice_ID(), 9)); + + // COMMENT1/2 + param.append(createPair("&COMMENT1", p_mp.getC_Payment_ID(), 128)); // Comment + param.append(createPair("&COMMENT2", p_mp.getC_BPartner_ID(), 128)); // Comment2 + + return process(param.toString()); + } // processCC + + /** + * Process Transaction + * @param parameter Command String + * @return true if processed successfully + */ + public boolean process (String parameter) + { + long start = System.currentTimeMillis(); + StringBuffer param = new StringBuffer(parameter); + // Usr/Pwd + param + .append("&PARTNER=").append(p_mpp.getPartnerID()) + .append("&VENDOR=").append(p_mpp.getVendorID()) + .append("&USER=").append(p_mpp.getUserID()) + .append("&PWD=").append(p_mpp.getPassword()); + log.fine("-> " + param.toString()); + + // Call the PayFlowPro client. + int rc = m_pp.CreateContext (p_mpp.getHostAddress(), p_mpp.getHostPort(), getTimeout(), + p_mpp.getProxyAddress(), p_mpp.getProxyPort(), p_mpp.getProxyLogon(), p_mpp.getProxyPassword()); + String response = m_pp.SubmitTransaction(param.toString()); + m_pp.DestroyContext(); + // + long ms = System.currentTimeMillis() - start; + log.fine("<- " + ms + "ms - " + rc + " - " + response); + p_mp.setR_Result(""); + p_mp.setR_Info(response); // complete info + + // RESULT=1&PNREF=PN0001480030&RESPMSG=Invalid User Authentication + // RESULT=0&PNREF=P60501480167&RESPMSG=Approved&AUTHCODE=010101&AVSADDR=X&AVSZIP=X + // RESULT=-31&RESPMSG=The certificate chain did not validate, no local certificate found, javax.net.ssl.SSLException: Cert Path = C:\Adempiere\lib, Working Directory = C:\Adempiere\adempiere-all2\client\temp + StringTokenizer st = new StringTokenizer(response, "&", false); + while (st.hasMoreTokens()) + { + String token = st.nextToken(); + int pos = token.indexOf("="); + String name = token.substring(0, pos); + String value = token.substring(pos+1); + // + if (name.equals("RESULT")) + { + p_mp.setR_Result (value); + m_ok = RESULT_OK.equals(value); + } + else if (name.equals("PNREF")) + p_mp.setR_PnRef(value); + else if (name.equals("RESPMSG")) + p_mp.setR_RespMsg(value); + else if (name.equals("AUTHCODE")) + p_mp.setR_AuthCode(value); + else if (name.equals("AVSADDR")) + p_mp.setR_AvsAddr(value); + else if (name.equals("AVSZIP")) + p_mp.setR_AvsZip(value); + else if (name.equals("IAVS")) // N=YSA, Y=International + ; + else if (name.equals("CVV2MATCH")) // Y/N X=not supported + ; + else + log.log(Level.SEVERE, "Response unknown = " + token); + } + // Probelms with rc (e.g. 0 with Result=24) + return m_ok; + } // process + + /** + * Payment is procesed successfully + * @return true if OK + */ + public boolean isProcessedOK() + { + return m_ok; + } // isProcessedOK + +} // PP_PayFowPro diff --git a/base/src/org/compiere/model/PP_PayPal.java b/base/src/org/compiere/model/PP_PayPal.java new file mode 100644 index 0000000000..eb2ec86a4b --- /dev/null +++ b/base/src/org/compiere/model/PP_PayPal.java @@ -0,0 +1,208 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.util.logging.*; +import org.compiere.util.*; +/** +import com.paypal.sdk.exceptions.*; +import com.paypal.sdk.profiles.*; +import com.paypal.sdk.services.*; +import com.paypal.soap.api.*; +**/ + +/** + * PayPal Payment Processor Services Interface + * + * @author Jorg Janke + * @version $Id: PP_PayPal.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class PP_PayPal extends PaymentProcessor + implements Serializable +{ + /** Status */ + private boolean m_ok = false; + /** PayPal Caller Service */ +// private CallerServices m_caller; + + + /** + * Process CC + * @return true if processed + * @throws IllegalArgumentException + */ + public boolean processCC () + throws IllegalArgumentException + { + return m_ok; + } // processCC + + /** + * Is Processed OK + * @return true if ok + */ + public boolean isProcessedOK () + { + return m_ok; + } // isProcessedOK + +/** + public void initialize() throws PayPalException + { + APIProfile profile = ProfileFactory.createAPIProfile(); + profile.setAPIUsername("sdk-seller_api1.sdk.com"); + profile.setAPIPassword("12345678"); + profile.setCertificateFile("../Cert/sdk-seller.p12"); + profile.setPrivateKeyPassword("password"); + profile.setEnvironment("sandbox"); + // + m_caller = new CallerServices(); + m_caller.setAPIProfile(profile); + } // initialize + + + public void transactionSearch() throws PayPalException + { + System.out.println("\n########## Transaction Search ##########\n"); + TransactionSearchRequestType request = new TransactionSearchRequestType(); + Calendar calendar = Calendar.getInstance(); + calendar.set(2005,2,25); + request.setStartDate(calendar); + request.setTransactionID("4KT33454GG2130806"); + + TransactionSearchResponseType response = + (TransactionSearchResponseType) caller.call("TransactionSearch", request); + System.out.println("Operation Ack: " + response.getAck()); + System.out.println("---------- Results ----------"); + + // Check to see if any transactions were found + PaymentTransactionSearchResultType[] ts = response.getPaymentTransactions(); + if (ts != null) + { + System.out.println("Found " + ts.length + " records"); + + // Display the results of the first transaction returned + for (int i = 0; i < ts.length; i++) + { + System.out.println("\nTransaction ID: " + ts[i].getTransactionID()); + System.out.println("Payer Name: " + ts[i].getPayerDisplayName()); + System.out.println("Gross Amount: " + ts[i].getGrossAmount().getCurrencyID() + " " + ts[i].getGrossAmount().get_value()); + System.out.println("Fee Amount: " + ts[i].getFeeAmount().getCurrencyID() + " " + ts[i].getFeeAmount().get_value()); + System.out.println("Net Amount: " + ts[i].getNetAmount().getCurrencyID() + " " + ts[i].getNetAmount().get_value()); + } + } + else + { + System.out.println("Found 0 transaction"); + } + } // transactionSearch + + + public void getTransactionDetails() throws PayPalException + { + System.out.println("\n########## Get Transaction Details ##########\n"); + GetTransactionDetailsRequestType request = new GetTransactionDetailsRequestType(); + request.setTransactionID("7J110007888511720"); + + GetTransactionDetailsResponseType response = (GetTransactionDetailsResponseType) caller.call("GetTransactionDetails", request); + System.out.println("Operation Ack: " + response.getAck()); + System.out.println("---------- Results ----------"); + + PaymentTransactionType ts = response.getPaymentTransactionDetails(); + System.out.println("\nTransaction ID: " + ts.getPaymentInfo().getTransactionID()); + System.out.println("Payer Name: " + ts.getPayerInfo().getPayer()); + System.out.println("Receiver Name: " + ts.getReceiverInfo().getReceiver()); + System.out.println("Gross Amount: " + ts.getPaymentInfo().getGrossAmount().getCurrencyID() + " " + ts.getPaymentInfo().getGrossAmount().get_value()); + } // getTransactionDetails + + + public void directPayment() throws PayPalException + { + System.out.println("\n########## Do Direct Payment ##########\n"); + + DoDirectPaymentRequestType request = new DoDirectPaymentRequestType(); + DoDirectPaymentRequestDetailsType details = new DoDirectPaymentRequestDetailsType(); + + CreditCardDetailsType creditCard = new CreditCardDetailsType(); + creditCard.setCreditCardNumber("4721930402892796"); + creditCard.setCreditCardType(CreditCardTypeType.Visa); + creditCard.setCVV2("000"); + creditCard.setExpMonth(11); + creditCard.setExpYear(2007); + + PayerInfoType cardOwner = new PayerInfoType(); + cardOwner.setPayerCountry(CountryCodeType.US); + + AddressType address = new AddressType(); + address.setPostalCode("95101"); + address.setStateOrProvince("CA"); + address.setStreet1("123 Main St"); + address.setCountryName("US"); + address.setCountry(CountryCodeType.US); + address.setCityName("San Jose"); + cardOwner.setAddress(address); + + PersonNameType payerName = new PersonNameType(); + payerName.setFirstName("SDK"); + payerName.setLastName("Buyer"); + cardOwner.setPayerName(payerName); + + creditCard.setCardOwner(cardOwner); + details.setCreditCard(creditCard); + + details.setIPAddress("12.36.5.78"); + details.setMerchantSessionId("456977"); + details.setPaymentAction(PaymentActionCodeType.Sale); + + PaymentDetailsType payment = new PaymentDetailsType(); + + BasicAmountType orderTotal = new BasicAmountType(); + orderTotal.setCurrencyID(CurrencyCodeType.USD); + orderTotal.set_value("20.00"); + payment.setOrderTotal(orderTotal); + + details.setPaymentDetails(payment); + request.setDoDirectPaymentRequestDetails(details); + + DoDirectPaymentResponseType response = (DoDirectPaymentResponseType) caller.call("DoDirectPayment", request); + + System.out.println("Operation Ack: " + response.getAck()); + System.out.println("---------- Results ----------"); + System.out.println("\nTransaction ID: " + response.getTransactionID()); + System.out.println("CVV2: " + response.getCVV2Code()); + System.out.println("AVS: " + response.getAVSCode()); + System.out.println("Gross Amount: " + response.getAmount().getCurrencyID() + + " " + response.getAmount().get_value()); + } // directPayment +**/ + + /** + * Test + * @param args ifnored + */ + public static void main (String[] args) + { + CLogMgt.initialize(true); + CLogMgt.setLevel(Level.ALL); + PP_PayPal pp = new PP_PayPal(); + pp.processCC(); + pp.isProcessedOK(); + + } // main + +} // PP_PayPal diff --git a/base/src/org/compiere/model/PaymentProcessor.java b/base/src/org/compiere/model/PaymentProcessor.java new file mode 100644 index 0000000000..80307780ef --- /dev/null +++ b/base/src/org/compiere/model/PaymentProcessor.java @@ -0,0 +1,309 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.*; +import java.math.*; +import java.util.*; +import java.util.logging.*; +import java.net.*; +import javax.net.ssl.*; + +import org.compiere.util.*; + +/** + * Payment Processor Abstract Class + * + * @author Jorg Janke + * @version $Id: PaymentProcessor.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public abstract class PaymentProcessor +{ + /** + * Public Constructor + */ + public PaymentProcessor() + { + } // PaymentProcessor + + /** Logger */ + protected CLogger log = CLogger.getCLogger (getClass()); + /** Payment Processor Logger */ + static private CLogger s_log = CLogger.getCLogger (PaymentProcessor.class); + /** Encoding (ISO-8859-1 - UTF-8) */ + public static final String ENCODING = "UTF-8"; + /** Encode Parameters */ + private boolean m_encoded = false; + /** Ampersand */ + public static final char AMP = '&'; + /** Equals */ + public static final char EQ = '='; + + /** + * Factory + * @param mpp payment processor model + * @param mp payment model + * @return initialized PaymentProcessor or null + */ + public static PaymentProcessor create (MPaymentProcessor mpp, MPayment mp) + { + s_log.info("create for " + mpp); + String className = mpp.getPayProcessorClass(); + if (className == null || className.length() == 0) + { + s_log.log(Level.SEVERE, "No PaymentProcessor class name in " + mpp); + return null; + } + // + PaymentProcessor myProcessor = null; + try + { + Class ppClass = Class.forName(className); + if (ppClass != null) + myProcessor = (PaymentProcessor)ppClass.newInstance(); + } + catch (Error e1) // NoClassDefFound + { + s_log.log(Level.SEVERE, className + " - Error=" + e1.getMessage()); + return null; + } + catch (Exception e2) + { + s_log.log(Level.SEVERE, className, e2); + return null; + } + if (myProcessor == null) + { + s_log.log(Level.SEVERE, "no class"); + return null; + } + + // Initialize + myProcessor.p_mpp = mpp; + myProcessor.p_mp = mp; + // + return myProcessor; + } // create + + /*************************************************************************/ + + protected MPaymentProcessor p_mpp = null; + protected MPayment p_mp = null; + // + private int m_timeout = 30; + + /*************************************************************************/ + + /** + * Process CreditCard (no date check) + * @return true if processed successfully + * @throws IllegalArgumentException + */ + public abstract boolean processCC () throws IllegalArgumentException; + + /** + * Payment is procesed successfully + * @return true if OK + */ + public abstract boolean isProcessedOK(); + + + /************************************************************************** + * Set Timeout + * @param newTimeout timeout + */ + public void setTimeout(int newTimeout) + { + m_timeout = newTimeout; + } + /** + * Get Timeout + * @return timeout + */ + public int getTimeout() + { + return m_timeout; + } + + + /************************************************************************** + * Check for delimiter fields &= and add length of not encoded + * @param name name + * @param value value + * @param maxLength maximum length + * @return name[5]=value or name=value + */ + protected String createPair(String name, BigDecimal value, int maxLength) + { + if (value == null) + return createPair (name, "0", maxLength); + else + { + if (value.scale() < 2) + value = value.setScale(2, BigDecimal.ROUND_HALF_UP); + return createPair (name, String.valueOf(value), maxLength); + } + } // createPair + + /** + * Check for delimiter fields &= and add length of not encoded + * @param name name + * @param value value + * @param maxLength maximum length + * @return name[5]=value or name=value + */ + protected String createPair(String name, int value, int maxLength) + { + if (value == 0) + return ""; + else + return createPair (name, String.valueOf(value), maxLength); + } // createPair + + /** + * Check for delimiter fields &= and add length of not encoded + * @param name name + * @param value value + * @param maxLength maximum length + * @return name[5]=value or name=value + */ + protected String createPair(String name, String value, int maxLength) + { + // Nothing to say + if (name == null || name.length() == 0 + || value == null || value.length() == 0) + return ""; + + if (value.length() > maxLength) + value = value.substring(0, maxLength); + + StringBuffer retValue = new StringBuffer(name); + if (m_encoded) + try + { + value = URLEncoder.encode(value, ENCODING); + } + catch (UnsupportedEncodingException e) + { + log.log(Level.SEVERE, value + " - " + e.toString()); + } + else if (value.indexOf(AMP) != -1 || value.indexOf(EQ) != -1) + retValue.append("[").append(value.length()).append("]"); + // + retValue.append(EQ); + retValue.append(value); + return retValue.toString(); + } // createPair + + /** + * Set Encoded + * @param doEncode true if encode + */ + public void setEncoded (boolean doEncode) + { + m_encoded = doEncode; + } // setEncode + /** + * Is Encoded + * @return true if encoded + */ + public boolean isEncoded() + { + return m_encoded; + } // setEncode + + /** + * Get Connect Post Properties + * @param urlString POST url string + * @param parameter parameter + * @return result as properties + */ + protected Properties getConnectPostProperties (String urlString, String parameter) + { + long start = System.currentTimeMillis(); + String result = connectPost(urlString, parameter); + if (result == null) + return null; + Properties prop = new Properties(); + try + { + String info = URLDecoder.decode(result, ENCODING); + StringTokenizer st = new StringTokenizer(info, "&"); // AMP + while (st.hasMoreTokens()) + { + String token = st.nextToken(); + int index = token.indexOf('='); + if (index == -1) + prop.put(token, ""); + else + { + String key = token.substring(0, index); + String value = token.substring(index+1); + prop.put(key, value); + } + } + } + catch (Exception e) + { + log.log(Level.SEVERE, result, e); + } + long ms = System.currentTimeMillis() - start; + log.fine(ms + "ms - " + prop.toString()); + return prop; + } // connectPost + + /** + * Connect via Post + * @param urlString url destination (assuming https) + * @param parameter parameter + * @return response or null if failure + */ + protected String connectPost (String urlString, String parameter) + { + String response = null; + try + { + // open secure connection + URL url = new URL(urlString); + HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + // URLConnection connection = url.openConnection(); + connection.setDoOutput(true); + connection.setUseCaches(false); + connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); + log.fine(connection.getURL().toString()); + + // POST the parameter + DataOutputStream out = new DataOutputStream (connection.getOutputStream()); + out.write(parameter.getBytes()); + out.flush(); + out.close(); + + // process and read the gateway response + BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); + response = in.readLine(); + in.close(); // no more data + log.finest(response); + } + catch (Exception e) + { + log.log(Level.SEVERE, urlString, e); + } + // + return response; + } // connectPost + +} // PaymentProcessor diff --git a/base/src/org/compiere/model/ProductCost.java b/base/src/org/compiere/model/ProductCost.java new file mode 100644 index 0000000000..c637701158 --- /dev/null +++ b/base/src/org/compiere/model/ProductCost.java @@ -0,0 +1,504 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Product Cost Model. + * Summarizes Info in MCost + * + * @author Jorg Janke + * @version $Id: ProductCost.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + */ +public class ProductCost +{ + /** + * Constructor + * @param ctx context + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID asi + * @param trxName trx + */ + public ProductCost (Properties ctx, int M_Product_ID, int M_AttributeSetInstance_ID, + String trxName) + { + m_M_Product_ID = M_Product_ID; + if (m_M_Product_ID != 0) + m_product = MProduct.get (ctx, M_Product_ID); + m_M_AttributeSetInstance_ID = M_AttributeSetInstance_ID; + m_trxName = trxName; + } // ProductCost + + /** The ID */ + private int m_M_Product_ID = 0; + /** ASI */ + private int m_M_AttributeSetInstance_ID = 0; + /** The Product */ + private MProduct m_product = null; + /** Transaction */ + private String m_trxName = null; + + private int m_C_UOM_ID = 0; + private BigDecimal m_qty = Env.ZERO; + + /** Logger */ + private static CLogger log = CLogger.getCLogger (ProductCost.class); + + /** + * Get Product + * @return Product might be null + */ + public MProduct getProduct() + { + return m_product; + } // getProduct + + /** + * Is this a Service + * @return true if service + */ + public boolean isService() + { + if (m_product != null) + return m_product.isService(); + return false; + } // isService + + /** + * Set Quantity in Storage UOM + * @param qty quantity + */ + public void setQty (BigDecimal qty) + { + m_qty = qty; + } // setQty + + /** + * Set Quantity in UOM + * @param qty quantity + * @param C_UOM_ID UOM + */ + public void setQty (BigDecimal qty, int C_UOM_ID) + { + m_qty = MUOMConversion.convert (C_UOM_ID, m_C_UOM_ID, qty, true); // StdPrecision + if (qty != null && m_qty == null) // conversion error + { + log.severe ("Conversion error - set to " + qty); + m_qty = qty; + } + else + m_C_UOM_ID = C_UOM_ID; + } // setQty + + + + + /** Product Revenue Acct */ + public static final int ACCTTYPE_P_Revenue = 1; + /** Product Expense Acct */ + public static final int ACCTTYPE_P_Expense = 2; + /** Product Asset Acct */ + public static final int ACCTTYPE_P_Asset = 3; + /** Product COGS Acct */ + public static final int ACCTTYPE_P_Cogs = 4; + /** Purchase Price Variance */ + public static final int ACCTTYPE_P_PPV = 5; + /** Invoice Price Variance */ + public static final int ACCTTYPE_P_IPV = 6; + /** Trade Discount Revenue */ + public static final int ACCTTYPE_P_TDiscountRec = 7; + /** Trade Discount Costs */ + public static final int ACCTTYPE_P_TDiscountGrant = 8; + /** Cost Adjustment */ + public static final int ACCTTYPE_P_CostAdjustment = 9; + /** Inventory Clearing */ + public static final int ACCTTYPE_P_InventoryClearing = 10; + + /** + * Line Account from Product + * + * @param AcctType see ACCTTYPE_* (1..8) + * @param as Accounting Schema + * @return Requested Product Account + */ + public MAccount getAccount(int AcctType, MAcctSchema as) + { + if (AcctType < 1 || AcctType > 10) + return null; + + // No Product - get Default from Product Category + if (m_M_Product_ID == 0) + return getAccountDefault(AcctType, as); + + String sql = "SELECT P_Revenue_Acct, P_Expense_Acct, P_Asset_Acct, P_Cogs_Acct, " // 1..4 + + "P_PurchasePriceVariance_Acct, P_InvoicePriceVariance_Acct, " // 5..6 + + "P_TradeDiscountRec_Acct, P_TradeDiscountGrant_Acct," // 7..8 + + "P_CostAdjustment_Acct, P_InventoryClearing_Acct " // 9..10 + + "FROM M_Product_Acct " + + "WHERE M_Product_ID=? AND C_AcctSchema_ID=?"; + // + int validCombination_ID = 0; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, m_M_Product_ID); + pstmt.setInt(2, as.getC_AcctSchema_ID()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + validCombination_ID = rs.getInt(AcctType); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + if (validCombination_ID == 0) + return null; + return MAccount.get(as.getCtx(), validCombination_ID); + } // getAccount + + /** + * Account from Default Product Category + * + * @param AcctType see ACCTTYPE_* (1..8) + * @param as accounting schema + * @return Requested Product Account + */ + public MAccount getAccountDefault (int AcctType, MAcctSchema as) + { + if (AcctType < 1 || AcctType > 10) + return null; + + String sql = "SELECT P_Revenue_Acct, P_Expense_Acct, P_Asset_Acct, P_Cogs_Acct, " + + "P_PurchasePriceVariance_Acct, P_InvoicePriceVariance_Acct, " + + "P_TradeDiscountRec_Acct, P_TradeDiscountGrant_Acct, " + + "P_CostAdjustment_Acct, P_InventoryClearing_Acct " + + "FROM M_Product_Category pc, M_Product_Category_Acct pca " + + "WHERE pc.M_Product_Category_ID=pca.M_Product_Category_ID" + + " AND pca.C_AcctSchema_ID=? " + + "ORDER BY pc.IsDefault DESC, pc.Created"; + // + int validCombination_ID = 0; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, as.getC_AcctSchema_ID()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + validCombination_ID = rs.getInt(AcctType); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + if (validCombination_ID == 0) + return null; + return MAccount.get(as.getCtx(), validCombination_ID); + } // getAccountDefault + + + /************************************************************************** + * Get Total Costs (amt*qty) in Accounting Schema Currency + * @param as accounting schema + * @param AD_Org_ID trx org + * @param costingMethod if null uses Accounting Schema - AcctSchema.COSTINGMETHOD_* + * @param C_OrderLine_ID optional order line + * @param zeroCostsOK zero/no costs are OK + * @return cost or null, if qty or costs cannot be determined + */ + public BigDecimal getProductCosts (MAcctSchema as, int AD_Org_ID, + String costingMethod, int C_OrderLine_ID, boolean zeroCostsOK) + { + if (m_qty == null) + { + log.fine("No Qty"); + return null; + } + /** Old Costing + MClient client = MClient.get(as.getCtx(), as.getAD_Client_ID()); + if (!client.isUseBetaFunctions()) + { + BigDecimal itemCost = getProductItemCostOld(as, costingMethod); + BigDecimal cost = m_qty.multiply(itemCost); + cost = cost.setScale(as.getCostingPrecision(), BigDecimal.ROUND_HALF_UP); + log.fine("Qty(" + m_qty + ") * Cost(" + itemCost + ") = " + cost); + return cost; + } + **/ + + // No Product + if (m_product == null) + { + log.fine("No Product"); + return null; + } + // + BigDecimal cost = MCost.getCurrentCost (m_product, m_M_AttributeSetInstance_ID, + as, AD_Org_ID, costingMethod, m_qty, C_OrderLine_ID, zeroCostsOK, m_trxName); + if (cost == null) + { + log.fine("No Costs"); + return null; + } + return cost; + } // getProductCosts + + + /** + * Get Product Costs per UOM for Accounting Schema in Accounting Schema Currency. + * - if costType defined - cost + * - else CurrentCosts + * @param as accounting schema + * @param costType - if null uses Accounting Schema Costs - see AcctSchema.COSTING_* + * @return product costs + */ + private BigDecimal getProductItemCostOld (MAcctSchema as, String costType) + { + BigDecimal current = null; + BigDecimal cost = null; + String cm = as.getCostingMethod(); + StringBuffer sql = new StringBuffer("SELECT CurrentCostPrice,"); // 1 + // + if ((costType == null && MAcctSchema.COSTINGMETHOD_AveragePO.equals(cm)) + || MAcctSchema.COSTINGMETHOD_AveragePO.equals(costType)) + sql.append("COSTAVERAGE"); // 2 + // else if (AcctSchema.COSTING_FIFO.equals(cm)) + // sql.append("COSTFIFO"); + // else if (AcctSchema.COSTING_LIFO.equals(cm)) + // sql.append("COSTLIFO"); + else if ((costType == null && MAcctSchema.COSTINGMETHOD_LastPOPrice.equals(cm)) + || MAcctSchema.COSTINGMETHOD_LastPOPrice.equals(costType)) + sql.append("PRICELASTPO"); + else // AcctSchema.COSTING_STANDARD + sql.append("COSTSTANDARD"); + sql.append(" FROM M_Product_Costing WHERE M_Product_ID=? AND C_AcctSchema_ID=?"); + + try + { + PreparedStatement pstmt = DB.prepareStatement(sql.toString(), null); + pstmt.setInt(1, m_M_Product_ID); + pstmt.setInt(2, as.getC_AcctSchema_ID()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + current = rs.getBigDecimal(1); + cost = rs.getBigDecimal(2); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + + // Return Costs + if (costType != null && cost != null && !cost.equals(Env.ZERO)) + { + log.fine("Costs=" + cost); + return cost; + } + else if (current != null && !current.equals(Env.ZERO)) + { + log.fine("Current=" + current); + return current; + } + + // Create/Update Cost Record + boolean create = (cost == null && current == null); + return updateCostsOld (as, create); + } // getProductCostOld + + /** + * Update/Create initial Cost Record. + * Check first for Purchase Price List, + * then Product Purchase Costs + * and then Price List + * @param as accounting schema + * @param create create record + * @return costs + */ + private BigDecimal updateCostsOld (MAcctSchema as, boolean create) + { + // Create Zero Record + if (create) + { + StringBuffer sql = new StringBuffer ("INSERT INTO M_Product_Costing " + + "(M_Product_ID,C_AcctSchema_ID," + + " AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy," + + " CurrentCostPrice,CostStandard,FutureCostPrice," + + " CostStandardPOQty,CostStandardPOAmt,CostStandardCumQty,CostStandardCumAmt," + + " CostAverage,CostAverageCumQty,CostAverageCumAmt," + + " PriceLastPO,PriceLastInv, TotalInvQty,TotalInvAmt) " + + "VALUES ("); + sql.append(m_M_Product_ID).append(",").append(as.getC_AcctSchema_ID()).append(",") + .append(as.getAD_Client_ID()).append(",").append(as.getAD_Org_ID()).append(",") + .append("'Y',SysDate,0,SysDate,0, 0,0,0, 0,0,0,0, 0,0,0, 0,0, 0,0)"); + int no = DB.executeUpdate(sql.toString(), m_trxName); + if (no == 1) + log.fine("CostingCreated"); + } + + // Try to find non ZERO Price + String costSource = "PriceList-PO"; + BigDecimal costs = getPriceList (as, true); + if (costs == null || costs.equals(Env.ZERO)) + { + costSource = "PO Cost"; + costs = getPOCost(as); + } + if (costs == null || costs.equals(Env.ZERO)) + { + costSource = "PriceList"; + costs = getPriceList (as, false); + } + + // if not found use $1 (to be able to do material transactions) + if (costs == null || costs.equals(Env.ZERO)) + { + costSource = "Not Found"; + costs = new BigDecimal("1"); + } + + // update current costs + StringBuffer sql = new StringBuffer ("UPDATE M_Product_Costing "); + sql.append("SET CurrentCostPrice=").append(costs) + .append(" WHERE M_Product_ID=").append(m_M_Product_ID) + .append(" AND C_AcctSchema_ID=").append(as.getC_AcctSchema_ID()); + int no = DB.executeUpdate(sql.toString(), m_trxName); + if (no == 1) + log.fine(costSource + " - " + costs); + return costs; + } // createCosts + + /** + * Get PO Price from PriceList - and convert it to AcctSchema Currency + * @param as accounting schema + * @param onlyPOPriceList use only PO price list + * @return po price + */ + private BigDecimal getPriceList (MAcctSchema as, boolean onlyPOPriceList) + { + StringBuffer sql = new StringBuffer ( + "SELECT pl.C_Currency_ID, pp.PriceList, pp.PriceStd, pp.PriceLimit " + + "FROM M_PriceList pl, M_PriceList_Version plv, M_ProductPrice pp " + + "WHERE pl.M_PriceList_ID = plv.M_PriceList_ID" + + " AND plv.M_PriceList_Version_ID = pp.M_PriceList_Version_ID" + + " AND pp.M_Product_ID=?"); + if (onlyPOPriceList) + sql.append(" AND pl.IsSOPriceList='N'"); + sql.append(" ORDER BY pl.IsSOPriceList ASC, plv.ValidFrom DESC"); + int C_Currency_ID = 0; + BigDecimal PriceList = null; + BigDecimal PriceStd = null; + BigDecimal PriceLimit = null; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql.toString(), null); + pstmt.setInt(1, m_M_Product_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + C_Currency_ID = rs.getInt(1); + PriceList = rs.getBigDecimal(2); + PriceStd = rs.getBigDecimal(3); + PriceLimit = rs.getBigDecimal(4); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + // nothing found + if (C_Currency_ID == 0) + return null; + + BigDecimal price = PriceLimit; // best bet + if (price == null || price.equals(Env.ZERO)) + price = PriceStd; + if (price == null || price.equals(Env.ZERO)) + price = PriceList; + // Convert + if (price != null && !price.equals(Env.ZERO)) + price = MConversionRate.convert (as.getCtx(), + price, C_Currency_ID, as.getC_Currency_ID(), + as.getAD_Client_ID(), 0); + return price; + } // getPOPrice + + /** + * Get PO Cost from Purchase Info - and convert it to AcctSchema Currency + * @param as accounting schema + * @return po cost + */ + private BigDecimal getPOCost (MAcctSchema as) + { + String sql = "SELECT C_Currency_ID, PriceList,PricePO,PriceLastPO " + + "FROM M_Product_PO WHERE M_Product_ID=? " + + "ORDER BY IsCurrentVendor DESC"; + + int C_Currency_ID = 0; + BigDecimal PriceList = null; + BigDecimal PricePO = null; + BigDecimal PriceLastPO = null; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, m_M_Product_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + C_Currency_ID = rs.getInt(1); + PriceList = rs.getBigDecimal(2); + PricePO = rs.getBigDecimal(3); + PriceLastPO = rs.getBigDecimal(4); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + // nothing found + if (C_Currency_ID == 0) + return null; + + BigDecimal cost = PriceLastPO; // best bet + if (cost == null || cost.equals(Env.ZERO)) + cost = PricePO; + if (cost == null || cost.equals(Env.ZERO)) + cost = PriceList; + // Convert - standard precision!! - should be costing precision + if (cost != null && !cost.equals(Env.ZERO)) + cost = MConversionRate.convert (as.getCtx(), + cost, C_Currency_ID, as.getC_Currency_ID(), as.getAD_Client_ID(), as.getAD_Org_ID()); + return cost; + } // getPOCost + +} // ProductCost diff --git a/base/src/org/compiere/model/ScheduleUtil.java b/base/src/org/compiere/model/ScheduleUtil.java new file mode 100644 index 0000000000..abb908e802 --- /dev/null +++ b/base/src/org/compiere/model/ScheduleUtil.java @@ -0,0 +1,868 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Scheduling Utilities. + * + * @author Jorg Janke + * @version $Id: ScheduleUtil.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class ScheduleUtil +{ + /** + * Constructor + * @param ctx context + */ + public ScheduleUtil (Properties ctx) + { + m_ctx = ctx; + } // MSchedule + + private Properties m_ctx; + private int m_S_Resource_ID; + private boolean m_isAvailable = true; + private boolean m_isSingleAssignment = true; + private int m_S_ResourceType_ID = 0; + private int m_C_UOM_ID = 0; + + private Timestamp m_startDate = null; + private Timestamp m_endDate = null; + + /** Resource Type Name */ + private String m_typeName = null; + /** Resource Type Start Time */ + private Timestamp m_slotStartTime = null; + /** Resource Type End Time */ + private Timestamp m_slotEndTime = null; + + /** Time Slots */ + private MAssignmentSlot[] m_timeSlots = null; + + /** Begin Timestamp 1/1/1970 */ + public static final Timestamp EARLIEST = new Timestamp(new GregorianCalendar(1970,1,1).getTimeInMillis()); + /** End Timestamp 12/31/2070 */ + public static final Timestamp LATEST = new Timestamp(new GregorianCalendar(2070,12,31).getTimeInMillis()); + + /** Logger */ + private static CLogger log = CLogger.getCLogger(ScheduleUtil.class); + + + /************************************************************************** + * Get Assignments for timeframe. + *
+	 * 		- Resource is Active and Available
+	 * 		- Resource UnAvailability
+	 * 		- NonBusinessDay
+	 * 		- ResourceType Available
+	 *  
+ * @param S_Resource_ID resource + * @param start_Date start date + * @param end_Date optional end date, need to provide qty to calculate it + * @param qty optional qty in ResourceType UOM - ignored, if end date is not null + * @param getAll if true return all errors + * @param trxName transaction + * @return Array of existing Assigments or null - if free + */ + @SuppressWarnings("unchecked") + public MAssignmentSlot[] getAssignmentSlots (int S_Resource_ID, + Timestamp start_Date, Timestamp end_Date, + BigDecimal qty, boolean getAll, String trxName) + { + log.config(start_Date.toString()); + if (m_S_Resource_ID != S_Resource_ID) + getBaseInfo (S_Resource_ID); + // + ArrayList list = new ArrayList(); + MAssignmentSlot ma = null; + + if (!m_isAvailable) + { + ma = new MAssignmentSlot (EARLIEST, LATEST, + Msg.getMsg (m_ctx, "ResourceNotAvailable"), "", MAssignmentSlot.STATUS_NotAvailable); + if (!getAll) + return new MAssignmentSlot[] {ma}; + list.add(ma); + } + + m_startDate = start_Date; + m_endDate = end_Date; + if (m_endDate == null) + m_endDate = MUOMConversion.getEndDate(m_ctx, m_startDate, m_C_UOM_ID, qty); + log.fine( "- EndDate=" + m_endDate); + + + // Resource Unavailability ------------------------------------------- + // log.fine( "- Unavailability -"); + String sql = "SELECT Description, DateFrom, DateTo " + + "FROM S_ResourceUnavailable " + + "WHERE S_Resource_ID=?" // #1 + + " AND DateTo >= ?" // #2 start + + " AND DateFrom <= ?" // #3 end + + " AND IsActive='Y'"; + try + { + // log.fine( sql, "ID=" + S_Resource_ID + ", Start=" + m_startDate + ", End=" + m_endDate); + PreparedStatement pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, m_S_Resource_ID); + pstmt.setTimestamp(2, m_startDate); + pstmt.setTimestamp(3, m_endDate); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + ma = new MAssignmentSlot (TimeUtil.getDay(rs.getTimestamp(2)), + TimeUtil.getNextDay(rs.getTimestamp(3)), // user entered date need to convert to not including end time + Msg.getMsg (m_ctx, "ResourceUnAvailable"), rs.getString(1), + MAssignmentSlot.STATUS_UnAvailable); + // log.fine( "- Unavailable", ma); + if (getAll) + createDaySlot (list, ma); + else + list.add(ma); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + ma = new MAssignmentSlot (EARLIEST, LATEST, + Msg.getMsg (m_ctx, "ResourceUnAvailable"), e.toString(), + MAssignmentSlot.STATUS_UnAvailable); + } + if (ma != null && !getAll) + return new MAssignmentSlot[] {ma}; + + + // NonBusinessDay ---------------------------------------------------- + // log.fine( "- NonBusinessDay -"); + // "WHERE TRUNC(Date1) BETWEEN TRUNC(?) AND TRUNC(?)" causes + // ORA-00932: inconsistent datatypes: expected NUMBER got TIMESTAMP + sql = MRole.getDefault(m_ctx, false).addAccessSQL ( + "SELECT Name, Date1 FROM C_NonBusinessDay " + + "WHERE TRUNC(Date1) BETWEEN ? AND ?", + "C_NonBusinessDay", false, false); // not qualified - RO + try + { + Timestamp startDay = TimeUtil.getDay(m_startDate); + Timestamp endDay = TimeUtil.getDay(m_endDate); + // log.fine( sql, "Start=" + startDay + ", End=" + endDay); + PreparedStatement pstmt = DB.prepareStatement(sql, trxName); + pstmt.setTimestamp(1, startDay); + pstmt.setTimestamp(2, endDay); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + ma = new MAssignmentSlot (TimeUtil.getDay(rs.getTimestamp(2)), + TimeUtil.getNextDay(rs.getTimestamp(2)), // user entered date need to convert to not including end time + Msg.getMsg(m_ctx, "NonBusinessDay"), rs.getString(1), + MAssignmentSlot.STATUS_NonBusinessDay); + log.finer("- NonBusinessDay " + ma); + list.add(ma); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + ma = new MAssignmentSlot (EARLIEST, LATEST, + Msg.getMsg(m_ctx, "NonBusinessDay"), e.toString(), + MAssignmentSlot.STATUS_NonBusinessDay); + } + if (ma != null && !getAll) + return new MAssignmentSlot[] {ma}; + + + // ResourceType Available -------------------------------------------- + // log.fine( "- ResourceTypeAvailability -"); + sql = "SELECT Name, IsTimeSlot,TimeSlotStart,TimeSlotEnd, " // 1..4 + + "IsDateSlot,OnMonday,OnTuesday,OnWednesday," // 5..8 + + "OnThursday,OnFriday,OnSaturday,OnSunday " // 9..12 + + "FROM S_ResourceType " + + "WHERE S_ResourceType_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, m_S_ResourceType_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + m_typeName = rs.getString(1); + // TimeSlot + if ("Y".equals(rs.getString(2))) + { + m_slotStartTime = TimeUtil.getDayTime (m_startDate, rs.getTimestamp(3)); + m_slotEndTime = TimeUtil.getDayTime (m_endDate, rs.getTimestamp(4)); + if (TimeUtil.inRange(m_startDate, m_endDate, m_slotStartTime, m_slotEndTime)) + { + ma = new MAssignmentSlot (m_slotStartTime, m_slotEndTime, + Msg.getMsg(m_ctx, "ResourceNotInSlotTime"), m_typeName, + MAssignmentSlot.STATUS_NotInSlotTime); + if (getAll) + createTimeSlot (list, + rs.getTimestamp(3), rs.getTimestamp(4)); + } + } // TimeSlot + + // DaySlot + if ("Y".equals(rs.getString(5))) + { + if (TimeUtil.inRange(m_startDate, m_endDate, + "Y".equals(rs.getString(6)), "Y".equals(rs.getString(7)), // Mo..Tu + "Y".equals(rs.getString(8)), "Y".equals(rs.getString(9)), "Y".equals(rs.getString(10)), // We..Fr + "Y".equals(rs.getString(11)), "Y".equals(rs.getString(12)))) + { + ma = new MAssignmentSlot (m_startDate, m_endDate, + Msg.getMsg(m_ctx, "ResourceNotInSlotDay"), m_typeName, + MAssignmentSlot.STATUS_NotInSlotDay); + if (getAll) + createDaySlot (list, + "Y".equals(rs.getString(6)), "Y".equals(rs.getString(7)), // Mo..Tu + "Y".equals(rs.getString(8)), "Y".equals(rs.getString(9)), "Y".equals(rs.getString(10)), // We..Fr + "Y".equals(rs.getString(11)), "Y".equals(rs.getString(12))); + } + } // DaySlot + + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + ma = new MAssignmentSlot (EARLIEST, LATEST, + Msg.getMsg(m_ctx, "ResourceNotInSlotDay"), e.toString(), + MAssignmentSlot.STATUS_NonBusinessDay); + } + if (ma != null && !getAll) + return new MAssignmentSlot[] {ma}; + + // Assignments ------------------------------------------------------- + sql = "SELECT S_ResourceAssignment_ID " + + "FROM S_ResourceAssignment " + + "WHERE S_Resource_ID=?" // #1 + + " AND AssignDateTo >= ?" // #2 start + + " AND AssignDateFrom <= ?" // #3 end + + " AND IsActive='Y'"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, m_S_Resource_ID); + pstmt.setTimestamp(2, m_startDate); + pstmt.setTimestamp(3, m_endDate); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + MResourceAssignment mAssignment = + new MResourceAssignment(Env.getCtx(), rs.getInt(1), trxName); + ma = new MAssignmentSlot (mAssignment); + if (!getAll) + break; + list.add(ma); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + ma = new MAssignmentSlot (EARLIEST, LATEST, + Msg.translate(m_ctx, "S_R"), e.toString(), + MAssignmentSlot.STATUS_NotConfirmed); + } + if (ma != null && !getAll) + return new MAssignmentSlot[] {ma}; + + /*********************************************************************/ + + // fill m_timeSlots (required for layout) + createTimeSlots(); + + // Clean list - date range + ArrayList clean = new ArrayList(list.size()); + for (int i = 0; i < list.size(); i++) + { + MAssignmentSlot mas = (MAssignmentSlot)list.get(i); + if ((mas.getStartTime().equals(m_startDate) || mas.getStartTime().after(m_startDate)) + && (mas.getEndTime().equals(m_endDate) || mas.getEndTime().before(m_endDate))) + clean.add(mas); + } + // Delete Unavailability TimeSlots when all day assigments exist + MAssignmentSlot[] sorted = new MAssignmentSlot[clean.size()]; + clean.toArray(sorted); + Arrays.sort(sorted, new MAssignmentSlot()); // sorted by start/end date + list.clear(); // used as day list + clean.clear(); // cleaned days + Timestamp sortedDay = null; + for (int i = 0; i < sorted.length; i++) + { + if (sortedDay == null) + sortedDay = TimeUtil.getDay(sorted[i].getStartTime()); + if (sortedDay.equals(TimeUtil.getDay(sorted[i].getStartTime()))) + list.add(sorted[i]); + else + { + // process info list -> clean + layoutSlots (list, clean); + // prepare next + list.clear(); + list.add(sorted[i]); + sortedDay = TimeUtil.getDay(sorted[i].getStartTime()); + } + } + // process info list -> clean + layoutSlots (list, clean); + + // Return + MAssignmentSlot[] retValue = new MAssignmentSlot[clean.size()]; + clean.toArray(retValue); + Arrays.sort(retValue, new MAssignmentSlot()); // sorted by start/end date + return retValue; + } // getAssignmentSlots + + /** + * Copy valid Slots of a day from list to clear and layout + * @param list list with slos of the day + * @param clean list with only valid slots + */ + @SuppressWarnings("unchecked") + private void layoutSlots (ArrayList list, ArrayList clean) + { + int size = list.size(); + // System.out.println("Start List=" + size + ", Clean=" + clean.size()); + if (size == 0) + return; + else if (size == 1) + { + MAssignmentSlot mas = (MAssignmentSlot)list.get(0); + layoutY (mas); + clean.add (mas); + return; + } + + // Delete Unavailability TimeSlots when all day assigments exist + boolean allDay = false; + for (int i = 0; !allDay && i < size; i++) + { + MAssignmentSlot mas = (MAssignmentSlot)list.get(i); + if (mas.getStatus() == MAssignmentSlot.STATUS_NotAvailable + || mas.getStatus() == MAssignmentSlot.STATUS_UnAvailable + || mas.getStatus() == MAssignmentSlot.STATUS_NonBusinessDay + || mas.getStatus() == MAssignmentSlot.STATUS_NotInSlotDay) + allDay = true; + + } + if (allDay) + { + // delete Time Slot + for (int i = 0; i < list.size(); i++) + { + MAssignmentSlot mas = (MAssignmentSlot)list.get(i); + if (mas.getStatus() == MAssignmentSlot.STATUS_NotInSlotTime) + list.remove(i--); + } + } + + // Copy & Y layout remaining + for (int i = 0; i < list.size(); i++) + { + MAssignmentSlot mas = (MAssignmentSlot)list.get(i); + layoutY (mas); + clean.add (mas); + } + + // X layout + int maxYslots = m_timeSlots.length; + int[] xSlots = new int[maxYslots]; // number of parallel slots + for (int i = 0; i < list.size(); i++) + { + MAssignmentSlot mas = (MAssignmentSlot)list.get(i); + for (int y = mas.getYStart(); y < mas.getYEnd(); y++) + xSlots[y]++; + } + // Max parallel X Slots + int maxXslots = 0; + for (int y = 0; y < xSlots.length; y++) + { + if (xSlots[y] > maxXslots) + maxXslots = xSlots[y]; + } + // Only one column + if (maxXslots < 2) + { + for (int i = 0; i < list.size(); i++) + { + MAssignmentSlot mas = (MAssignmentSlot)list.get(i); + mas.setX(0, 1); + } + return; + } + + // Create xy Matrix + ArrayList[][] matrix = new ArrayList[maxXslots][maxYslots]; + // Populate Matrix first column + for (int y = 0; y < maxYslots; y++) + { + ArrayList xyList = new ArrayList(); + matrix[0][y] = xyList; + // see if one assignment fits into slot + for (int i = 0; i < list.size(); i++) + { + MAssignmentSlot mas = (MAssignmentSlot)list.get(i); + if (y >= mas.getYStart() && y <= mas.getYEnd()) + xyList.add(mas); + } + // initiate right columns + for (int x = 1; x < maxXslots; x++) + matrix[x][y] = new ArrayList(); + } // for all y slots + + /** + * (AB)() -> (B)(A) -> (B)(A) + * (BC)() -> (BC)() -> (B)(C) + * - if the row above is empty, move the first one right + * - else - check col_1..x above and move any content if the same + * - if size > 0 + * - if the element is is not the same as above, + * move to the first empty column on the right + */ + // if in one column cell, there is more than one, move it to the right + for (int y = 0; y < maxYslots; y++) + { + // if an element is the same as the line above, move it there + if (y > 0 && matrix[0][y].size() > 0) + { + for (int x = 1; x < maxXslots; x++) + { + if (matrix[x][y-1].size() > 0) // above slot is not empty + { + Object above = matrix[x][y-1].get(0); + for (int i = 0; i < matrix[x][y].size(); i++) + { + if (above.equals(matrix[0][y].get(i))) // same - move it + { + matrix[x][y].add(matrix[0][y].get(i)); + matrix[0][y].remove(i--); + } + } + } + } + } // if an element is the same as the line above, move it there + + // we need to move items to the right + if (matrix[0][y].size() > 1) + { + Object above = null; + if (y > 0 && matrix[0][y-1].size() > 0) + above = matrix[0][y-1].get(0); + // + for (int i = 0; matrix[0][y].size() > 1; i++) + { + Object move = matrix[0][y].get(i); + if (!move.equals(above)) // we can move it + { + for (int x = 1; move != null && x < maxXslots; x++) + { + if (matrix[x][y].size() == 0) // found an empty slot + { + matrix[x][y].add(move); + matrix[0][y].remove(i--); + move = null; + } + } + } + } + } // we need to move items to the right + } // for all y slots + + // go through the matrix and assign the X position + for (int y = 0; y < maxYslots; y++) + { + for (int x = 0; x < maxXslots; x++) + { + if (matrix[x][y].size() > 0) + { + MAssignmentSlot mas = (MAssignmentSlot)matrix[x][y].get(0); + mas.setX(x, xSlots[y]); + } + } + } + // clean up + matrix = null; + } // layoutSlots + + /** + * Layout Y axis + * @param mas assignment slot + */ + private void layoutY (MAssignmentSlot mas) + { + int timeSlotStart = getTimeSlotIndex(mas.getStartTime(), false); + int timeSlotEnd = getTimeSlotIndex(mas.getEndTime(), true); + if (TimeUtil.isAllDay(mas.getStartTime(), mas.getEndTime())) + timeSlotEnd = m_timeSlots.length - 1; + // + mas.setY (timeSlotStart, timeSlotEnd); + } // layoutY + + /** + * Return the Time Slot index for the time. + * Based on start time and not including end time + * @param time time (day is ignored) + * @param endTime if true, the end time is included + * @return slot index + */ + private int getTimeSlotIndex (Timestamp time, boolean endTime) + { + // Just one slot + if (m_timeSlots.length <= 1) + return 0; + // search for it + for (int i = 0; i < m_timeSlots.length; i++) + { + if (m_timeSlots[i].inSlot (time, endTime)) + return i; + } + log.log(Level.SEVERE, "MSchedule.getTimeSlotIndex - did not find Slot for " + time + " end=" + endTime); + return 0; + } // getTimeSlotIndex + + + /** + * Get Basic Info + * @param S_Resource_ID resource + */ + private void getBaseInfo (int S_Resource_ID) + { + // Resource is Active and Available + String sql = MRole.getDefault(m_ctx, false).addAccessSQL ( + "SELECT r.IsActive,r.IsAvailable,null," // r.IsSingleAssignment," + + "r.S_ResourceType_ID,rt.C_UOM_ID " + + "FROM S_Resource r, S_ResourceType rt " + + "WHERE r.S_Resource_ID=?" + + " AND r.S_ResourceType_ID=rt.S_ResourceType_ID", + "r", MRole.SQL_FULLYQUALIFIED, MRole.SQL_RO); + // + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, S_Resource_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + if (!"Y".equals(rs.getString(1))) // Active + m_isAvailable = false; + if (m_isAvailable && !"Y".equals(rs.getString(2))) // Available + m_isAvailable = false; + m_isSingleAssignment = "Y".equals(rs.getString(3)); + // + m_S_ResourceType_ID = rs.getInt(4); + m_C_UOM_ID = rs.getInt(5); + // log.fine( "- Resource_ID=" + m_S_ResourceType_ID + ",IsAvailable=" + m_isAvailable); + } + else + m_isAvailable = false; + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + m_isAvailable = false; + } + m_S_Resource_ID = S_Resource_ID; + } // getBaseInfo + + /** + * Create Unavailable Timeslots. + * For every day from startDay..endDay create unavailable slots + * for 00:00..startTime and endTime..24:00 + * @param list list to add time slots to + * @param startTime start time in day + * @param endTime end time in day + */ + private void createTimeSlot (ArrayList list, + Timestamp startTime, Timestamp endTime) + { + // log.fine( "MSchedule.createTimeSlot"); + GregorianCalendar cal = new GregorianCalendar(Language.getLoginLanguage().getLocale()); + cal.setTimeInMillis(m_startDate.getTime()); + // End Date for Comparison + GregorianCalendar calEnd = new GregorianCalendar(Language.getLoginLanguage().getLocale()); + calEnd.setTimeInMillis(m_endDate.getTime()); + + while (cal.before(calEnd)) + { + // 00:00..startTime + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + Timestamp start = new Timestamp (cal.getTimeInMillis()); + // + GregorianCalendar cal_1 = new GregorianCalendar(Language.getLoginLanguage().getLocale()); + cal_1.setTimeInMillis(startTime.getTime()); + cal.set(Calendar.HOUR_OF_DAY, cal_1.get(Calendar.HOUR_OF_DAY)); + cal.set(Calendar.MINUTE, cal_1.get(Calendar.MINUTE)); + cal.set(Calendar.SECOND, cal_1.get(Calendar.SECOND)); + Timestamp end = new Timestamp (cal.getTimeInMillis()); + // + MAssignmentSlot ma = new MAssignmentSlot (start, end, + Msg.getMsg(m_ctx, "ResourceNotInSlotTime"), "", + MAssignmentSlot.STATUS_NotInSlotTime); + list.add(ma); + + // endTime .. 00:00 next day + cal_1.setTimeInMillis(endTime.getTime()); + cal.set(Calendar.HOUR_OF_DAY, cal_1.get(Calendar.HOUR_OF_DAY)); + cal.set(Calendar.MINUTE, cal_1.get(Calendar.MINUTE)); + cal.set(Calendar.SECOND, cal_1.get(Calendar.SECOND)); + start = new Timestamp (cal.getTimeInMillis()); + // + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.add(Calendar.DAY_OF_YEAR, 1); + end = new Timestamp (cal.getTimeInMillis()); + // + ma = new MAssignmentSlot (start, end, + Msg.getMsg(m_ctx, "ResourceNotInSlotTime"), "", + MAssignmentSlot.STATUS_NotInSlotTime); + list.add(ma); + } + } // createTimeSlot + + /** + * Create Unavailable Dayslots. + * For every day from startDay..endDay create unavailable slots + * @param list list to add Day slots to + * @param OnMonday true if OK to have appointments (i.e. blocked if false) + * @param OnTuesday true if OK + * @param OnWednesday true if OK + * @param OnThursday true if OK + * @param OnFriday true if OK + * @param OnSaturday true if OK + * @param OnSunday true if OK + */ + private void createDaySlot (ArrayList list, + boolean OnMonday, boolean OnTuesday, boolean OnWednesday, + boolean OnThursday, boolean OnFriday, boolean OnSaturday, boolean OnSunday) + { + // log.fine( "MSchedule.createDaySlot"); + GregorianCalendar cal = new GregorianCalendar(Language.getLoginLanguage().getLocale()); + cal.setTimeInMillis(m_startDate.getTime()); + // End Date for Comparison + GregorianCalendar calEnd = new GregorianCalendar(Language.getLoginLanguage().getLocale()); + calEnd.setTimeInMillis(m_endDate.getTime()); + + while (cal.before(calEnd)) + { + int weekday = cal.get(Calendar.DAY_OF_WEEK); + if ((!OnSaturday && weekday == Calendar.SATURDAY) + || (!OnSunday && weekday == Calendar.SUNDAY) + || (!OnMonday && weekday == Calendar.MONDAY) + || (!OnTuesday && weekday == Calendar.TUESDAY) + || (!OnWednesday && weekday == Calendar.WEDNESDAY) + || (!OnThursday && weekday == Calendar.THURSDAY) + || (!OnFriday && weekday == Calendar.FRIDAY)) + { + // 00:00..00:00 next day + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + Timestamp start = new Timestamp (cal.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, 1); + Timestamp end = new Timestamp (cal.getTimeInMillis()); + + MAssignmentSlot ma = new MAssignmentSlot (start, end, + Msg.getMsg(m_ctx, "ResourceNotInSlotDay"), "", + MAssignmentSlot.STATUS_NotInSlotDay); + list.add(ma); + } + else // next day + cal.add(Calendar.DAY_OF_YEAR, 1); + } + } // createDaySlot + + /** + * Create a day slot for range + * @param list list + * @param ma assignment + */ + private void createDaySlot (ArrayList list, MAssignmentSlot ma) + { + // log.fine( "MSchedule.createDaySlot", ma); + // + Timestamp start = ma.getStartTime(); + GregorianCalendar calStart = new GregorianCalendar(); + calStart.setTime(start); + calStart.set(Calendar.HOUR_OF_DAY, 0); + calStart.set(Calendar.MINUTE, 0); + calStart.set(Calendar.SECOND, 0); + calStart.set(Calendar.MILLISECOND, 0); + Timestamp end = ma.getEndTime(); + GregorianCalendar calEnd = new GregorianCalendar(); + calEnd.setTime(end); + calEnd.set(Calendar.HOUR_OF_DAY, 0); + calEnd.set(Calendar.MINUTE, 0); + calEnd.set(Calendar.SECOND, 0); + calEnd.set(Calendar.MILLISECOND, 0); + // + while (calStart.before(calEnd)) + { + Timestamp xStart = new Timestamp(calStart.getTimeInMillis()); + calStart.add(Calendar.DAY_OF_YEAR, 1); + Timestamp xEnd = new Timestamp(calStart.getTimeInMillis()); + MAssignmentSlot myMa = new MAssignmentSlot (xStart, xEnd, + ma.getName(), ma.getDescription(), ma.getStatus()); + list.add(myMa); + } + } // createDaySlot + + /*************************************************************************/ + + /** + * Get Day Time Slots for Date + * @return "heading" or null + */ + public MAssignmentSlot[] getDayTimeSlots () + { + return m_timeSlots; + } // getDayTimeSlots + + /** + * Create Time Slots + */ + private void createTimeSlots() + { + // development error + if (m_typeName == null) + throw new IllegalStateException("ResourceTypeName not set"); + + ArrayList list = new ArrayList(); + MUOM uom = MUOM.get (m_ctx, m_C_UOM_ID); + int minutes = MUOMConversion.convertToMinutes (m_ctx, m_C_UOM_ID, Env.ONE); + log.config("Minutes=" + minutes); + // + if (minutes > 0 && minutes < 60*24) + { + // Set Start Time + GregorianCalendar cal = new GregorianCalendar(); + cal.setTime(m_startDate); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + // we have slots - create first + if (m_slotStartTime != null) + { + long start = cal.getTimeInMillis(); + cal.setTime(TimeUtil.getDayTime(m_startDate, m_slotStartTime)); // set to start time + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + list.add(new MAssignmentSlot(start, cal.getTimeInMillis())); + } + // Set End Time + GregorianCalendar calEnd = new GregorianCalendar(); + if (m_slotEndTime != null) + { + calEnd.setTime(TimeUtil.getDayTime(m_startDate, m_slotEndTime)); + calEnd.set(Calendar.SECOND, 0); + calEnd.set(Calendar.MILLISECOND, 0); + } + else // No Slot - all day + { + calEnd.setTime(m_startDate); + calEnd.set(Calendar.HOUR_OF_DAY, 0); + calEnd.set(Calendar.MINUTE, 0); + calEnd.set(Calendar.SECOND, 0); + calEnd.set(Calendar.MILLISECOND, 0); + calEnd.add(Calendar.DAY_OF_YEAR, 1); + } +//System.out.println("Start=" + new Timestamp(cal.getTimeInMillis())); +//System.out.println("Endt=" + new Timestamp(calEnd.getTimeInMillis())); + + // Set end Slot Time + GregorianCalendar calEndSlot = new GregorianCalendar(); + calEndSlot.setTime(cal.getTime()); + calEndSlot.add(Calendar.MINUTE, minutes); + + while (cal.before(calEnd)) + { + list.add(new MAssignmentSlot(cal.getTimeInMillis(), calEndSlot.getTimeInMillis())); + // Next Slot + cal.add(Calendar.MINUTE, minutes); + calEndSlot.add(Calendar.MINUTE, minutes); + } + // create last slot + calEndSlot.setTime(cal.getTime()); + calEndSlot.set(Calendar.HOUR_OF_DAY, 0); + calEndSlot.set(Calendar.MINUTE, 0); + calEndSlot.set(Calendar.SECOND, 0); + calEndSlot.set(Calendar.MILLISECOND, 0); + calEndSlot.add(Calendar.DAY_OF_YEAR, 1); // 00:00 next day + list.add(new MAssignmentSlot(cal.getTimeInMillis(), calEndSlot.getTimeInMillis())); + } + + else // Day, .... + { + list.add (new MAssignmentSlot(TimeUtil.getDay(m_startDate), TimeUtil.getNextDay(m_startDate))); + } + + // + m_timeSlots = new MAssignmentSlot[list.size()]; + list.toArray(m_timeSlots); + } // createTimeSlots + + /*************************************************************************/ + + /** + * Get Resource ID. Set by getAssignmentSlots + * @return current resource + */ + public int getS_Resource_ID() + { + return m_S_Resource_ID; + } // getS_Resource_ID + + /** + * Return Start Date. Set by getAssignmentSlots + * @return start date + */ + public Timestamp getStartDate () + { + return m_startDate; + } // getStartDate + + /** + * Return End Date. Set by getAssignmentSlots + * @return end date + */ + public Timestamp getEndDate () + { + return m_endDate; + } // getEndDate + +} // MSchedule diff --git a/base/src/org/compiere/model/Scriptlet.java b/base/src/org/compiere/model/Scriptlet.java new file mode 100644 index 0000000000..f418c24368 --- /dev/null +++ b/base/src/org/compiere/model/Scriptlet.java @@ -0,0 +1,394 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; +import bsh.*; + +/** + * Script Model + * + * @author Jorg Janke + * @version $Id: Scriptlet.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ + */ +public class Scriptlet +{ + /** + * Run Script + * @param variable + * @param script + * @param ctx + * @param WindowNo Included Window variables + * @return result + */ + static Object run (String variable, String script, Properties ctx, int WindowNo) + { + Scriptlet scr = new Scriptlet (variable, script, ctx, WindowNo); + scr.execute(); + return scr.getResult(false); + } // run + + /** + * Constructor + */ + public Scriptlet() + { + this(VARIABLE, "", Env.getCtx(), 0); + } // Scriptlet + + /** Default Result Variable Name */ + public static final String VARIABLE = "result"; + + /** Logger */ + private static CLogger log = CLogger.getCLogger(Scriptlet.class); + + /** + * Full Constructor + * + * @param variable Variable Name + * @param script The Script + * @param prop Environment + * @param WindowNo Included Window variables + */ + public Scriptlet (String variable, String script, Properties prop, int WindowNo) + { + setVariable(variable); + setScript(script); + setEnvironment(prop, WindowNo); + } // Scriptlet + + /** + * Full Constructor + * + * @param variable Variable Name + * @param script The Script + * @param ctx Environment + */ + public Scriptlet (String variable, String script, HashMap ctx) + { + setVariable(variable); + setScript(script); + setEnvironment(ctx); + } // Scriptlet + + /** Variable */ + private String m_variable; + /** Script */ + private String m_script; + /** Context */ + private HashMap m_ctx; + /** Result */ + private Object m_result; + + /*************************************************************************/ + + /** + * Execute Script + * Loads environment and saves result + * @return null or Exception + */ + public Exception execute() + { + m_result = null; + if (m_variable == null || m_variable.length() == 0 || m_script == null || m_script.length() == 0) + { + IllegalArgumentException e = new IllegalArgumentException("No variable/script"); + log.config(e.toString()); + return e; + } + Interpreter i = new Interpreter(); + loadEnvironment(i); + try + { + log.config(m_script); + i.eval(m_script); + } + catch (Exception e) + { + log.config(e.toString()); + return e; + } + try + { + m_result = i.get (m_variable); + log.config("Result (" + m_result.getClass().getName() + ") " + m_result); + } + catch (Exception e) + { + log.config("Result - " + e); + if (e instanceof NullPointerException) + e = new IllegalArgumentException("Result Variable not found - " + m_variable); + return e; + } + return null; + } // execute + + /** + * Set Environment for Interpreter + * + * @param i Interpreter + */ + private void loadEnvironment (Interpreter i) + { + if (m_ctx == null) + return; + Iterator it = m_ctx.keySet().iterator(); + while (it.hasNext()) + { + String key = (String)it.next(); + Object value = m_ctx.get(key); + try + { + if (value instanceof Boolean) + i.set(key, ((Boolean)value).booleanValue()); + else if (value instanceof Integer) + i.set(key, ((Integer)value).intValue()); + else if (value instanceof Double) + i.set(key, ((Double)value).doubleValue()); + else + i.set(key, value); + } + catch (EvalError ee) + { + log.log(Level.SEVERE, "", ee); + } + } + } // setEnvironment + + /*************************************************************************/ + + /** + * Get Variable + * @return variable + */ + public String getVariable() + { + return m_variable; + } // getVariable + + /** + * Set Variable + * @param variable - if null set to VARIABLE + */ + public void setVariable(String variable) + { + if (variable == null || variable.length() == 0) + m_variable = VARIABLE; + else + m_variable = variable; + } + + /** + * Set Script + * @param script + */ + public void setScript(String script) + { + if (script == null) + m_script = ""; + else + m_script = script; + } // setScript + + /** + * Get Script + * @return script + */ + public String getScript() + { + return m_script; + } // getScript + + /** + * Set Environment + * @param prop + * @param WindowNo included Window variables + */ + public void setEnvironment (Properties prop, int WindowNo) + { + if (prop == null) + prop = Env.getCtx(); + + m_ctx = new HashMap(); + // Convert properties to HashMap + Enumeration en = prop.keys(); + while (en.hasMoreElements()) + { + String key = en.nextElement().toString(); + // filter + if (key == null || key.length() == 0 + || key.startsWith("P") // Preferences + || (key.indexOf("|") != -1 && !key.startsWith(String.valueOf(WindowNo))) // other Window Settings + ) + continue; + + String value = prop.getProperty(key); + setEnvironment (key, value); + } + + } // setEnvironment + + /** + * Set Environment key to value + * + * @param key variable name ('#' will be converted to '_') + * @param stringValue try to convert to Object + */ + public void setEnvironment (String key, String stringValue) + { + if (key == null || key.length() == 0) + return; + // log.fine( "Scriptlet.setEnvironment " + key, stringValue); + if (stringValue == null) + { + m_ctx.remove(key); + return; + } + + // Boolean + if (stringValue.equals("Y")) + { + m_ctx.put(convertKey(key), new Boolean(true)); + return; + } + if (stringValue.equals("N")) + { + m_ctx.put(convertKey(key), new Boolean(false)); + return; + } + + // Timestamp + Timestamp timeValue = null; + try + { + timeValue = Timestamp.valueOf(stringValue); + m_ctx.put(convertKey(key), timeValue); + return; + } + catch (Exception e) {} + + // Numeric + Integer intValue = null; + try { + intValue = Integer.valueOf(stringValue); + } catch (Exception e) {} + Double doubleValue = null; + try { + doubleValue = Double.valueOf(stringValue); + } catch (Exception e) {} + if (doubleValue != null) + { + if (intValue != null) + { + double di = Double.parseDouble(intValue.toString()); + // the numbers are the same -> integer + if (Double.compare(di, doubleValue.doubleValue()) == 0) + { + m_ctx.put(convertKey(key), intValue); + return; + } + } + m_ctx.put(convertKey(key), doubleValue); + return; + } + if (intValue != null) + { + m_ctx.put(convertKey(key), intValue); + return; + } + m_ctx.put(convertKey(key), stringValue); + } // SetEnvironment + + /** + * Set Environment key to value + * + * @param key variable name ('#' will be vonverted to '_') + * @param value + */ + public void setEnvironment (String key, Object value) + { + if (key != null && key.length() > 0) + { + // log.fine( "Scriptlet.setEnvironment " + key, value); + if (value == null) + m_ctx.remove(key); + else + m_ctx.put(convertKey(key), value); + } + } // SetEnvironment + + /** + * Convert Key + * # -> _ + * @param key + * @return converted key + */ + private String convertKey (String key) + { + String retValue = Util.replace(key, "#", "_"); + return retValue; + } // convertKey + + /** + * Set Environment + * @param ctx + */ + public void setEnvironment (HashMap ctx) + { + if (ctx == null) + m_ctx = new HashMap(); + else + m_ctx = ctx; + } // setEnvironment + + /** + * Get Environment + * @return environment + */ + public HashMap getEnvironment() + { + return m_ctx; + } // getEnvironment + + + /************************************************************************** + * Get Result + * @param runIt if true, execute script + * @return result or null + */ + public Object getResult (boolean runIt) + { + if (runIt) + execute(); + return m_result; + } // getResult + + /** + * String Representation incl. Result + * @return Scipt + */ + public String toString() + { + StringBuffer sb = new StringBuffer(m_variable); + sb.append(" { ").append(m_script).append(" } = ").append(getResult(true)); + return sb.toString(); + } // toString + +} // Scriptlet diff --git a/base/src/org/compiere/model/Tax.java b/base/src/org/compiere/model/Tax.java new file mode 100644 index 0000000000..55a025b3ce --- /dev/null +++ b/base/src/org/compiere/model/Tax.java @@ -0,0 +1,599 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Tax Handling + * + * @author Jorg Janke + * @version $Id: Tax.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class Tax +{ + /** Logger */ + static private CLogger log = CLogger.getCLogger (Tax.class); + + + /************************************************************************** + * Get Tax ID - converts parameters to call Get Tax. + *
+	 *		M_Product_ID/C_Charge_ID	->	C_TaxCategory_ID
+	 *		billDate, shipDate			->	billDate, shipDate
+	 *		AD_Org_ID					->	billFromC_Location_ID
+	 *		M_Warehouse_ID				->	shipFromC_Location_ID
+	 *		billC_BPartner_Location_ID  ->	billToC_Location_ID
+	 *		shipC_BPartner_Location_ID 	->	shipToC_Location_ID
+	 *
+	 *  if IsSOTrx is false, bill and ship are reversed
+	 *  
+ * @param ctx context + * @param M_Product_ID product + * @param C_Charge_ID product + * @param billDate invoice date + * @param shipDate ship date + * @param AD_Org_ID org + * @param M_Warehouse_ID warehouse + * @param billC_BPartner_Location_ID invoice location + * @param shipC_BPartner_Location_ID ship location + * @param IsSOTrx is a sales trx + * @return C_Tax_ID + * If error it returns 0 and sets error log (TaxCriteriaNotFound) + */ + public static int get (Properties ctx, int M_Product_ID, int C_Charge_ID, + Timestamp billDate, Timestamp shipDate, + int AD_Org_ID, int M_Warehouse_ID, + int billC_BPartner_Location_ID, int shipC_BPartner_Location_ID, + boolean IsSOTrx) + { + if (M_Product_ID != 0) + return getProduct (ctx, M_Product_ID, billDate, shipDate, AD_Org_ID, M_Warehouse_ID, + billC_BPartner_Location_ID, shipC_BPartner_Location_ID, IsSOTrx); + else if (C_Charge_ID != 0) + return getCharge (ctx, C_Charge_ID, billDate, shipDate, AD_Org_ID, M_Warehouse_ID, + billC_BPartner_Location_ID, shipC_BPartner_Location_ID, IsSOTrx); + else + return getExemptTax (ctx, AD_Org_ID); + } // get + + /** + * Get Tax ID - converts parameters to call Get Tax. + *
+	 *		C_Charge_ID					->	C_TaxCategory_ID
+	 *		billDate, shipDate			->	billDate, shipDate
+	 *		AD_Org_ID					->	billFromC_Location_ID
+	 *		M_Warehouse_ID				->	shipFromC_Location_ID
+	 *		billC_BPartner_Location_ID  ->	billToC_Location_ID
+	 *		shipC_BPartner_Location_ID 	->	shipToC_Location_ID
+	 *
+	 *  if IsSOTrx is false, bill and ship are reversed
+	 *  
+ * @param ctx context + * @param C_Charge_ID product + * @param billDate invoice date + * @param shipDate ship date + * @param AD_Org_ID org + * @param M_Warehouse_ID warehouse + * @param billC_BPartner_Location_ID invoice location + * @param shipC_BPartner_Location_ID ship location + * @param IsSOTrx is a sales trx + * @return C_Tax_ID + * If error it returns 0 and sets error log (TaxCriteriaNotFound) + */ + public static int getCharge (Properties ctx, int C_Charge_ID, + Timestamp billDate, Timestamp shipDate, + int AD_Org_ID, int M_Warehouse_ID, + int billC_BPartner_Location_ID, int shipC_BPartner_Location_ID, + boolean IsSOTrx) + { + if (M_Warehouse_ID == 0) + M_Warehouse_ID = Env.getContextAsInt(ctx, "M_Warehouse_ID"); + if (M_Warehouse_ID == 0) + { + log.warning("No Warehouse - C_Charge_ID=" + C_Charge_ID); + return 0; + } + String variable = ""; + int C_TaxCategory_ID = 0; + int shipFromC_Location_ID = 0; + int shipToC_Location_ID = 0; + int billFromC_Location_ID = 0; + int billToC_Location_ID = 0; + String IsTaxExempt = null; + + // Get all at once + String sql = "SELECT c.C_TaxCategory_ID, o.C_Location_ID, il.C_Location_ID, b.IsTaxExempt," + + " w.C_Location_ID, sl.C_Location_ID " + + "FROM C_Charge c, AD_OrgInfo o," + + " C_BPartner_Location il INNER JOIN C_BPartner b ON (il.C_BPartner_ID=b.C_BPartner_ID)," + + " M_Warehouse w, C_BPartner_Location sl " + + "WHERE c.C_Charge_ID=?" + + " AND o.AD_Org_ID=?" + + " AND il.C_BPartner_Location_ID=?" + + " AND w.M_Warehouse_ID=?" + + " AND sl.C_BPartner_Location_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, C_Charge_ID); + pstmt.setInt (2, AD_Org_ID); + pstmt.setInt (3, billC_BPartner_Location_ID); + pstmt.setInt (4, M_Warehouse_ID); + pstmt.setInt (5, shipC_BPartner_Location_ID); + ResultSet rs = pstmt.executeQuery (); + boolean found = false; + if (rs.next ()) + { + C_TaxCategory_ID = rs.getInt (1); + billFromC_Location_ID = rs.getInt (2); + billToC_Location_ID = rs.getInt (3); + IsTaxExempt = rs.getString (4); + shipFromC_Location_ID = rs.getInt (5); + shipToC_Location_ID = rs.getInt (6); + found = true; + } + rs.close (); + pstmt.close (); + // + if (!found) + { + log.warning("Not found for C_Charge_ID=" + C_Charge_ID + + ", AD_Org_ID=" + AD_Org_ID + ", M_Warehouse_ID=" + M_Warehouse_ID + + ", C_BPartner_Location_ID=" + billC_BPartner_Location_ID + + "/" + shipC_BPartner_Location_ID); + return 0; + } + else if ("Y".equals (IsTaxExempt)) + return getExemptTax (ctx, AD_Org_ID); + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + return 0; + } + + // Reverese for PO + if (!IsSOTrx) + { + int temp = billFromC_Location_ID; + billFromC_Location_ID = billToC_Location_ID; + billToC_Location_ID = temp; + temp = shipFromC_Location_ID; + shipFromC_Location_ID = shipToC_Location_ID; + shipToC_Location_ID = temp; + } + // + log.fine("getCharge - C_TaxCategory_ID=" + C_TaxCategory_ID + + ", billFromC_Location_ID=" + billFromC_Location_ID + + ", billToC_Location_ID=" + billToC_Location_ID + + ", shipFromC_Location_ID=" + shipFromC_Location_ID + + ", shipToC_Location_ID=" + shipToC_Location_ID); + return get (ctx, C_TaxCategory_ID, IsSOTrx, + shipDate, shipFromC_Location_ID, shipToC_Location_ID, + billDate, billFromC_Location_ID, billToC_Location_ID); + } // getCharge + + + /** + * Get Tax ID - converts parameters to call Get Tax. + *
+	 *		M_Product_ID				->	C_TaxCategory_ID
+	 *		billDate, shipDate			->	billDate, shipDate
+	 *		AD_Org_ID					->	billFromC_Location_ID
+	 *		M_Warehouse_ID				->	shipFromC_Location_ID
+	 *		billC_BPartner_Location_ID  ->	billToC_Location_ID
+	 *		shipC_BPartner_Location_ID 	->	shipToC_Location_ID
+	 *
+	 *  if IsSOTrx is false, bill and ship are reversed
+	 *  
+ * @param ctx context + * @param M_Product_ID product + * @param billDate invoice date + * @param shipDate ship date + * @param AD_Org_ID org + * @param M_Warehouse_ID warehouse + * @param billC_BPartner_Location_ID invoice location + * @param shipC_BPartner_Location_ID ship location + * @param IsSOTrx is a sales trx + * @return C_Tax_ID + * If error it returns 0 and sets error log (TaxCriteriaNotFound) + */ + public static int getProduct (Properties ctx, int M_Product_ID, + Timestamp billDate, Timestamp shipDate, + int AD_Org_ID, int M_Warehouse_ID, + int billC_BPartner_Location_ID, int shipC_BPartner_Location_ID, + boolean IsSOTrx) + { + String variable = ""; + int C_TaxCategory_ID = 0; + int shipFromC_Location_ID = 0; + int shipToC_Location_ID = 0; + int billFromC_Location_ID = 0; + int billToC_Location_ID = 0; + String IsTaxExempt = null; + + try + { + // Get all at once + String sql = "SELECT p.C_TaxCategory_ID, o.C_Location_ID, il.C_Location_ID, b.IsTaxExempt," + + " w.C_Location_ID, sl.C_Location_ID " + + "FROM M_Product p, AD_OrgInfo o," + + " C_BPartner_Location il INNER JOIN C_BPartner b ON (il.C_BPartner_ID=b.C_BPartner_ID)," + + " M_Warehouse w, C_BPartner_Location sl " + + "WHERE p.M_Product_ID=?" + + " AND o.AD_Org_ID=?" + + " AND il.C_BPartner_Location_ID=?" + + " AND w.M_Warehouse_ID=?" + + " AND sl.C_BPartner_Location_ID=?"; + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, M_Product_ID); + pstmt.setInt(2, AD_Org_ID); + pstmt.setInt(3, billC_BPartner_Location_ID); + pstmt.setInt(4, M_Warehouse_ID); + pstmt.setInt(5, shipC_BPartner_Location_ID); + ResultSet rs = pstmt.executeQuery(); + boolean found = false; + if (rs.next()) + { + C_TaxCategory_ID = rs.getInt(1); + billFromC_Location_ID = rs.getInt(2); + billToC_Location_ID = rs.getInt(3); + IsTaxExempt = rs.getString(4); + shipFromC_Location_ID = rs.getInt(5); + shipToC_Location_ID = rs.getInt(6); + found = true; + } + rs.close(); + pstmt.close(); + // + if (found && "Y".equals(IsTaxExempt)) + { + log.fine("getProduct - Business Partner is Tax exempt"); + return getExemptTax(ctx, AD_Org_ID); + } + else if (found) + { + if (!IsSOTrx) + { + int temp = billFromC_Location_ID; + billFromC_Location_ID = billToC_Location_ID; + billToC_Location_ID = temp; + temp = shipFromC_Location_ID; + shipFromC_Location_ID = shipToC_Location_ID; + shipToC_Location_ID = temp; + } + log.fine("getProduct - C_TaxCategory_ID=" + C_TaxCategory_ID + + ", billFromC_Location_ID=" + billFromC_Location_ID + + ", billToC_Location_ID=" + billToC_Location_ID + + ", shipFromC_Location_ID=" + shipFromC_Location_ID + + ", shipToC_Location_ID=" + shipToC_Location_ID); + return get(ctx, C_TaxCategory_ID, IsSOTrx, + shipDate, shipFromC_Location_ID, shipToC_Location_ID, + billDate, billFromC_Location_ID, billToC_Location_ID); + } + + // ---------------------------------------------------------------- + + // Detail for error isolation + + // M_Product_ID -> C_TaxCategory_ID + sql = "SELECT C_TaxCategory_ID FROM M_Product " + + "WHERE M_Product_ID=?"; + variable = "M_Product_ID"; + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, M_Product_ID); + rs = pstmt.executeQuery(); + found = false; + if (rs.next()) + { + C_TaxCategory_ID = rs.getInt(1); + found = true; + } + rs.close(); + pstmt.close(); + if (C_TaxCategory_ID == 0) + { + log.saveError("TaxCriteriaNotFound", Msg.translate(ctx, variable) + + (found ? "" : " (Product=" + M_Product_ID + " not found)")); + return 0; + } + log.fine("getProduct - C_TaxCategory_ID=" + C_TaxCategory_ID); + + // AD_Org_ID -> billFromC_Location_ID + sql = "SELECT C_Location_ID FROM AD_OrgInfo " + + "WHERE AD_Org_ID=?"; + variable = "AD_Org_ID"; + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Org_ID); + rs = pstmt.executeQuery(); + found = false; + if (rs.next()) + { + billFromC_Location_ID = rs.getInt (1); + found = true; + } + rs.close(); + pstmt.close(); + if (billFromC_Location_ID == 0) + { + log.saveError("TaxCriteriaNotFound", Msg.translate(Env.getAD_Language(ctx), variable) + + (found ? "" : " (Info/Org=" + AD_Org_ID + " not found)")); + return 0; + } + + // billC_BPartner_Location_ID -> billToC_Location_ID + sql = "SELECT l.C_Location_ID, b.IsTaxExempt " + + "FROM C_BPartner_Location l INNER JOIN C_BPartner b ON (l.C_BPartner_ID=b.C_BPartner_ID) " + + "WHERE C_BPartner_Location_ID=?"; + variable = "BillTo_ID"; + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, billC_BPartner_Location_ID); + rs = pstmt.executeQuery(); + found = false; + if (rs.next()) + { + billToC_Location_ID = rs.getInt(1); + IsTaxExempt = rs.getString(2); + found = true; + } + rs.close(); + pstmt.close(); + if (billToC_Location_ID == 0) + { + log.saveError("TaxCriteriaNotFound", Msg.translate(Env.getAD_Language(ctx), variable) + + (found ? "" : " (BPLocation=" + billC_BPartner_Location_ID + " not found)")); + return 0; + } + if ("Y".equals(IsTaxExempt)) + return getExemptTax(ctx, AD_Org_ID); + + // Reverse for PO + if (!IsSOTrx) + { + int temp = billFromC_Location_ID; + billFromC_Location_ID = billToC_Location_ID; + billToC_Location_ID = temp; + } + log.fine("getProduct - billFromC_Location_ID = " + billFromC_Location_ID); + log.fine("getProduct - billToC_Location_ID = " + billToC_Location_ID); + + //----------------------------------------------------------------- + + // M_Warehouse_ID -> shipFromC_Location_ID + sql = "SELECT C_Location_ID FROM M_Warehouse " + + "WHERE M_Warehouse_ID=?"; + variable = "M_Warehouse_ID"; + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, M_Warehouse_ID); + rs = pstmt.executeQuery(); + found = false; + if (rs.next()) + { + shipFromC_Location_ID = rs.getInt (1); + found = true; + } + rs.close(); + pstmt.close(); + if (shipFromC_Location_ID == 0) + { + log.saveError("TaxCriteriaNotFound", Msg.translate(Env.getAD_Language(ctx), variable) + + (found ? "" : " (Warehouse=" + M_Warehouse_ID + " not found)")); + return 0; + } + + // shipC_BPartner_Location_ID -> shipToC_Location_ID + sql = "SELECT C_Location_ID FROM C_BPartner_Location " + + "WHERE C_BPartner_Location_ID=?"; + variable = "C_BPartner_Location_ID"; + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, shipC_BPartner_Location_ID); + rs = pstmt.executeQuery(); + found = false; + if (rs.next()) + { + shipToC_Location_ID = rs.getInt (1); + found = true; + } + rs.close(); + pstmt.close(); + if (shipToC_Location_ID == 0) + { + log.saveError("TaxCriteriaNotFound", Msg.translate(Env.getAD_Language(ctx), variable) + + (found ? "" : " (BPLocation=" + shipC_BPartner_Location_ID + " not found)")); + return 0; + } + + // Reverse for PO + if (!IsSOTrx) + { + int temp = shipFromC_Location_ID; + shipFromC_Location_ID = shipToC_Location_ID; + shipToC_Location_ID = temp; + } + log.fine("getProduct - shipFromC_Location_ID = " + shipFromC_Location_ID); + log.fine("getProduct - shipToC_Location_ID = " + shipToC_Location_ID); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "getProduct (" + variable + ")", e); + } + + return get (ctx, C_TaxCategory_ID, IsSOTrx, + shipDate, shipFromC_Location_ID, shipToC_Location_ID, + billDate, billFromC_Location_ID, billToC_Location_ID); + } // getProduct + + /** + * Get Exempt Tax Code + * @param ctx context + * @param AD_Org_ID org to find client + * @return C_Tax_ID + */ + private static int getExemptTax (Properties ctx, int AD_Org_ID) + { + int C_Tax_ID = 0; + String sql = "SELECT t.C_Tax_ID " + + "FROM C_Tax t" + + " INNER JOIN AD_Org o ON (t.AD_Client_ID=o.AD_Client_ID) " + + "WHERE t.IsTaxExempt='Y' AND o.AD_Org_ID=? " + + "ORDER BY t.Rate DESC"; + boolean found = false; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Org_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + C_Tax_ID = rs.getInt (1); + found = true; + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "getExemptTax", e); + } + log.fine("getExemptTax - TaxExempt=Y - C_Tax_ID=" + C_Tax_ID); + if (C_Tax_ID == 0) + log.saveError("TaxCriteriaNotFound", Msg.getMsg(ctx, "TaxNoExemptFound") + + (found ? "" : " (Tax/Org=" + AD_Org_ID + " not found)")); + return C_Tax_ID; + } // getExemptTax + + + /************************************************************************** + * Get Tax ID (Detail). + * If error return 0 and set error log (TaxNotFound) + * @param ctx context + * @param C_TaxCategory_ID tax category + * @param IsSOTrx Sales Order Trx + * @param shipDate ship date (ignored) + * @param shipFromC_Locction_ID ship from (ignored) + * @param shipToC_Location_ID ship to (ignored) + * @param billDate invoice date + * @param billFromC_Location_ID invoice from + * @param billToC_Location_ID invoice to + * @return C_Tax_ID + */ + protected static int get (Properties ctx, + int C_TaxCategory_ID, boolean IsSOTrx, + Timestamp shipDate, int shipFromC_Locction_ID, int shipToC_Location_ID, + Timestamp billDate, int billFromC_Location_ID, int billToC_Location_ID) + { + // C_TaxCategory contains CommodityCode + + // API to Tax Vendor comes here + + if (CLogMgt.isLevelFine()) + { + log.info("get(Detail) - Category=" + C_TaxCategory_ID + + ", SOTrx=" + IsSOTrx); + log.config("get(Detail) - BillFrom=" + billFromC_Location_ID + + ", BillTo=" + billToC_Location_ID + ", BillDate=" + billDate); + } + + MTax[] taxes = MTax.getAll (ctx); + MLocation lFrom = new MLocation (ctx, billFromC_Location_ID, null); + MLocation lTo = new MLocation (ctx, billToC_Location_ID, null); + log.finer("From=" + lFrom); + log.finer("To=" + lTo); + + for (int i = 0; i < taxes.length; i++) + { + MTax tax = taxes[i]; + log.finest(tax.toString()); + // + if (tax.getC_TaxCategory_ID() != C_TaxCategory_ID + || !tax.isActive() + || tax.getParent_Tax_ID() != 0) // user parent tax + continue; + if (IsSOTrx && MTax.SOPOTYPE_PurchaseTax.equals(tax.getSOPOType())) + continue; + if (!IsSOTrx && MTax.SOPOTYPE_SalesTax.equals(tax.getSOPOType())) + continue; + + log.finest("From Country - " + (tax.getC_Country_ID() == lFrom.getC_Country_ID() + || tax.getC_Country_ID() == 0)); + log.finest("From Region - " + (tax.getC_Region_ID() == lFrom.getC_Region_ID() + || tax.getC_Region_ID() == 0)); + log.finest("To Country - " + (tax.getTo_Country_ID() == lTo.getC_Country_ID() + || tax.getTo_Country_ID() == 0)); + log.finest("To Region - " + (tax.getTo_Region_ID() == lTo.getC_Region_ID() + || tax.getTo_Region_ID() == 0)); + log.finest("Date valid - " + (!tax.getValidFrom().after(billDate))); + + // From Country + if ((tax.getC_Country_ID() == lFrom.getC_Country_ID() + || tax.getC_Country_ID() == 0) + // From Region + && (tax.getC_Region_ID() == lFrom.getC_Region_ID() + || tax.getC_Region_ID() == 0) + // To Country + && (tax.getTo_Country_ID() == lTo.getC_Country_ID() + || tax.getTo_Country_ID() == 0) + // To Region + && (tax.getTo_Region_ID() == lTo.getC_Region_ID() + || tax.getTo_Region_ID() == 0) + // Date + && !tax.getValidFrom().after(billDate) + ) + { + if (!tax.isPostal()) + return tax.getC_Tax_ID(); + // + MTaxPostal[] postals = tax.getPostals(false); + for (int j = 0; j < postals.length; j++) + { + MTaxPostal postal = postals[j]; + if (postal.isActive() + // Postal From is mandatory + && postal.getPostal().startsWith(lFrom.getPostal()) + // Postal To is optional + && (postal.getPostal_To() == null + || postal.getPostal_To().startsWith(lTo.getPostal())) + ) + return tax.getC_Tax_ID(); + } // for all postals + } + } // for all taxes + + // Default Tax + for (int i = 0; i < taxes.length; i++) + { + MTax tax = taxes[i]; + if (!tax.isDefault() || !tax.isActive() + || tax.getParent_Tax_ID() != 0) // user parent tax + continue; + if (IsSOTrx && MTax.SOPOTYPE_PurchaseTax.equals(tax.getSOPOType())) + continue; + if (!IsSOTrx && MTax.SOPOTYPE_SalesTax.equals(tax.getSOPOType())) + continue; + log.fine("get (default) - " + tax); + return tax.getC_Tax_ID(); + } // for all taxes + + log.saveError("TaxNotFound", ""); + return 0; + } // get + +} // Tax diff --git a/base/src/org/compiere/model/package.html b/base/src/org/compiere/model/package.html new file mode 100644 index 0000000000..028010d019 --- /dev/null +++ b/base/src/org/compiere/model/package.html @@ -0,0 +1,34 @@ + + + + + + + +Provides for.... + +

Package Specification

+ + + +

Related Documentation

+ +For overviews, tutorials, examples, guides, and tool documentation, please see: + + + + + + diff --git a/base/src/org/compiere/process/AD_PrintPaper_Default.java b/base/src/org/compiere/process/AD_PrintPaper_Default.java new file mode 100644 index 0000000000..8d351d2da7 --- /dev/null +++ b/base/src/org/compiere/process/AD_PrintPaper_Default.java @@ -0,0 +1,93 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + * Contributor(s): Carlos Ruiz (globalqss) + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Title: Set Current Format as Default + * + * @author Carlos Ruiz (globalqss) + * @version $Id: AD_PrintPaper_Default.java,v 1.0 2005/09/14 22:29:00 globalqss Exp $ + */ +public class AD_PrintPaper_Default extends SvrProcess +{ + + /** The Client */ + private int p_AD_Client_ID = -1; + /** The Record */ + private int p_Record_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Client_ID")) + p_AD_Client_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_Record_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt() throws Exception + { + StringBuffer sql = new StringBuffer(""); + int cnt = 0; + + log.info("Set Print Format"); + + try + { + sql.append("UPDATE AD_PrintFormat pf " + + "SET AD_PrintPaper_ID = " + p_Record_ID + " " + + "WHERE EXISTS (SELECT * FROM AD_PrintPaper pp " + + "WHERE pf.AD_PrintPaper_ID=pp.AD_PrintPaper_ID " + + "AND IsLandscape = (SELECT IsLandscape FROM AD_PrintPaper " + + "WHERE AD_PrintPaper_ID=" + p_Record_ID + "))"); + if (p_AD_Client_ID != -1) { + sql.append(" AND AD_Client_ID = " + p_AD_Client_ID); + } + cnt = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info("Updated " + cnt + " columns"); + log.fine("Committing ..."); + DB.commit(true, null); + } + catch (Exception e) + { + log.log(Level.SEVERE, "set print format", e); + } + + return "@Copied@=" + cnt; + } // doIt + +} // AD_PrintPaper_Default diff --git a/base/src/org/compiere/process/AcctSchemaCopyAcct.java b/base/src/org/compiere/process/AcctSchemaCopyAcct.java new file mode 100644 index 0000000000..6e64d10a12 --- /dev/null +++ b/base/src/org/compiere/process/AcctSchemaCopyAcct.java @@ -0,0 +1,230 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Copy Accounts from one Acct Schema to another + * + * @author Jorg Janke + * @version $Id: AcctSchemaCopyAcct.java,v 1.3 2006/07/30 00:51:01 jjanke Exp $ + */ +public class AcctSchemaCopyAcct extends SvrProcess +{ + private int p_SourceAcctSchema_ID = 0; + private int p_TargetAcctSchema_ID = 0; + + /** + * Prepare + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_AcctSchema_ID")) + p_SourceAcctSchema_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_TargetAcctSchema_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("SourceAcctSchema_ID=" + p_SourceAcctSchema_ID + + ", TargetAcctSchema_ID=" + p_TargetAcctSchema_ID); + + if (p_SourceAcctSchema_ID == 0 || p_TargetAcctSchema_ID == 0) + throw new AdempiereSystemError("ID=0"); + + if (p_SourceAcctSchema_ID == p_TargetAcctSchema_ID) + throw new AdempiereUserError("Must be different"); + + MAcctSchema source = MAcctSchema.get(getCtx(), p_SourceAcctSchema_ID, null); + if (source.get_ID() == 0) + throw new AdempiereSystemError("NotFound Source C_AcctSchema_ID=" + p_SourceAcctSchema_ID); + MAcctSchema target = new MAcctSchema (getCtx(), p_TargetAcctSchema_ID, get_TrxName()); + if (source.get_ID() == 0) + throw new AdempiereSystemError("NotFound Target C_AcctSchema_ID=" + p_TargetAcctSchema_ID); + + // + MAcctSchemaElement[] sourceElements = source.getAcctSchemaElements(); + MAcctSchemaElement[] targetElements = target.getAcctSchemaElements(); + if (targetElements.length == 0) + throw new AdempiereUserError("NotFound Target C_AcctSchema_Element"); + + // Accounting Element must be the same + MAcctSchemaElement sourceAcctElement = source.getAcctSchemaElement(MAcctSchemaElement.ELEMENTTYPE_Account); + if (sourceAcctElement == null) + throw new AdempiereUserError("NotFound Source AC C_AcctSchema_Element"); + MAcctSchemaElement targetAcctElement = target.getAcctSchemaElement(MAcctSchemaElement.ELEMENTTYPE_Account); + if (targetAcctElement == null) + throw new AdempiereUserError("NotFound Target AC C_AcctSchema_Element"); + if (sourceAcctElement.getC_Element_ID() != targetAcctElement.getC_Element_ID()) + throw new AdempiereUserError("@C_Element_ID@ different"); + + if (MAcctSchemaGL.get(getCtx(), p_TargetAcctSchema_ID) == null) + copyGL(target); + if (MAcctSchemaDefault.get(getCtx(), p_TargetAcctSchema_ID) == null) + copyDefault(target); + + return "@OK@"; + } // doIt + + /** + * Copy GL + * @param targetAS target + * @throws Exception + */ + private void copyGL (MAcctSchema targetAS) throws Exception + { + MAcctSchemaGL source = MAcctSchemaGL.get(getCtx(), p_SourceAcctSchema_ID); + MAcctSchemaGL target = new MAcctSchemaGL(getCtx(), 0, get_TrxName()); + target.setC_AcctSchema_ID(p_TargetAcctSchema_ID); + ArrayList list = source.getAcctInfo(); + for (int i = 0; i < list.size(); i++) + { + KeyNamePair pp = list.get(i); + int sourceC_ValidCombination_ID = pp.getKey(); + String columnName = pp.getName(); + MAccount sourceAccount = MAccount.get(getCtx(), sourceC_ValidCombination_ID); + MAccount targetAccount = createAccount(targetAS, sourceAccount); + target.setValue(columnName, new Integer(targetAccount.getC_ValidCombination_ID())); + } + if (!target.save()) + throw new AdempiereSystemError("Could not Save GL"); + } // copyGL + + /** + * Copy Default + * @param targetAS target + * @throws Exception + */ + private void copyDefault(MAcctSchema targetAS) throws Exception + { + MAcctSchemaDefault source = MAcctSchemaDefault.get(getCtx(), p_SourceAcctSchema_ID); + MAcctSchemaDefault target = new MAcctSchemaDefault(getCtx(), 0, get_TrxName()); + target.setC_AcctSchema_ID(p_TargetAcctSchema_ID); + target.setC_AcctSchema_ID(p_TargetAcctSchema_ID); + ArrayList list = source.getAcctInfo(); + for (int i = 0; i < list.size(); i++) + { + KeyNamePair pp = list.get(i); + int sourceC_ValidCombination_ID = pp.getKey(); + String columnName = pp.getName(); + MAccount sourceAccount = MAccount.get(getCtx(), sourceC_ValidCombination_ID); + MAccount targetAccount = createAccount(targetAS, sourceAccount); + target.setValue(columnName, new Integer(targetAccount.getC_ValidCombination_ID())); + } + if (!target.save()) + throw new AdempiereSystemError("Could not Save Default"); + } // copyDefault + + /** + * Create Account + * @param targetAS target AS + * @param sourceAcct source account + * @return target account + */ + private MAccount createAccount(MAcctSchema targetAS, MAccount sourceAcct) + { + int AD_Client_ID = targetAS.getAD_Client_ID(); + int C_AcctSchema_ID = targetAS.getC_AcctSchema_ID(); + // + int AD_Org_ID = 0; + int Account_ID = 0; + int C_SubAcct_ID = 0; + int M_Product_ID = 0; + int C_BPartner_ID = 0; + int AD_OrgTrx_ID = 0; + int C_LocFrom_ID = 0; + int C_LocTo_ID = 0; + int C_SalesRegion_ID = 0; + int C_Project_ID = 0; + int C_Campaign_ID = 0; + int C_Activity_ID = 0; + int User1_ID = 0; + int User2_ID = 0; + int UserElement1_ID = 0; + int UserElement2_ID = 0; + // + // Active Elements + MAcctSchemaElement[] elements = targetAS.getAcctSchemaElements(); + for (int i = 0; i < elements.length; i++) + { + MAcctSchemaElement ase = elements[i]; + String elementType = ase.getElementType(); + // + if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_Organization)) + AD_Org_ID = sourceAcct.getAD_Org_ID(); + else if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_Account)) + Account_ID = sourceAcct.getAccount_ID(); + else if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_SubAccount)) + C_SubAcct_ID = sourceAcct.getC_SubAcct_ID(); + else if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_BPartner)) + C_BPartner_ID = sourceAcct.getC_BPartner_ID(); + else if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_Product)) + M_Product_ID = sourceAcct.getM_Product_ID(); + else if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_Activity)) + C_Activity_ID = sourceAcct.getC_Activity_ID(); + else if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_LocationFrom)) + C_LocFrom_ID = sourceAcct.getC_LocFrom_ID(); + else if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_LocationTo)) + C_LocTo_ID = sourceAcct.getC_LocTo_ID(); + else if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_Campaign)) + C_Campaign_ID = sourceAcct.getC_Campaign_ID(); + else if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_OrgTrx)) + AD_OrgTrx_ID = sourceAcct.getAD_OrgTrx_ID(); + else if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_Project)) + C_Project_ID = sourceAcct.getC_Project_ID(); + else if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_SalesRegion)) + C_SalesRegion_ID = sourceAcct.getC_SalesRegion_ID(); + else if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_UserList1)) + User1_ID = sourceAcct.getUser1_ID(); + else if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_UserList2)) + User2_ID = sourceAcct.getUser2_ID(); + else if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_UserElement1)) + UserElement1_ID = sourceAcct.getUserElement1_ID(); + else if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_UserElement2)) + UserElement2_ID = sourceAcct.getUserElement2_ID(); + // No UserElement + } + // + return MAccount.get(getCtx(), AD_Client_ID, AD_Org_ID, + C_AcctSchema_ID, Account_ID, C_SubAcct_ID, + M_Product_ID, C_BPartner_ID, AD_OrgTrx_ID, + C_LocFrom_ID, C_LocTo_ID, C_SalesRegion_ID, + C_Project_ID, C_Campaign_ID, C_Activity_ID, + User1_ID, User2_ID, UserElement1_ID, UserElement2_ID); + } // createAccount + + +} // AcctSchemaCopyAcct + diff --git a/base/src/org/compiere/process/AcctSchemaDefaultCopy.java b/base/src/org/compiere/process/AcctSchemaDefaultCopy.java new file mode 100644 index 0000000000..fe1fc2e323 --- /dev/null +++ b/base/src/org/compiere/process/AcctSchemaDefaultCopy.java @@ -0,0 +1,532 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import java.math.*; + +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Add or Copy Acct Schema Default Accounts + * + * @author Jorg Janke + * @version $Id: AcctSchemaDefaultCopy.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class AcctSchemaDefaultCopy extends SvrProcess +{ + /** Acct Schema */ + private int p_C_AcctSchema_ID = 0; + /** Copy & Overwrite */ + private boolean p_CopyOverwriteAcct = false; + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_AcctSchema_ID")) + p_C_AcctSchema_ID = para[i].getParameterAsInt(); + else if (name.equals("CopyOverwriteAcct")) + p_CopyOverwriteAcct = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("C_AcctSchema_ID=" + p_C_AcctSchema_ID + + ", CopyOverwriteAcct=" + p_CopyOverwriteAcct); + if (p_C_AcctSchema_ID == 0) + throw new AdempiereSystemError("C_AcctSchema_ID=0"); + MAcctSchema as = MAcctSchema.get(getCtx(), p_C_AcctSchema_ID); + if (as.get_ID() == 0) + throw new AdempiereSystemError("Not Found - C_AcctSchema_ID=" + p_C_AcctSchema_ID); + MAcctSchemaDefault acct = MAcctSchemaDefault.get (getCtx(), p_C_AcctSchema_ID); + if (acct == null || acct.get_ID() == 0) + throw new AdempiereSystemError("Default Not Found - C_AcctSchema_ID=" + p_C_AcctSchema_ID); + + String sql = null; + int updated = 0; + int created = 0; + int updatedTotal = 0; + int createdTotal = 0; + + // Update existing Product Category + if (p_CopyOverwriteAcct) + { + sql = "UPDATE M_Product_Category_Acct pa " + + "SET P_Revenue_Acct=" + acct.getP_Revenue_Acct() + + ", P_Expense_Acct=" + acct.getP_Expense_Acct() + + ", P_CostAdjustment_Acct=" + acct.getP_CostAdjustment_Acct() + + ", P_InventoryClearing_Acct=" + acct.getP_InventoryClearing_Acct() + + ", P_Asset_Acct=" + acct.getP_Asset_Acct() + + ", P_COGS_Acct=" + acct.getP_COGS_Acct() + + ", P_PurchasePriceVariance_Acct=" + acct.getP_PurchasePriceVariance_Acct() + + ", P_InvoicePriceVariance_Acct=" + acct.getP_InvoicePriceVariance_Acct() + + ", P_TradeDiscountRec_Acct=" + acct.getP_TradeDiscountRec_Acct() + + ", P_TradeDiscountGrant_Acct=" + acct.getP_TradeDiscountGrant_Acct() + + ", Updated=SysDate, UpdatedBy=0 " + + "WHERE pa.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND EXISTS (SELECT * FROM M_Product_Category p " + + "WHERE p.M_Product_Category_ID=pa.M_Product_Category_ID)"; + updated = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(updated), "@Updated@ @M_Product_Category_ID@"); + updatedTotal += updated; + } + // Insert new Product Category + sql = "INSERT INTO M_Product_Category_Acct " + + "(M_Product_Category_ID, C_AcctSchema_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " P_Revenue_Acct, P_Expense_Acct, P_CostAdjustment_Acct, P_InventoryClearing_Acct, P_Asset_Acct, P_CoGs_Acct," + + " P_PurchasePriceVariance_Acct, P_InvoicePriceVariance_Acct," + + " P_TradeDiscountRec_Acct, P_TradeDiscountGrant_Acct) " + + "SELECT p.M_Product_Category_ID, acct.C_AcctSchema_ID," + + " p.AD_Client_ID, p.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0," + + " acct.P_Revenue_Acct, acct.P_Expense_Acct, acct.P_CostAdjustment_Acct, acct.P_InventoryClearing_Acct, acct.P_Asset_Acct, acct.P_CoGs_Acct," + + " acct.P_PurchasePriceVariance_Acct, acct.P_InvoicePriceVariance_Acct," + + " acct.P_TradeDiscountRec_Acct, acct.P_TradeDiscountGrant_Acct " + + "FROM M_Product_Category p" + + " INNER JOIN C_AcctSchema_Default acct ON (p.AD_Client_ID=acct.AD_Client_ID) " + + "WHERE acct.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND NOT EXISTS (SELECT * FROM M_Product_Category_Acct pa " + + "WHERE pa.M_Product_Category_ID=p.M_Product_Category_ID" + + " AND pa.C_AcctSchema_ID=acct.C_AcctSchema_ID)"; + created = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(created), "@Created@ @M_Product_Category_ID@"); + createdTotal += created; + if (!p_CopyOverwriteAcct) // Insert new Products + { + sql = "INSERT INTO M_Product_Acct " + + "(M_Product_ID, C_AcctSchema_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " P_Revenue_Acct, P_Expense_Acct, P_CostAdjustment_Acct, P_InventoryClearing_Acct, P_Asset_Acct, P_CoGs_Acct," + + " P_PurchasePriceVariance_Acct, P_InvoicePriceVariance_Acct," + + " P_TradeDiscountRec_Acct, P_TradeDiscountGrant_Acct) " + + "SELECT p.M_Product_ID, acct.C_AcctSchema_ID," + + " p.AD_Client_ID, p.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0," + + " acct.P_Revenue_Acct, acct.P_Expense_Acct, acct.P_CostAdjustment_Acct, acct.P_InventoryClearing_Acct, acct.P_Asset_Acct, acct.P_CoGs_Acct," + + " acct.P_PurchasePriceVariance_Acct, acct.P_InvoicePriceVariance_Acct," + + " acct.P_TradeDiscountRec_Acct, acct.P_TradeDiscountGrant_Acct " + + "FROM M_Product p" + + " INNER JOIN M_Product_Category_Acct acct ON (acct.M_Product_Category_ID=p.M_Product_Category_ID)" + + "WHERE acct.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND p.M_Product_Category_ID=acct.M_Product_Category_ID" + + " AND NOT EXISTS (SELECT * FROM M_Product_Acct pa " + + "WHERE pa.M_Product_ID=p.M_Product_ID" + + " AND pa.C_AcctSchema_ID=acct.C_AcctSchema_ID)"; + created = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(created), "@Created@ @M_Product_ID@"); + createdTotal += created; + } + + + // Update Business Partner Group + if (p_CopyOverwriteAcct) + { + sql = "UPDATE C_BP_Group_Acct a " + + "SET C_Receivable_Acct=" + acct.getC_Receivable_Acct() + + ", C_Receivable_Services_Acct=" + acct.getC_Receivable_Services_Acct() + + ", C_Prepayment_Acct=" + acct.getC_Prepayment_Acct() + + ", V_Liability_Acct=" + acct.getV_Liability_Acct() + + ", V_Liability_Services_Acct=" + acct.getV_Liability_Services_Acct() + + ", V_Prepayment_Acct=" + acct.getV_Prepayment_Acct() + + ", PayDiscount_Exp_Acct=" + acct.getPayDiscount_Exp_Acct() + + ", PayDiscount_Rev_Acct=" + acct.getPayDiscount_Rev_Acct() + + ", WriteOff_Acct=" + acct.getWriteOff_Acct() + + ", NotInvoicedReceipts_Acct=" + acct.getNotInvoicedReceipts_Acct() + + ", UnEarnedRevenue_Acct=" + acct.getUnEarnedRevenue_Acct() + + ", NotInvoicedRevenue_Acct=" + acct.getNotInvoicedRevenue_Acct() + + ", NotInvoicedReceivables_Acct=" + acct.getNotInvoicedReceivables_Acct() + + ", Updated=SysDate, UpdatedBy=0 " + + "WHERE a.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND EXISTS (SELECT * FROM C_BP_Group_Acct x " + + "WHERE x.C_BP_Group_ID=a.C_BP_Group_ID)"; + updated = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(updated), "@Updated@ @C_BP_Group_ID@"); + updatedTotal += updated; + } + // Insert Business Partner Group + sql = "INSERT INTO C_BP_Group_Acct " + + "(C_BP_Group_ID, C_AcctSchema_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " C_Receivable_Acct, C_Receivable_Services_Acct, C_PrePayment_Acct," + + " V_Liability_Acct, V_Liability_Services_Acct, V_PrePayment_Acct," + + " PayDiscount_Exp_Acct, PayDiscount_Rev_Acct, WriteOff_Acct," + + " NotInvoicedReceipts_Acct, UnEarnedRevenue_Acct," + + " NotInvoicedRevenue_Acct, NotInvoicedReceivables_Acct) " + + "SELECT x.C_BP_Group_ID, acct.C_AcctSchema_ID," + + " x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0," + + " acct.C_Receivable_Acct, acct.C_Receivable_Services_Acct, acct.C_PrePayment_Acct," + + " acct.V_Liability_Acct, acct.V_Liability_Services_Acct, acct.V_PrePayment_Acct," + + " acct.PayDiscount_Exp_Acct, acct.PayDiscount_Rev_Acct, acct.WriteOff_Acct," + + " acct.NotInvoicedReceipts_Acct, acct.UnEarnedRevenue_Acct," + + " acct.NotInvoicedRevenue_Acct, acct.NotInvoicedReceivables_Acct " + + "FROM C_BP_Group x" + + " INNER JOIN C_AcctSchema_Default acct ON (x.AD_Client_ID=acct.AD_Client_ID) " + + "WHERE acct.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND NOT EXISTS (SELECT * FROM C_BP_Group_Acct a " + + "WHERE a.C_BP_Group_ID=x.C_BP_Group_ID" + + " AND a.C_AcctSchema_ID=acct.C_AcctSchema_ID)"; + created = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(created), "@Created@ @C_BP_Group_ID@"); + createdTotal += created; + + + // Update Business Partner - Employee + if (p_CopyOverwriteAcct) + { + sql = "UPDATE C_BP_Employee_Acct a " + + "SET E_Expense_Acct=" + acct.getE_Expense_Acct() + + ", E_Prepayment_Acct=" + acct.getE_Prepayment_Acct() + + ", Updated=SysDate, UpdatedBy=0 " + + "WHERE a.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND EXISTS (SELECT * FROM C_BP_Employee_Acct x " + + "WHERE x.C_BPartner_ID=a.C_BPartner_ID)"; + updated = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(updated), "@Updated@ @C_BPartner_ID@ @IsEmployee@"); + updatedTotal += updated; + } + // Insert new Business Partner - Employee + sql = "INSERT INTO C_BP_Employee_Acct " + + "(C_BPartner_ID, C_AcctSchema_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " E_Expense_Acct, E_Prepayment_Acct) " + + "SELECT x.C_BPartner_ID, acct.C_AcctSchema_ID," + + " x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0," + + " acct.E_Expense_Acct, acct.E_Prepayment_Acct " + + "FROM C_BPartner x" + + " INNER JOIN C_AcctSchema_Default acct ON (x.AD_Client_ID=acct.AD_Client_ID) " + + "WHERE acct.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND NOT EXISTS (SELECT * FROM C_BP_Employee_Acct a " + + "WHERE a.C_BPartner_ID=x.C_BPartner_ID" + + " AND a.C_AcctSchema_ID=acct.C_AcctSchema_ID)"; + created = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(created), "@Created@ @C_BPartner_ID@ @IsEmployee@"); + createdTotal += created; + // + if (!p_CopyOverwriteAcct) + { + sql = "INSERT INTO C_BP_Customer_Acct " + + "(C_BPartner_ID, C_AcctSchema_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " C_Receivable_Acct, C_Receivable_Services_Acct, C_PrePayment_Acct) " + + "SELECT p.C_BPartner_ID, acct.C_AcctSchema_ID," + + " p.AD_Client_ID, p.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0," + + " acct.C_Receivable_Acct, acct.C_Receivable_Services_Acct, acct.C_PrePayment_Acct " + + "FROM C_BPartner p" + + " INNER JOIN C_BP_Group_Acct acct ON (acct.C_BP_Group_ID=p.C_BP_Group_ID)" + + "WHERE acct.C_AcctSchema_ID=" + p_C_AcctSchema_ID // # + + " AND p.C_BP_Group_ID=acct.C_BP_Group_ID" + + " AND NOT EXISTS (SELECT * FROM C_BP_Customer_Acct ca " + + "WHERE ca.C_BPartner_ID=p.C_BPartner_ID" + + " AND ca.C_AcctSchema_ID=acct.C_AcctSchema_ID)"; + created = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(created), "@Created@ @C_BPartner_ID@ @IsCustomer@"); + createdTotal += created; + // + sql = "INSERT INTO C_BP_Vendor_Acct " + + "(C_BPartner_ID, C_AcctSchema_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " V_Liability_Acct, V_Liability_Services_Acct, V_PrePayment_Acct) " + + "SELECT p.C_BPartner_ID, acct.C_AcctSchema_ID," + + " p.AD_Client_ID, p.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0," + + " acct.V_Liability_Acct, acct.V_Liability_Services_Acct, acct.V_PrePayment_Acct " + + "FROM C_BPartner p" + + " INNER JOIN C_BP_Group_Acct acct ON (acct.C_BP_Group_ID=p.C_BP_Group_ID)" + + "WHERE acct.C_AcctSchema_ID=" + p_C_AcctSchema_ID // # + + " AND p.C_BP_Group_ID=acct.C_BP_Group_ID" + + " AND NOT EXISTS (SELECT * FROM C_BP_Vendor_Acct va " + + "WHERE va.C_BPartner_ID=p.C_BPartner_ID AND va.C_AcctSchema_ID=acct.C_AcctSchema_ID)"; + created = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(created), "@Created@ @C_BPartner_ID@ @IsVendor@"); + createdTotal += created; + } + + // Update Warehouse + if (p_CopyOverwriteAcct) + { + sql = "UPDATE M_Warehouse_Acct a " + + "SET W_Inventory_Acct=" + acct.getW_Inventory_Acct() + + ", W_Differences_Acct=" + acct.getW_Differences_Acct() + + ", W_Revaluation_Acct=" + acct.getW_Revaluation_Acct() + + ", W_InvActualAdjust_Acct=" + acct.getW_InvActualAdjust_Acct() + + ", Updated=SysDate, UpdatedBy=0 " + + "WHERE a.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND EXISTS (SELECT * FROM M_Warehouse_Acct x " + + "WHERE x.M_Warehouse_ID=a.M_Warehouse_ID)"; + updated = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(updated), "@Updated@ @M_Warehouse_ID@"); + updatedTotal += updated; + } + // Insert new Warehouse + sql = "INSERT INTO M_Warehouse_Acct " + + "(M_Warehouse_ID, C_AcctSchema_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " W_Inventory_Acct, W_Differences_Acct, W_Revaluation_Acct, W_InvActualAdjust_Acct) " + + "SELECT x.M_Warehouse_ID, acct.C_AcctSchema_ID," + + " x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0," + + " acct.W_Inventory_Acct, acct.W_Differences_Acct, acct.W_Revaluation_Acct, acct.W_InvActualAdjust_Acct " + + "FROM M_Warehouse x" + + " INNER JOIN C_AcctSchema_Default acct ON (x.AD_Client_ID=acct.AD_Client_ID) " + + "WHERE acct.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND NOT EXISTS (SELECT * FROM M_Warehouse_Acct a " + + "WHERE a.M_Warehouse_ID=x.M_Warehouse_ID" + + " AND a.C_AcctSchema_ID=acct.C_AcctSchema_ID)"; + created = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(created), "@Created@ @M_Warehouse_ID@"); + createdTotal += created; + + + // Update Project + if (p_CopyOverwriteAcct) + { + sql = "UPDATE C_Project_Acct a " + + "SET PJ_Asset_Acct=" + acct.getPJ_Asset_Acct() + + ", PJ_WIP_Acct=" + acct.getPJ_Asset_Acct() + + ", Updated=SysDate, UpdatedBy=0 " + + "WHERE a.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND EXISTS (SELECT * FROM C_Project_Acct x " + + "WHERE x.C_Project_ID=a.C_Project_ID)"; + updated = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(updated), "@Updated@ @C_Project_ID@"); + updatedTotal += updated; + } + // Insert new Projects + sql = "INSERT INTO C_Project_Acct " + + "(C_Project_ID, C_AcctSchema_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " PJ_Asset_Acct, PJ_WIP_Acct) " + + "SELECT x.C_Project_ID, acct.C_AcctSchema_ID," + + " x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0," + + " acct.PJ_Asset_Acct, acct.PJ_WIP_Acct " + + "FROM C_Project x" + + " INNER JOIN C_AcctSchema_Default acct ON (x.AD_Client_ID=acct.AD_Client_ID) " + + "WHERE acct.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND NOT EXISTS (SELECT * FROM C_Project_Acct a " + + "WHERE a.C_Project_ID=x.C_Project_ID" + + " AND a.C_AcctSchema_ID=acct.C_AcctSchema_ID)"; + created = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(created), "@Created@ @C_Project_ID@"); + createdTotal += created; + + + // Update Tax + if (p_CopyOverwriteAcct) + { + sql = "UPDATE C_Tax_Acct a " + + "SET T_Due_Acct=" + acct.getT_Due_Acct() + + ", T_Liability_Acct=" + acct.getT_Liability_Acct() + + ", T_Credit_Acct=" + acct.getT_Credit_Acct() + + ", T_Receivables_Acct=" + acct.getT_Receivables_Acct() + + ", T_Expense_Acct=" + acct.getT_Expense_Acct() + + ", Updated=SysDate, UpdatedBy=0 " + + "WHERE a.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND EXISTS (SELECT * FROM C_Tax_Acct x " + + "WHERE x.C_Tax_ID=a.C_Tax_ID)"; + updated = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(updated), "@Updated@ @C_Tax_ID@"); + updatedTotal += updated; + } + // Insert new Tax + sql = "INSERT INTO C_Tax_Acct " + + "(C_Tax_ID, C_AcctSchema_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " T_Due_Acct, T_Liability_Acct, T_Credit_Acct, T_Receivables_Acct, T_Expense_Acct) " + + "SELECT x.C_Tax_ID, acct.C_AcctSchema_ID," + + " x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0," + + " acct.T_Due_Acct, acct.T_Liability_Acct, acct.T_Credit_Acct, acct.T_Receivables_Acct, acct.T_Expense_Acct " + + "FROM C_Tax x" + + " INNER JOIN C_AcctSchema_Default acct ON (x.AD_Client_ID=acct.AD_Client_ID) " + + "WHERE acct.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND NOT EXISTS (SELECT * FROM C_Tax_Acct a " + + "WHERE a.C_Tax_ID=x.C_Tax_ID" + + " AND a.C_AcctSchema_ID=acct.C_AcctSchema_ID)"; + created = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(created), "@Created@ @C_Tax_ID@"); + createdTotal += created; + + + // Update BankAccount + if (p_CopyOverwriteAcct) + { + sql = "UPDATE C_BankAccount_Acct a " + + "SET B_InTransit_Acct=" + acct.getB_InTransit_Acct() + + ", B_Asset_Acct=" + acct.getB_Asset_Acct() + + ", B_Expense_Acct=" + acct.getB_Expense_Acct() + + ", B_InterestRev_Acct=" + acct.getB_InterestRev_Acct() + + ", B_InterestExp_Acct=" + acct.getB_InterestExp_Acct() + + ", B_Unidentified_Acct=" + acct.getB_Unidentified_Acct() + + ", B_UnallocatedCash_Acct=" + acct.getB_UnallocatedCash_Acct() + + ", B_PaymentSelect_Acct=" + acct.getB_PaymentSelect_Acct() + + ", B_SettlementGain_Acct=" + acct.getB_SettlementGain_Acct() + + ", B_SettlementLoss_Acct=" + acct.getB_SettlementLoss_Acct() + + ", B_RevaluationGain_Acct=" + acct.getB_RevaluationGain_Acct() + + ", B_RevaluationLoss_Acct=" + acct.getB_RevaluationLoss_Acct() + + ", Updated=SysDate, UpdatedBy=0 " + + "WHERE a.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND EXISTS (SELECT * FROM C_BankAccount_Acct x " + + "WHERE x.C_BankAccount_ID=a.C_BankAccount_ID)"; + updated = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(updated), "@Updated@ @C_BankAccount_ID@"); + updatedTotal += updated; + } + // Insert new BankAccount + sql = "INSERT INTO C_BankAccount_Acct " + + "(C_BankAccount_ID, C_AcctSchema_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " B_InTransit_Acct, B_Asset_Acct, B_Expense_Acct, B_InterestRev_Acct, B_InterestExp_Acct," + + " B_Unidentified_Acct, B_UnallocatedCash_Acct, B_PaymentSelect_Acct," + + " B_SettlementGain_Acct, B_SettlementLoss_Acct," + + " B_RevaluationGain_Acct, B_RevaluationLoss_Acct) " + + "SELECT x.C_BankAccount_ID, acct.C_AcctSchema_ID," + + " x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0," + + " acct.B_InTransit_Acct, acct.B_Asset_Acct, acct.B_Expense_Acct, acct.B_InterestRev_Acct, acct.B_InterestExp_Acct," + + " acct.B_Unidentified_Acct, acct.B_UnallocatedCash_Acct, acct.B_PaymentSelect_Acct," + + " acct.B_SettlementGain_Acct, acct.B_SettlementLoss_Acct," + + " acct.B_RevaluationGain_Acct, acct.B_RevaluationLoss_Acct " + + "FROM C_BankAccount x" + + " INNER JOIN C_AcctSchema_Default acct ON (x.AD_Client_ID=acct.AD_Client_ID) " + + "WHERE acct.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND NOT EXISTS (SELECT * FROM C_BankAccount_Acct a " + + "WHERE a.C_BankAccount_ID=x.C_BankAccount_ID" + + " AND a.C_AcctSchema_ID=acct.C_AcctSchema_ID)"; + created = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(created), "@Created@ @C_BankAccount_ID@"); + createdTotal += created; + + + // Update Withholding + if (p_CopyOverwriteAcct) + { + sql = "UPDATE C_Withholding_Acct a " + + "SET Withholding_Acct=" + acct.getWithholding_Acct() + + ", Updated=SysDate, UpdatedBy=0 " + + "WHERE a.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND EXISTS (SELECT * FROM C_Withholding_Acct x " + + "WHERE x.C_Withholding_ID=a.C_Withholding_ID)"; + updated = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(updated), "@Updated@ @C_Withholding_ID@"); + updatedTotal += updated; + } + // Insert new Withholding + sql = "INSERT INTO C_Withholding_Acct " + + "(C_Withholding_ID, C_AcctSchema_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " Withholding_Acct) " + + "SELECT x.C_Withholding_ID, acct.C_AcctSchema_ID," + + " x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0," + + " acct.Withholding_Acct " + + "FROM C_Withholding x" + + " INNER JOIN C_AcctSchema_Default acct ON (x.AD_Client_ID=acct.AD_Client_ID) " + + "WHERE acct.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND NOT EXISTS (SELECT * FROM C_Withholding_Acct a " + + "WHERE a.C_Withholding_ID=x.C_Withholding_ID" + + " AND a.C_AcctSchema_ID=acct.C_AcctSchema_ID)"; + created = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(created), "@Created@ @C_Withholding_ID@"); + createdTotal += created; + + + // Update Charge + if (p_CopyOverwriteAcct) + { + sql = "UPDATE C_Charge_Acct a " + + "SET Ch_Expense_Acct=" + acct.getCh_Expense_Acct() + + ", Ch_Revenue_Acct=" + acct.getCh_Revenue_Acct() + + ", Updated=SysDate, UpdatedBy=0 " + + "WHERE a.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND EXISTS (SELECT * FROM C_Charge_Acct x " + + "WHERE x.C_Charge_ID=a.C_Charge_ID)"; + updated = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(updated), "@Updated@ @C_Charge_ID@"); + updatedTotal += updated; + } + // Insert new Charge + sql = "INSERT INTO C_Charge_Acct " + + "(C_Charge_ID, C_AcctSchema_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " Ch_Expense_Acct, Ch_Revenue_Acct) " + + "SELECT x.C_Charge_ID, acct.C_AcctSchema_ID," + + " x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0," + + " acct.Ch_Expense_Acct, acct.Ch_Revenue_Acct " + + "FROM C_Charge x" + + " INNER JOIN C_AcctSchema_Default acct ON (x.AD_Client_ID=acct.AD_Client_ID) " + + "WHERE acct.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND NOT EXISTS (SELECT * FROM C_Charge_Acct a " + + "WHERE a.C_Charge_ID=x.C_Charge_ID" + + " AND a.C_AcctSchema_ID=acct.C_AcctSchema_ID)"; + created = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(created), "@Created@ @C_Charge_ID@"); + createdTotal += created; + + + // Update Cashbook + if (p_CopyOverwriteAcct) + { + sql = "UPDATE C_Cashbook_Acct a " + + "SET CB_Asset_Acct=" + acct.getCB_Asset_Acct() + + ", CB_Differences_Acct=" + acct.getCB_Differences_Acct() + + ", CB_CashTransfer_Acct=" + acct.getCB_CashTransfer_Acct() + + ", CB_Expense_Acct=" + acct.getCB_Expense_Acct() + + ", CB_Receipt_Acct=" + acct.getCB_Receipt_Acct() + + ", Updated=SysDate, UpdatedBy=0 " + + "WHERE a.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND EXISTS (SELECT * FROM C_Cashbook_Acct x " + + "WHERE x.C_Cashbook_ID=a.C_Cashbook_ID)"; + updated = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(updated), "@Updated@ @C_Cashbook_ID@"); + updatedTotal += updated; + } + // Insert new Cashbook + sql = "INSERT INTO C_Cashbook_Acct " + + "(C_Cashbook_ID, C_AcctSchema_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " CB_Asset_Acct, CB_Differences_Acct, CB_CashTransfer_Acct," + + " CB_Expense_Acct, CB_Receipt_Acct) " + + "SELECT x.C_Cashbook_ID, acct.C_AcctSchema_ID," + + " x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0," + + " acct.CB_Asset_Acct, acct.CB_Differences_Acct, acct.CB_CashTransfer_Acct," + + " acct.CB_Expense_Acct, acct.CB_Receipt_Acct " + + "FROM C_Cashbook x" + + " INNER JOIN C_AcctSchema_Default acct ON (x.AD_Client_ID=acct.AD_Client_ID) " + + "WHERE acct.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND NOT EXISTS (SELECT * FROM C_Cashbook_Acct a " + + "WHERE a.C_Cashbook_ID=x.C_Cashbook_ID" + + " AND a.C_AcctSchema_ID=acct.C_AcctSchema_ID)"; + created = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(created), "@Created@ @C_Cashbook_ID@"); + createdTotal += created; + + return "@Created@=" + createdTotal + ", @Updated@=" + updatedTotal; + } // doIt + +} // AcctSchemaDefaultCopy diff --git a/base/src/org/compiere/process/Aging.java b/base/src/org/compiere/process/Aging.java new file mode 100644 index 0000000000..7102b6d61b --- /dev/null +++ b/base/src/org/compiere/process/Aging.java @@ -0,0 +1,212 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Invoice Aging Report. + * Based on RV_Aging. + * @author Jorg Janke + * @version $Id: Aging.java,v 1.5 2006/10/07 00:58:44 jjanke Exp $ + */ +public class Aging extends SvrProcess +{ + /** The date to calculate the days due from */ + private Timestamp p_StatementDate = null; + private boolean p_IsSOTrx = false; + private int p_C_Currency_ID = 0; + private int p_C_BP_Group_ID = 0; + private int p_C_BPartner_ID = 0; + private boolean p_IsListInvoices = false; + /** Number of days between today and statement date */ + private int m_statementOffset = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("StatementDate")) + p_StatementDate = (Timestamp)para[i].getParameter(); + else if (name.equals("IsSOTrx")) + p_IsSOTrx = "Y".equals(para[i].getParameter()); + else if (name.equals("C_Currency_ID")) + p_C_Currency_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_BP_Group_ID")) + p_C_BP_Group_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("IsListInvoices")) + p_IsListInvoices = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + if (p_StatementDate == null) + p_StatementDate = new Timestamp (System.currentTimeMillis()); + else + m_statementOffset = TimeUtil.getDaysBetween( + new Timestamp(System.currentTimeMillis()), p_StatementDate); + } // prepare + + /** + * DoIt + * @return Message + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info("StatementDate=" + p_StatementDate + ", IsSOTrx=" + p_IsSOTrx + + ", C_Currency_ID=" + p_C_Currency_ID + + ", C_BP_Group_ID=" + p_C_BP_Group_ID + ", C_BPartner_ID=" + p_C_BPartner_ID + + ", IsListInvoices=" + p_IsListInvoices); + // + StringBuffer sql = new StringBuffer(); + sql.append("SELECT bp.C_BP_Group_ID, oi.C_BPartner_ID,oi.C_Invoice_ID,oi.C_InvoicePaySchedule_ID, " + + "oi.C_Currency_ID, oi.IsSOTrx, " // 5..6 + + "oi.DateInvoiced, oi.NetDays,oi.DueDate,oi.DaysDue, "); // 7..10 + if (p_C_Currency_ID == 0) + sql.append("oi.GrandTotal, oi.PaidAmt, oi.OpenAmt "); // 11..13 + else + { + String s = ",oi.C_Currency_ID," + p_C_Currency_ID + ",oi.DateAcct,oi.C_ConversionType_ID,oi.AD_Client_ID,oi.AD_Org_ID)"; + sql.append("currencyConvert(oi.GrandTotal").append(s) // 11.. + .append(", currencyConvert(oi.PaidAmt").append(s) + .append(", currencyConvert(oi.OpenAmt").append(s); + } + sql.append(",oi.C_Activity_ID,oi.C_Campaign_ID,oi.C_Project_ID " // 14 + + "FROM RV_OpenItem oi" + + " INNER JOIN C_BPartner bp ON (oi.C_BPartner_ID=bp.C_BPartner_ID) " + + "WHERE oi.ISSoTrx=").append(p_IsSOTrx ? "'Y'" : "'N'"); + if (p_C_BPartner_ID > 0) + sql.append(" AND oi.C_BPartner_ID=").append(p_C_BPartner_ID); + else if (p_C_BP_Group_ID > 0) + sql.append(" AND bp.C_BP_Group_ID=").append(p_C_BP_Group_ID); + sql.append(" ORDER BY oi.C_BPartner_ID, oi.C_Currency_ID, oi.C_Invoice_ID"); + + log.finest(sql.toString()); + String finalSql = MRole.getDefault(getCtx(), false).addAccessSQL( + sql.toString(), "oi", MRole.SQL_FULLYQUALIFIED, MRole.SQL_RO); + log.finer(finalSql); + + PreparedStatement pstmt = null; + // + MAging aging = null; + int counter = 0; + int rows = 0; + int AD_PInstance_ID = getAD_PInstance_ID(); + // + try + { + pstmt = DB.prepareStatement(finalSql, get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + int C_BP_Group_ID = rs.getInt(1); + int C_BPartner_ID = rs.getInt(2); + int C_Invoice_ID = p_IsListInvoices ? rs.getInt(3) : 0; + int C_InvoicePaySchedule_ID = p_IsListInvoices ? rs.getInt(4) : 0; + int C_Currency_ID = rs.getInt(5); + boolean IsSOTrx = "Y".equals(rs.getString(6)); + // + Timestamp DateInvoiced = rs.getTimestamp(7); + int NetDays = rs.getInt(8); + Timestamp DueDate = rs.getTimestamp(9); + // Days Due + int DaysDue = rs.getInt(10) // based on today + + m_statementOffset; + // + BigDecimal GrandTotal = rs.getBigDecimal(11); + BigDecimal PaidAmt = rs.getBigDecimal(12); + BigDecimal OpenAmt = rs.getBigDecimal(13); + // + int C_Activity_ID = p_IsListInvoices ? rs.getInt(14) : 0; + int C_Campaign_ID = p_IsListInvoices ? rs.getInt(15) : 0; + int C_Project_ID = p_IsListInvoices ? rs.getInt(16) : 0; + + rows++; + // New Aging Row + if (aging == null // Key + || AD_PInstance_ID != aging.getAD_PInstance_ID() + || C_BPartner_ID != aging.getC_BPartner_ID() + || C_Currency_ID != aging.getC_Currency_ID() + || C_Invoice_ID != aging.getC_Invoice_ID() + || C_InvoicePaySchedule_ID != aging.getC_InvoicePaySchedule_ID()) + { + if (aging != null) + { + if (aging.save()) + log.fine("#" + ++counter + " - " + aging); + else + { + log.log(Level.SEVERE, "Not saved " + aging); + break; + } + } + aging = new MAging (getCtx(), AD_PInstance_ID, p_StatementDate, + C_BPartner_ID, C_Currency_ID, + C_Invoice_ID, C_InvoicePaySchedule_ID, + C_BP_Group_ID, DueDate, IsSOTrx, get_TrxName()); + aging.setC_Activity_ID(C_Activity_ID); + aging.setC_Campaign_ID(C_Campaign_ID); + aging.setC_Project_ID(C_Project_ID); + } + // Fill Buckets + aging.add (DueDate, DaysDue, GrandTotal, OpenAmt); + } + if (aging != null) + { + if (aging.save()) + log.fine("#" + ++counter + " - " + aging); + else + log.log(Level.SEVERE, "Not saved " + aging); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, finalSql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + log.info("#" + counter + " - rows=" + rows); + return ""; + } // doIt + +} // Aging + diff --git a/base/src/org/compiere/process/AllocationAuto.java b/base/src/org/compiere/process/AllocationAuto.java new file mode 100644 index 0000000000..c0e1060c38 --- /dev/null +++ b/base/src/org/compiere/process/AllocationAuto.java @@ -0,0 +1,854 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Automatic Allocation Process + * + * @author Jorg Janke + * @version $Id: AllocationAuto.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class AllocationAuto extends SvrProcess +{ + /** BP Group */ + private int p_C_BP_Group_ID = 0; + /** BPartner */ + private int p_C_BPartner_ID = 0; + /** Allocate Oldest Setting */ + private boolean p_AllocateOldest = true; + /** Only AP/AR Transactions */ + private String p_APAR = "A"; + + private static String ONLY_AP = "P"; + private static String ONLY_AR = "R"; + + /** Payments */ + private MPayment[] m_payments = null; + /** Invoices */ + private MInvoice[] m_invoices = null; + /** Allocation */ + private MAllocationHdr m_allocation = null; + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_BP_Group_ID")) + p_C_BP_Group_ID = para[i].getParameterAsInt(); + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = para[i].getParameterAsInt(); + else if (name.equals("AllocateOldest")) + p_AllocateOldest = "Y".equals(para[i].getParameter()); + else if (name.equals("APAR")) + p_APAR = (String)para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info ("C_BP_Group_ID=" + p_C_BP_Group_ID + + ", C_BPartner_ID=" + p_C_BPartner_ID + + ", Oldest=" + p_AllocateOldest + + ", AP/AR=" + p_APAR); + int countBP = 0; + int countAlloc = 0; + if (p_C_BPartner_ID != 0) + { + countAlloc = allocateBP (p_C_BPartner_ID); + if (countAlloc > 0) + countBP++; + } + else if (p_C_BP_Group_ID != 0) + { + String sql = "SELECT C_BPartner_ID FROM C_BPartner WHERE C_BP_Group_ID=? ORDER BY Value"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, p_C_BP_Group_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + int C_BPartner_ID = rs.getInt(1); + int count = allocateBP (C_BPartner_ID); + if (count > 0) + { + countBP++; + countAlloc += count; + commit(); + } + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + } + else + { + String sql = "SELECT C_BPartner_ID FROM C_BPartner WHERE AD_Client_ID=? ORDER BY Value"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, Env.getAD_Client_ID(getCtx())); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + int C_BPartner_ID = rs.getInt(1); + int count = allocateBP (C_BPartner_ID); + if (count > 0) + { + countBP++; + countAlloc += count; + commit(); + } + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + } + // + return "@Created@ #" + countBP + "/" + countAlloc; + } // doIt + + /** + * Allocate BP + * @param C_BPartner_ID + * @return number of allocations + */ + private int allocateBP (int C_BPartner_ID) throws Exception + { + getPayments(C_BPartner_ID); + getInvoices(C_BPartner_ID); + log.info ("(1) - C_BPartner_ID=" + C_BPartner_ID + + " - #Payments=" + m_payments.length + ", #Invoices=" + m_invoices.length); + if (m_payments.length + m_invoices.length < 2) + return 0; + + // Payment Info - Invoice or Pay Selection + int count = allocateBPPaymentWithInfo(); + if (count != 0) + { + getPayments(C_BPartner_ID); // for next + getInvoices(C_BPartner_ID); + log.info ("(2) - C_BPartner_ID=" + C_BPartner_ID + + " - #Payments=" + m_payments.length + ", #Invoices=" + m_invoices.length); + if (m_payments.length + m_invoices.length < 2) + return count; + } + + // All + int newCount = allocateBPartnerAll(); + if (newCount != 0) + { + count += newCount; + getPayments(C_BPartner_ID); // for next + getInvoices(C_BPartner_ID); + processAllocation(); + log.info ("(3) - C_BPartner_ID=" + C_BPartner_ID + + " - #Payments=" + m_payments.length + ", #Invoices=" + m_invoices.length); + if (m_payments.length + m_invoices.length < 2) + return count; + } + + // One:One + newCount = allocateBPOneToOne(); + if (newCount != 0) + { + count += newCount; + getPayments(C_BPartner_ID); // for next + getInvoices(C_BPartner_ID); + processAllocation(); + log.info ("(4) - C_BPartner_ID=" + C_BPartner_ID + + " - #Payments=" + m_payments.length + ", #Invoices=" + m_invoices.length); + if (m_payments.length + m_invoices.length < 2) + return count; + } + + // Oldest First + if (p_AllocateOldest) + { + newCount = allocateBPOldestFirst(); + if (newCount != 0) + { + count += newCount; + getPayments(C_BPartner_ID); // for next + getInvoices(C_BPartner_ID); + processAllocation(); + log.info ("(5) - C_BPartner_ID=" + C_BPartner_ID + + " - #Payments=" + m_payments.length + ", #Invoices=" + m_invoices.length); + if (m_payments.length + m_invoices.length < 2) + return count; + } + } + + // Other, e.g. + // Allocation if "close" % and $ + + return count; + } // alloc + + /** + * Get Payments of BP + * @param C_BPartner_ID id + * @return unallocated payments + */ + private MPayment[] getPayments (int C_BPartner_ID) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_Payment " + + "WHERE IsAllocated='N' AND Processed='Y' AND C_BPartner_ID=?" + + " AND IsPrepayment='N' AND C_Charge_ID IS NULL "; + if (ONLY_AP.equals(p_APAR)) + sql += "AND IsReceipt='N' "; + else if (ONLY_AR.equals(p_APAR)) + sql += "AND IsReceipt='Y' "; + sql += "ORDER BY DateTrx"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, C_BPartner_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MPayment payment = new MPayment (getCtx(), rs, get_TrxName()); + BigDecimal allocated = payment.getAllocatedAmt(); + if (allocated != null && allocated.compareTo(payment.getPayAmt()) == 0) + { + payment.setIsAllocated(true); + payment.save(); + } + else + list.add (payment); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_payments = new MPayment[list.size ()]; + list.toArray (m_payments); + return m_payments; + } // getPayments + + /** + * Get Invoices of BP + * @param C_BPartner_ID id + * @return unallocated Invoices + */ + private MInvoice[] getInvoices (int C_BPartner_ID) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_Invoice " + + "WHERE IsPaid='N' AND Processed='Y' AND C_BPartner_ID=? "; + if (ONLY_AP.equals(p_APAR)) + sql += "AND IsSOTrx='N' "; + else if (ONLY_AR.equals(p_APAR)) + sql += "AND IsSOTrx='Y' "; + sql += "ORDER BY DateInvoiced";; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, C_BPartner_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MInvoice invoice = new MInvoice (getCtx(), rs, get_TrxName()); + if (invoice.getOpenAmt(false, null).signum() == 0) + { + invoice.setIsPaid(true); + invoice.save(); + } + else + list.add (invoice); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_invoices = new MInvoice[list.size ()]; + list.toArray (m_invoices); + return m_invoices; + } // getInvoices + + + /************************************************************************** + * Allocate Individual Payments with payment references + * @return number of allocations + */ + private int allocateBPPaymentWithInfo () + { + int count = 0; + + //**** See if there is a direct link (Invoice or Pay Selection) + for (int p = 0; p < m_payments.length; p++) + { + MPayment payment = m_payments[p]; + if (payment.isAllocated()) + continue; + BigDecimal allocatedAmt = payment.getAllocatedAmt(); + log.info(payment + ", Allocated=" + allocatedAmt); + if (allocatedAmt != null && allocatedAmt.signum() != 0) + continue; + BigDecimal availableAmt = payment.getPayAmt() + .add(payment.getDiscountAmt()) + .add(payment.getWriteOffAmt()) + .add(payment.getOverUnderAmt()); + if (!payment.isReceipt()) + availableAmt = availableAmt.negate(); + log.fine("Available=" + availableAmt); + // + if (payment.getC_Invoice_ID() != 0) + { + for (int i = 0; i < m_invoices.length; i++) + { + MInvoice invoice = m_invoices[i]; + if (invoice.isPaid()) + continue; + // log.fine("allocateIndividualPayments - " + invoice); + if (payment.getC_Invoice_ID() == invoice.getC_Invoice_ID()) + { + if (payment.getC_Currency_ID() == invoice.getC_Currency_ID()) + { + BigDecimal openAmt = invoice.getOpenAmt(true, null); + if (!invoice.isSOTrx()) + openAmt = openAmt.negate(); + log.fine(invoice + ", Open=" + openAmt); + // With Discount, etc. + if (availableAmt.compareTo(openAmt) == 0) + { + if (payment.allocateIt()) + { + addLog(0, payment.getDateAcct(), openAmt, payment.getDocumentNo() + " [1]"); + count++; + } + break; + } + } + else // Mixed Currency + { + } + } // invoice found + } // for all invoices + } // payment has invoice + else // No direct invoice + { + MPaySelectionCheck psCheck = MPaySelectionCheck.getOfPayment(getCtx(), payment.getC_Payment_ID(), get_TrxName()); + if (psCheck == null) + continue; + // + BigDecimal totalInvoice = Env.ZERO; + MPaySelectionLine[] psLines = psCheck.getPaySelectionLines(false); + for (int i = 0; i < psLines.length; i++) + { + MPaySelectionLine line = psLines[i]; + MInvoice invoice = line.getInvoice(); + if (payment.getC_Currency_ID() == invoice.getC_Currency_ID()) + { + BigDecimal invoiceAmt = invoice.getOpenAmt(true, null); + BigDecimal overUnder = line.getOpenAmt().subtract(line.getPayAmt()) + .subtract(line.getDiscountAmt()).subtract(line.getDifferenceAmt()); + invoiceAmt = invoiceAmt.subtract(line.getDiscountAmt()) + .subtract(line.getDifferenceAmt()).subtract(overUnder); + if (!invoice.isSOTrx()) + invoiceAmt = invoiceAmt.negate(); + log.fine(invoice + ", Invoice=" + invoiceAmt); + totalInvoice = totalInvoice.add(invoiceAmt); + } + else // Multi-Currency + { + } + } + if (availableAmt.compareTo(totalInvoice) == 0) + { + if (payment.allocateIt()) + { + addLog(0, payment.getDateAcct(), availableAmt, payment.getDocumentNo() + " [n]"); + count++; + } + } + } // No direct invoice + } + //**** See if there is a direct link + + return count; + } // allocateIndividualPayments + + + /** + * Allocate Payment:Invoice 1:1 + * @return allocations + */ + private int allocateBPOneToOne() throws Exception + { + int count = 0; + for (int p = 0; p < m_payments.length; p++) + { + MPayment payment = m_payments[p]; + if (payment.isAllocated()) + continue; + BigDecimal allocatedAmt = payment.getAllocatedAmt(); + log.info(payment + ", Allocated=" + allocatedAmt); + if (allocatedAmt != null && allocatedAmt.signum() != 0) + continue; + BigDecimal availableAmt = payment.getPayAmt() + .add(payment.getDiscountAmt()) + .add(payment.getWriteOffAmt()) + .add(payment.getOverUnderAmt()); + if (!payment.isReceipt()) + availableAmt = availableAmt.negate(); + log.fine("Available=" + availableAmt); + for (int i = 0; i < m_invoices.length; i++) + { + MInvoice invoice = m_invoices[i]; + if (invoice == null || invoice.isPaid()) + continue; + if (payment.getC_Currency_ID() == invoice.getC_Currency_ID()) + { + // log.fine("allocateBPartnerAll - " + invoice); + BigDecimal openAmt = invoice.getOpenAmt(true, null); + if (!invoice.isSOTrx()) + openAmt = openAmt.negate(); + BigDecimal difference = availableAmt.subtract(openAmt).abs(); + log.fine(invoice + ", Open=" + openAmt + " - Difference=" + difference); + if (difference.signum() == 0) + { + Timestamp dateAcct = payment.getDateAcct(); + if (invoice.getDateAcct().after(dateAcct)) + dateAcct = invoice.getDateAcct(); + if (!createAllocation(payment.getC_Currency_ID(), "1:1 (" + availableAmt + ")", + dateAcct, availableAmt, null, null, null, + invoice.getC_BPartner_ID(), payment.getC_Payment_ID(), + invoice.getC_Invoice_ID(), invoice.getAD_Org_ID())) + { + throw new AdempiereSystemError("Cannot create Allocation"); + } + processAllocation(); + count++; + m_invoices[i] = null; // remove invoice + m_payments[p] = null; + payment = null; + break; + } + } + else // Multi-Currency + { + } + } // for all invoices + } // for all payments + return count; + } // allocateOneToOne + + /** + * Allocate all Payments/Invoices using Accounting currency + * @return allocations + */ + private int allocateBPartnerAll() throws Exception + { + int C_Currency_ID = MClient.get(getCtx()).getC_Currency_ID(); + Timestamp dateAcct = null; + // Payments + BigDecimal totalPayments = Env.ZERO; + for (int p = 0; p < m_payments.length; p++) + { + MPayment payment = m_payments[p]; + if (payment.isAllocated()) + continue; + BigDecimal allocatedAmt = payment.getAllocatedAmt(); + // log.info("allocateBPartnerAll - " + payment + ", Allocated=" + allocatedAmt); + if (allocatedAmt != null && allocatedAmt.signum() != 0) + continue; + BigDecimal availableAmt = payment.getPayAmt() + .add(payment.getDiscountAmt()) + .add(payment.getWriteOffAmt()) + .add(payment.getOverUnderAmt()); + if (!payment.isReceipt()) + availableAmt = availableAmt.negate(); + // Foreign currency + if (payment.getC_Currency_ID() != C_Currency_ID) + continue; + // log.fine("allocateBPartnerAll - Available=" + availableAmt); + if (dateAcct == null || payment.getDateAcct().after(dateAcct)) + dateAcct = payment.getDateAcct(); + totalPayments = totalPayments.add(availableAmt); + } + // Invoices + BigDecimal totalInvoices = Env.ZERO; + for (int i = 0; i < m_invoices.length; i++) + { + MInvoice invoice = m_invoices[i]; + if (invoice.isPaid()) + continue; + // log.info("allocateBPartnerAll - " + invoice); + BigDecimal openAmt = invoice.getOpenAmt(true, null); + if (!invoice.isSOTrx()) + openAmt = openAmt.negate(); + // Foreign currency + if (invoice.getC_Currency_ID() != C_Currency_ID) + continue; + // log.fine("allocateBPartnerAll - Open=" + openAmt); + if (dateAcct == null || invoice.getDateAcct().after(dateAcct)) + dateAcct = invoice.getDateAcct(); + totalInvoices = totalInvoices.add(openAmt); + } + + BigDecimal difference = totalInvoices.subtract(totalPayments); + log.info("= Invoices=" + totalInvoices + + " - Payments=" + totalPayments + + " = Difference=" + difference); + + if (difference.signum() == 0) + { + for (int p = 0; p < m_payments.length; p++) + { + MPayment payment = m_payments[p]; + if (payment.isAllocated()) + continue; + BigDecimal allocatedAmt = payment.getAllocatedAmt(); + if (allocatedAmt != null && allocatedAmt.signum() != 0) + continue; + BigDecimal availableAmt = payment.getPayAmt() + .add(payment.getDiscountAmt()) + .add(payment.getWriteOffAmt()) + .add(payment.getOverUnderAmt()); + if (!payment.isReceipt()) + availableAmt = availableAmt.negate(); + // Foreign currency + if (payment.getC_Currency_ID() != C_Currency_ID) + continue; + if (!createAllocation(C_Currency_ID, "BP All", + dateAcct, availableAmt, null, null, null, + payment.getC_BPartner_ID(), payment.getC_Payment_ID(), 0, payment.getAD_Org_ID())) + { + throw new AdempiereSystemError("Cannot create Allocation"); + } + } // for all payments + // + for (int i = 0; i < m_invoices.length; i++) + { + MInvoice invoice = m_invoices[i]; + if (invoice.isPaid()) + continue; + BigDecimal openAmt = invoice.getOpenAmt(true, null); + if (!invoice.isSOTrx()) + openAmt = openAmt.negate(); + // Foreign currency + if (invoice.getC_Currency_ID() != C_Currency_ID) + continue; + if (!createAllocation(C_Currency_ID, "BP All", + dateAcct, openAmt, null, null, null, + invoice.getC_BPartner_ID(), 0, invoice.getC_Invoice_ID(), invoice.getAD_Org_ID())) + { + throw new AdempiereSystemError("Cannot create Allocation"); + } + } // for all invoices + processAllocation(); + return 1; + } // Difference OK + + return 0; + } // allocateBPartnerAll + + + /** + * Allocate Oldest First using Accounting currency + * @return allocations + */ + private int allocateBPOldestFirst() throws Exception + { + int C_Currency_ID = MClient.get(getCtx()).getC_Currency_ID(); + Timestamp dateAcct = null; + // Payments + BigDecimal totalPayments = Env.ZERO; + for (int p = 0; p < m_payments.length; p++) + { + MPayment payment = m_payments[p]; + if (payment.isAllocated()) + continue; + if (payment.getC_Currency_ID() != C_Currency_ID) + continue; + BigDecimal allocatedAmt = payment.getAllocatedAmt(); + log.info(payment + ", Allocated=" + allocatedAmt); + BigDecimal availableAmt = payment.getPayAmt() + .add(payment.getDiscountAmt()) + .add(payment.getWriteOffAmt()) + .add(payment.getOverUnderAmt()); + if (!payment.isReceipt()) + availableAmt = availableAmt.negate(); + log.fine("Available=" + availableAmt); + if (dateAcct == null || payment.getDateAcct().after(dateAcct)) + dateAcct = payment.getDateAcct(); + totalPayments = totalPayments.add(availableAmt); + } + // Invoices + BigDecimal totalInvoices = Env.ZERO; + for (int i = 0; i < m_invoices.length; i++) + { + MInvoice invoice = m_invoices[i]; + if (invoice.isPaid()) + continue; + if (invoice.getC_Currency_ID() != C_Currency_ID) + continue; + BigDecimal openAmt = invoice.getOpenAmt(true, null); + log.fine("" + invoice); + if (!invoice.isSOTrx()) + openAmt = openAmt.negate(); + // Foreign currency + log.fine("Open=" + openAmt); + if (dateAcct == null || invoice.getDateAcct().after(dateAcct)) + dateAcct = invoice.getDateAcct(); + totalInvoices = totalInvoices.add(openAmt); + } + + // must be either AP or AR balance + if (totalInvoices.signum() != totalPayments.signum()) + { + log.fine("Signum - Invoices=" + totalInvoices.signum() + + " <> Payments=" + totalPayments.signum()); + return 0; + } + + BigDecimal difference = totalInvoices.subtract(totalPayments); + BigDecimal maxAmt = totalInvoices.abs().min(totalPayments.abs()); + if (totalInvoices.signum() < 0) + maxAmt = maxAmt.negate(); + log.info("= Invoices=" + totalInvoices + + " - Payments=" + totalPayments + + " = Difference=" + difference + " - Max=" + maxAmt); + + + // Allocate Payments up to max + BigDecimal allocatedPayments = Env.ZERO; + for (int p = 0; p < m_payments.length; p++) + { + MPayment payment = m_payments[p]; + if (payment.isAllocated()) + continue; + if (payment.getC_Currency_ID() != C_Currency_ID) + continue; + BigDecimal allocatedAmt = payment.getAllocatedAmt(); + if (allocatedAmt != null && allocatedAmt.signum() != 0) + continue; + BigDecimal availableAmt = payment.getPayAmt() + .add(payment.getDiscountAmt()) + .add(payment.getWriteOffAmt()) + .add(payment.getOverUnderAmt()); + if (!payment.isReceipt()) + availableAmt = availableAmt.negate(); + allocatedPayments = allocatedPayments.add(availableAmt); + if ((totalInvoices.signum() > 0 && allocatedPayments.compareTo(maxAmt) > 0) + || (totalInvoices.signum() < 0 && allocatedPayments.compareTo(maxAmt) < 0)) + { + BigDecimal diff = allocatedPayments.subtract(maxAmt); + availableAmt = availableAmt.subtract(diff); + allocatedPayments = allocatedPayments.subtract(diff); + } + log.fine("Payment Allocated=" + availableAmt); + if (!createAllocation(C_Currency_ID, "BP Oldest (" + difference.abs() + ")", + dateAcct, availableAmt, null, null, null, + payment.getC_BPartner_ID(), payment.getC_Payment_ID(), 0, payment.getAD_Org_ID())) + { + throw new AdempiereSystemError("Cannot create Allocation"); + } + if (allocatedPayments.compareTo(maxAmt) == 0) + break; + } // for all payments + // Allocated Invoices up to max + BigDecimal allocatedInvoices = Env.ZERO; + for (int i = 0; i < m_invoices.length; i++) + { + MInvoice invoice = m_invoices[i]; + if (invoice.isPaid()) + continue; + if (invoice.getC_Currency_ID() != C_Currency_ID) + continue; + BigDecimal openAmt = invoice.getOpenAmt(true, null); + if (!invoice.isSOTrx()) + openAmt = openAmt.negate(); + allocatedInvoices = allocatedInvoices.add(openAmt); + if ((totalInvoices.signum() > 0 && allocatedInvoices.compareTo(maxAmt) > 0) + || (totalInvoices.signum() < 0 && allocatedInvoices.compareTo(maxAmt) < 0)) + { + BigDecimal diff = allocatedInvoices.subtract(maxAmt); + openAmt = openAmt.subtract(diff); + allocatedInvoices = allocatedInvoices.subtract(diff); + } + if (openAmt.signum() == 0) + break; + log.fine("Invoice Allocated=" + openAmt); + if (!createAllocation(C_Currency_ID, "BP Oldest (" + difference.abs() + ")", + dateAcct, openAmt, null, null, null, + invoice.getC_BPartner_ID(), 0, invoice.getC_Invoice_ID(), invoice.getAD_Org_ID())) + { + throw new AdempiereSystemError("Cannot create Allocation"); + } + if (allocatedInvoices.compareTo(maxAmt) == 0) + break; + } // for all invoices + + if (allocatedPayments.compareTo(allocatedInvoices) != 0) + { + throw new AdempiereSystemError("Allocated Payments=" + allocatedPayments + + " <> Invoices=" + allocatedInvoices); + } + processAllocation(); + return 1; + } // allocateOldestFirst + + + + /********************************************************************************************** + * Create Allocation allocation + * @param C_Currency_ID currency + * @param description decription + * @param Amount amount + * @param DiscountAmt discount + * @param WriteOffAmt write off + * @param OverUnderAmt over under + * @param C_BPartner_ID partner + * @param C_Payment_ID payment + * @param C_Invoice_ID invoice + * @return true if created + */ + private boolean createAllocation (int C_Currency_ID, String description, + Timestamp dateAcct, BigDecimal Amount, + BigDecimal DiscountAmt, BigDecimal WriteOffAmt, BigDecimal OverUnderAmt, + int C_BPartner_ID, int C_Payment_ID, int C_Invoice_ID, int AD_Org_ID) + { + // Process old Allocation + if (m_allocation != null + && m_allocation.getC_Currency_ID() != C_Currency_ID) + processAllocation(); + + // New Allocation + if (m_allocation == null) + { + m_allocation = new MAllocationHdr (getCtx(), false, dateAcct, // automatic + C_Currency_ID, "Auto " + description, get_TrxName()); + m_allocation.setAD_Org_ID(AD_Org_ID); + if (!m_allocation.save()) + return false; + } + + // New Allocation Line + MAllocationLine aLine = new MAllocationLine (m_allocation, Amount, + DiscountAmt, WriteOffAmt, OverUnderAmt); + aLine.setC_BPartner_ID(C_BPartner_ID); + aLine.setC_Payment_ID(C_Payment_ID); + aLine.setC_Invoice_ID(C_Invoice_ID); + return aLine.save(); + } // createAllocation + + /** + * Process Allocation + * @return true if processes/saved or none + */ + private boolean processAllocation() + { + if (m_allocation == null) + return true; + boolean success = m_allocation.processIt(MAllocationHdr.DOCACTION_Complete); + if (success) + success = m_allocation.save(); + else + m_allocation.save(); + addLog(0, m_allocation.getDateAcct(), null, m_allocation.getDescription()); + m_allocation = null; + return success; + } // processAllocation + +} // AllocationAuto diff --git a/base/src/org/compiere/process/AllocationReset.java b/base/src/org/compiere/process/AllocationReset.java new file mode 100644 index 0000000000..3992124bf2 --- /dev/null +++ b/base/src/org/compiere/process/AllocationReset.java @@ -0,0 +1,200 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Reset (delete) Allocations + * + * @author Jorg Janke + * @version $Id: AllocationReset.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class AllocationReset extends SvrProcess +{ + /** BP Group */ + private int p_C_BP_Group_ID = 0; + /** BPartner */ + private int p_C_BPartner_ID = 0; + /** Date Acct From */ + private Timestamp p_DateAcct_From = null; + /** Date Acct To */ + private Timestamp p_DateAcct_To = null; + /** Allocation directly */ + private int p_C_AllocationHdr_ID = 0; + /** Transaction */ + private Trx m_trx = null; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + log.fine("prepare - " + para[i]); + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_BP_Group_ID")) + p_C_BP_Group_ID = para[i].getParameterAsInt(); + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = para[i].getParameterAsInt(); + else if (name.equals("C_AllocationHdr_ID")) + p_C_AllocationHdr_ID = para[i].getParameterAsInt(); + else if (name.equals("DateAcct")) + { + p_DateAcct_From = (Timestamp)para[i].getParameter(); + p_DateAcct_To = (Timestamp)para[i].getParameter_To(); + } + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info ("C_BP_Group_ID=" + p_C_BP_Group_ID + ", C_BPartner_ID=" + p_C_BPartner_ID + + ", DateAcct= " + p_DateAcct_From + " - " + p_DateAcct_To + + ", C_AllocationHdr_ID=" + p_C_AllocationHdr_ID); + + m_trx = Trx.get(Trx.createTrxName("AllocReset"), true); + int count = 0; + + if (p_C_AllocationHdr_ID != 0) + { + MAllocationHdr hdr = new MAllocationHdr(getCtx(), p_C_AllocationHdr_ID, m_trx.getTrxName()); + if (delete(hdr)) + count++; + m_trx.close(); + return "@Deleted@ #" + count; + } + + // Selection + StringBuffer sql = new StringBuffer("SELECT * FROM C_AllocationHdr ah " + + "WHERE EXISTS (SELECT * FROM C_AllocationLine al " + + "WHERE ah.C_AllocationHdr_ID=al.C_AllocationHdr_ID"); + if (p_C_BPartner_ID != 0) + sql.append(" AND al.C_BPartner_ID=?"); + else if (p_C_BP_Group_ID != 0) + sql.append(" AND EXISTS (SELECT * FROM C_BPartner bp " + + "WHERE bp.C_BPartner_ID=al.C_BPartner_ID AND bp.C_BP_Group_ID=?)"); + else + sql.append(" AND AD_Client_ID=?"); + if (p_DateAcct_From != null) + sql.append(" AND TRIM(ah.DateAcct) >= ?"); + if (p_DateAcct_To != null) + sql.append(" AND TRIM(ah.DateAcct) <= ?"); + // Do not delete Cash Trx + sql.append(" AND al.C_CashLine_ID IS NULL)"); + // Open Period + sql.append(" AND EXISTS (SELECT * FROM C_Period p" + + " INNER JOIN C_PeriodControl pc ON (p.C_Period_ID=pc.C_Period_ID AND pc.DocBaseType='CMA') " + + "WHERE ah.DateAcct BETWEEN p.StartDate AND p.EndDate)"); + // + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql.toString(), m_trx.getTrxName()); + int index = 1; + if (p_C_BPartner_ID != 0) + pstmt.setInt(index++, p_C_BPartner_ID); + else if (p_C_BP_Group_ID != 0) + pstmt.setInt(index++, p_C_BP_Group_ID); + else + pstmt.setInt(index++, Env.getAD_Client_ID(getCtx())); + if (p_DateAcct_From != null) + pstmt.setTimestamp(index++, p_DateAcct_From); + if (p_DateAcct_To != null) + pstmt.setTimestamp(index++, p_DateAcct_To); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MAllocationHdr hdr = new MAllocationHdr(getCtx(), rs, m_trx.getTrxName()); + if (delete(hdr)) + count++; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql.toString(), e); + m_trx.rollback(); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_trx.close(); + return "@Deleted@ #" + count; + } // doIt + + + private boolean delete(MAllocationHdr hdr) + { + // m_trx.start(); + boolean success = false; + if (hdr.delete(true, m_trx.getTrxName())) + { + log.fine(hdr.toString()); + success = true; + } + if (success) + m_trx.commit(); + else + m_trx.rollback(); + return success; + } // delete + + + /** + * Set BPartner (may not be required + */ + private void setBPartner() + { + /** + UPDATE C_AllocationLine al + SET C_BPartner_ID=(SELECT C_BPartner_ID FROM C_Payment p WHERE al.C_Payment_ID=p.C_Payment_ID) + WHERE C_BPartner_ID IS NULL AND C_Payment_ID IS NOT NULL; + UPDATE C_AllocationLine al + SET C_BPartner_ID=(SELECT C_BPartner_ID FROM C_Invoice i WHERE al.C_Invoice_ID=i.C_Invoice_ID) + WHERE C_BPartner_ID IS NULL AND C_Invoice_ID IS NOT NULL; + UPDATE C_AllocationLine al + SET C_BPartner_ID=(SELECT C_BPartner_ID FROM C_Order o WHERE al.C_Order_ID=o.C_Order_ID) + WHERE C_BPartner_ID IS NULL AND C_Order_ID IS NOT NULL; + COMMIT + **/ + } // setBPartner + +} // AllocationReset diff --git a/base/src/org/compiere/process/AssetDelivery.java b/base/src/org/compiere/process/AssetDelivery.java new file mode 100644 index 0000000000..c49cf33b26 --- /dev/null +++ b/base/src/org/compiere/process/AssetDelivery.java @@ -0,0 +1,296 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.net.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Deliver Assets Electronically + * + * @author Jorg Janke + * @version $Id: AssetDelivery.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class AssetDelivery extends SvrProcess +{ + private MClient m_client = null; + + private int m_A_Asset_Group_ID = 0; + private int m_M_Product_ID = 0; + private int m_C_BPartner_ID = 0; + private int m_A_Asset_ID = 0; + private Timestamp m_GuaranteeDate = null; + private int m_NoGuarantee_MailText_ID = 0; + private boolean m_AttachAsset = false; + // + private MMailText m_MailText = null; + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("A_Asset_Group_ID")) + m_A_Asset_Group_ID = para[i].getParameterAsInt(); + else if (name.equals("M_Product_ID")) + m_M_Product_ID = para[i].getParameterAsInt(); + else if (name.equals("C_BPartner_ID")) + m_C_BPartner_ID = para[i].getParameterAsInt(); + else if (name.equals("A_Asset_ID")) + m_A_Asset_ID = para[i].getParameterAsInt(); + else if (name.equals("GuaranteeDate")) + m_GuaranteeDate = (Timestamp)para[i].getParameter(); + else if (name.equals("NoGuarantee_MailText_ID")) + m_NoGuarantee_MailText_ID = para[i].getParameterAsInt(); + else if (name.equals("AttachAsset")) + m_AttachAsset = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + if (m_GuaranteeDate == null) + m_GuaranteeDate = new Timestamp (System.currentTimeMillis()); + // + m_client = MClient.get(getCtx()); + } // prepare + + /** + * Perrform process. + * @return Message to be translated + * @throws Exception + */ + protected String doIt() throws java.lang.Exception + { + log.info(""); + long start = System.currentTimeMillis(); + + // Test + if (m_client.getSMTPHost() == null) + throw new Exception ("No Client SMTP Info"); + if (m_client.getRequestEMail() == null) + throw new Exception ("No Client Request User"); + + // Asset selected + if (m_A_Asset_ID != 0) + { + String msg = deliverIt (m_A_Asset_ID); + addLog (m_A_Asset_ID, null, null, msg); + return msg; + } + // + StringBuffer sql = new StringBuffer ("SELECT A_Asset_ID, GuaranteeDate " + + "FROM A_Asset a" + + " INNER JOIN M_Product p ON (a.M_Product_ID=p.M_Product_ID) " + + "WHERE "); + if (m_A_Asset_Group_ID != 0) + sql.append("a.A_Asset_Group_ID=").append(m_A_Asset_Group_ID).append(" AND "); + if (m_M_Product_ID != 0) + sql.append("p.M_Product_ID=").append(m_M_Product_ID).append(" AND "); + if (m_C_BPartner_ID != 0) + sql.append("a.C_BPartner_ID=").append(m_C_BPartner_ID).append(" AND "); + String s = sql.toString(); + if (s.endsWith(" WHERE ")) + throw new Exception ("@RestrictSelection@"); + // No mail to expired + if (m_NoGuarantee_MailText_ID == 0) + { + sql.append("TRUNC(GuaranteeDate) >= ").append(DB.TO_DATE(m_GuaranteeDate, true)); + s = sql.toString(); + } + // Clean up + if (s.endsWith(" AND ")) + s = sql.substring(0, sql.length()-5); + // + Statement stmt = null; + int count = 0; + int errors = 0; + int reminders = 0; + try + { + stmt = DB.createStatement(); + ResultSet rs = stmt.executeQuery(s); + while (rs.next()) + { + int A_Asset_ID = rs.getInt(1); + Timestamp GuaranteeDate = rs.getTimestamp(2); + + // Guarantee Expired + if (GuaranteeDate != null && GuaranteeDate.before(m_GuaranteeDate)) + { + if (m_NoGuarantee_MailText_ID != 0) + { + sendNoGuaranteeMail (A_Asset_ID, m_NoGuarantee_MailText_ID, get_TrxName()); + reminders++; + } + } + else // Guarantee valid + { + String msg = deliverIt (A_Asset_ID); + addLog (A_Asset_ID, null, null, msg); + if (msg.startsWith ("** ")) + errors++; + else + count++; + } + } + rs.close(); + stmt.close(); + stmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, s, e); + } + finally + { + try + { + if (stmt != null) + stmt.close (); + } + catch (Exception e) + {} + stmt = null; + } + log.info("Count=" + count + ", Errors=" + errors + ", Reminder=" + reminders + + " - " + (System.currentTimeMillis()-start) + "ms"); + return "@Sent@=" + count + " - @Errors@=" + errors; + } // doIt + + + /** + * Send No Guarantee EMail + * @param A_Asset_ID asset + * @param R_MailText_ID mail to send + * @return message - delivery errors start with ** + */ + private String sendNoGuaranteeMail (int A_Asset_ID, int R_MailText_ID, String trxName) + { + MAsset asset = new MAsset (getCtx(), A_Asset_ID, trxName); + if (asset.getAD_User_ID() == 0) + return "** No Asset User"; + MUser user = new MUser (getCtx(), asset.getAD_User_ID(), get_TrxName()); + if (user.getEMail() == null || user.getEMail().length() == 0) + return "** No Asset User Email"; + if (m_MailText == null || m_MailText.getR_MailText_ID() != R_MailText_ID) + m_MailText = new MMailText (getCtx(), R_MailText_ID, get_TrxName()); + if (m_MailText.getMailHeader() == null || m_MailText.getMailHeader().length() == 0) + return "** No Subject"; + + // Create Mail + EMail email = m_client.createEMail(user.getEMail(), null, null); + m_MailText.setPO(user); + m_MailText.setPO(asset); + String message = m_MailText.getMailText(true); + if (m_MailText.isHtml()) + email.setMessageHTML(m_MailText.getMailHeader(), message); + else + { + email.setSubject (m_MailText.getMailHeader()); + email.setMessageText (message); + } + String msg = email.send(); + new MUserMail(m_MailText, asset.getAD_User_ID(), email).save(); + if (!EMail.SENT_OK.equals(msg)) + return "** Not delivered: " + user.getEMail() + " - " + msg; + // + return user.getEMail(); + } // sendNoGuaranteeMail + + + /************************************************************************** + * Deliver Asset + * @param A_Asset_ID asset + * @return message - delivery errors start with ** + */ + private String deliverIt (int A_Asset_ID) + { + log.fine("A_Asset_ID=" + A_Asset_ID); + long start = System.currentTimeMillis(); + // + MAsset asset = new MAsset (getCtx(), A_Asset_ID, get_TrxName()); + if (asset.getAD_User_ID() == 0) + return "** No Asset User"; + MUser user = new MUser (getCtx(), asset.getAD_User_ID(), get_TrxName()); + if (user.getEMail() == null || user.getEMail().length() == 0) + return "** No Asset User Email"; + if (asset.getProductR_MailText_ID() == 0) + return "** Product Mail Text"; + if (m_MailText == null || m_MailText.getR_MailText_ID() != asset.getProductR_MailText_ID()) + m_MailText = new MMailText (getCtx(), asset.getProductR_MailText_ID(), get_TrxName()); + if (m_MailText.getMailHeader() == null || m_MailText.getMailHeader().length() == 0) + return "** No Subject"; + + // Create Mail + EMail email = m_client.createEMail(user.getEMail(), null, null); + if (!email.isValid()) + { + asset.setHelp(asset.getHelp() + " - Invalid EMail"); + asset.setIsActive(false); + return "** Invalid EMail: " + user.getEMail(); + } + if (m_client.isSmtpAuthorization()) + email.createAuthenticator(m_client.getRequestUser(), m_client.getRequestUserPW()); + m_MailText.setUser(user); + m_MailText.setPO(asset); + String message = m_MailText.getMailText(true); + if (m_MailText.isHtml() || m_AttachAsset) + email.setMessageHTML(m_MailText.getMailHeader(), message); + else + { + email.setSubject (m_MailText.getMailHeader()); + email.setMessageText (message); + } + if (m_AttachAsset) + { + MProductDownload[] pdls = asset.getProductDownloads(); + if (pdls != null) + { + for (int i = 0; i < pdls.length; i++) + { + URL url = pdls[i].getDownloadURL(m_client.getDocumentDir()); + if (url != null) + email.addAttachment(url); + } + } + else + log.warning("No DowloadURL for A_Asset_ID=" + A_Asset_ID); + } + String msg = email.send(); + new MUserMail(m_MailText, asset.getAD_User_ID(), email).save(); + if (!EMail.SENT_OK.equals(msg)) + return "** Not delivered: " + user.getEMail() + " - " + msg; + + MAssetDelivery ad = asset.confirmDelivery(email, user.getAD_User_ID()); + ad.save(); + asset.save(); + // + log.fine((System.currentTimeMillis()-start) + " ms"); + // success + return user.getEMail() + " - " + asset.getProductVersionNo(); + } // deliverIt + +} // AssetDelivery diff --git a/base/src/org/compiere/process/BOMValidate.java b/base/src/org/compiere/process/BOMValidate.java new file mode 100644 index 0000000000..40e5c9a16c --- /dev/null +++ b/base/src/org/compiere/process/BOMValidate.java @@ -0,0 +1,260 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Validate BOM + * + * @author Jorg Janke + * @version $Id: BOMValidate.java,v 1.3 2006/07/30 00:51:01 jjanke Exp $ + */ +public class BOMValidate extends SvrProcess +{ + /** The Product */ + private int p_M_Product_ID = 0; + /** Product Category */ + private int p_M_Product_Category_ID = 0; + /** Re-Validate */ + private boolean p_IsReValidate = false; + + /** Product */ + private MProduct m_product = null; + /** List of Products */ + private ArrayList m_products = null; + + /** + * Prepare + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("M_Product_Category_ID")) + p_M_Product_Category_ID = para[i].getParameterAsInt(); + else if (name.equals("IsReValidate")) + p_IsReValidate = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_M_Product_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return Info + * @throws Exception + */ + protected String doIt() throws Exception + { + if (p_M_Product_ID != 0) + { + log.info("M_Product_ID=" + p_M_Product_ID); + return validateProduct(new MProduct(getCtx(), p_M_Product_ID, get_TrxName())); + } + log.info("M_Product_Category_ID=" + p_M_Product_Category_ID + + ", IsReValidate=" + p_IsReValidate); + // + int counter = 0; + PreparedStatement pstmt = null; + String sql = "SELECT * FROM M_Product " + + "WHERE IsBOM='Y' AND "; + if (p_M_Product_Category_ID == 0) + sql += "AD_Client_ID=? "; + else + sql += "M_Product_Category_ID=? "; + if (!p_IsReValidate) + sql += "AND IsVerified<>'Y' "; + sql += "ORDER BY Name"; + int AD_Client_ID = Env.getAD_Client_ID(getCtx()); + try + { + pstmt = DB.prepareStatement (sql, null); + if (p_M_Product_Category_ID == 0) + pstmt.setInt (1, AD_Client_ID); + else + pstmt.setInt(1, p_M_Product_Category_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + String info = validateProduct(new MProduct(getCtx(), p_M_Product_ID, get_TrxName())); + addLog(0, null, null, info); + counter++; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return "#" + counter; + } // doIt + + + + /** + * Validate Product + * @param product product + * @return Info + */ + private String validateProduct (MProduct product) + { + if (!product.isBOM()) + return product.getName() + " @NotValid@ @M_BOM_ID@"; + m_product = product; + + // Check Old Product BOM Structure + log.config(m_product.getName()); + m_products = new ArrayList(); + if (!validateOldProduct (m_product)) + { + m_product.setIsVerified(false); + m_product.save(); + return m_product.getName() + " @NotValid@"; + } + + // New Structure + MBOM[] boms = MBOM.getOfProduct(getCtx(), p_M_Product_ID, get_TrxName(), null); + for (int i = 0; i < boms.length; i++) + { + m_products = new ArrayList(); + if (!validateBOM(boms[i])) + { + m_product.setIsVerified(false); + m_product.save(); + return m_product.getName() + " " + boms[i].getName() + " @NotValid@"; + } + } + + // OK + m_product.setIsVerified(true); + m_product.save(); + return m_product.getName() + " @IsValid@"; + } // validateProduct + + + /** + * Validate Old BOM Product structure + * @param product product + * @return true if valid + */ + private boolean validateOldProduct (MProduct product) + { + if (!product.isBOM()) + return true; + // + if (m_products.contains(product)) + { + log.warning (m_product.getName() + " recursively includes " + product.getName()); + return false; + } + m_products.add(product); + log.fine(product.getName()); + // + MProductBOM[] productsBOMs = MProductBOM.getBOMLines(product); + for (int i = 0; i < productsBOMs.length; i++) + { + MProductBOM productsBOM = productsBOMs[i]; + MProduct pp = new MProduct(getCtx(), productsBOM.getM_ProductBOM_ID(), get_TrxName()); + if (!pp.isBOM()) + log.finer(pp.getName()); + else if (!validateOldProduct(pp)) + return false; + } + return true; + } // validateOldProduct + + /** + * Validate BOM + * @param bom bom + * @return true if valid + */ + private boolean validateBOM (MBOM bom) + { + MBOMProduct[] BOMproducts = MBOMProduct.getOfBOM(bom); + for (int i = 0; i < BOMproducts.length; i++) + { + MBOMProduct BOMproduct = BOMproducts[i]; + MProduct pp = new MProduct(getCtx(), BOMproduct.getM_BOMProduct_ID(), get_TrxName()); + if (pp.isBOM()) + return validateProduct(pp, bom.getBOMType(), bom.getBOMUse()); + } + return true; + } // validateBOM + + /** + * Validate Product + * @param product product + * @param BOMType type + * @param BOMUse use + * @return true if valid + */ + private boolean validateProduct (MProduct product, String BOMType, String BOMUse) + { + if (!product.isBOM()) + return true; + // + String restriction = "BOMType='" + BOMType + "' AND BOMUse='" + BOMUse + "'"; + MBOM[] boms = MBOM.getOfProduct(getCtx(), p_M_Product_ID, get_TrxName(), + restriction); + if (boms.length != 1) + { + log.warning(restriction + " - Length=" + boms.length); + return false; + } + if (m_products.contains(product)) + { + log.warning (m_product.getName() + " recursively includes " + product.getName()); + return false; + } + m_products.add(product); + log.fine(product.getName()); + // + MBOM bom = boms[0]; + MBOMProduct[] BOMproducts = MBOMProduct.getOfBOM(bom); + for (int i = 0; i < BOMproducts.length; i++) + { + MBOMProduct BOMproduct = BOMproducts[i]; + MProduct pp = new MProduct(getCtx(), BOMproduct.getM_BOMProduct_ID(), get_TrxName()); + if (pp.isBOM()) + return validateProduct(pp, bom.getBOMType(), bom.getBOMUse()); + } + return true; + } // validateProduct + +} // BOMValidate diff --git a/base/src/org/compiere/process/BPGroupAcctCopy.java b/base/src/org/compiere/process/BPGroupAcctCopy.java new file mode 100644 index 0000000000..e4665f79bc --- /dev/null +++ b/base/src/org/compiere/process/BPGroupAcctCopy.java @@ -0,0 +1,152 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Copy BP Group default Accounts + * + * @author Jorg Janke + * @version $Id: BPGroupAcctCopy.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class BPGroupAcctCopy extends SvrProcess +{ + /** BP Group */ + private int p_C_BP_Group_ID = 0; + /** Acct Schema */ + private int p_C_AcctSchema_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_BP_Group_ID")) + p_C_BP_Group_ID = para[i].getParameterAsInt(); + else if (name.equals("C_AcctSchema_ID")) + p_C_AcctSchema_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("C_AcctSchema_ID=" + p_C_AcctSchema_ID); + if (p_C_AcctSchema_ID == 0) + throw new AdempiereSystemError("C_AcctSchema_ID=0"); + MAcctSchema as = MAcctSchema.get(getCtx(), p_C_AcctSchema_ID); + if (as.get_ID() == 0) + throw new AdempiereSystemError("Not Found - C_AcctSchema_ID=" + p_C_AcctSchema_ID); + // + String sql = null; + int updated = 0; + int created = 0; + int updatedTotal = 0; + int createdTotal = 0; + + // Update existing Customers + sql = "UPDATE C_BP_Customer_Acct ca " + + "SET (C_Receivable_Acct,C_Receivable_Services_Acct,C_PrePayment_Acct)=" + + " (SELECT C_Receivable_Acct,C_Receivable_Services_Acct,C_PrePayment_Acct " + + " FROM C_BP_Group_Acct" + + " WHERE C_BP_Group_ID=" + p_C_BP_Group_ID + + " AND C_AcctSchema_ID=" + p_C_AcctSchema_ID + + "), Updated=SysDate, UpdatedBy=0 " + + "WHERE ca.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND EXISTS (SELECT * FROM C_BPartner p " + + "WHERE p.C_BPartner_ID=ca.C_BPartner_ID" + + " AND p.C_BP_Group_ID=" + p_C_BP_Group_ID + ")"; + updated = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(updated), "@Updated@ @C_BPartner_ID@ @IsCustomer@"); + updatedTotal += updated; + + // Insert new Customer + sql = "INSERT INTO C_BP_Customer_Acct " + + "(C_BPartner_ID, C_AcctSchema_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " C_Receivable_Acct, C_Receivable_Services_Acct, C_PrePayment_Acct) " + + "SELECT p.C_BPartner_ID, acct.C_AcctSchema_ID," + + " p.AD_Client_ID, p.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0," + + " acct.C_Receivable_Acct, acct.C_Receivable_Services_Acct, acct.C_PrePayment_Acct " + + "FROM C_BPartner p" + + " INNER JOIN C_BP_Group_Acct acct ON (acct.C_BP_Group_ID=p.C_BP_Group_ID)" + + "WHERE acct.C_AcctSchema_ID=" + p_C_AcctSchema_ID // # + + " AND p.C_BP_Group_ID=" + p_C_BP_Group_ID + + " AND NOT EXISTS (SELECT * FROM C_BP_Customer_Acct ca " + + "WHERE ca.C_BPartner_ID=p.C_BPartner_ID" + + " AND ca.C_AcctSchema_ID=acct.C_AcctSchema_ID)"; + created = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(created), "@Created@ @C_BPartner_ID@ @IsCustomer@"); + createdTotal += created; + + + // Update existing Vendors + sql = "UPDATE C_BP_Vendor_Acct va " + + "SET (V_Liability_Acct,V_Liability_Services_Acct,V_PrePayment_Acct)=" + + " (SELECT V_Liability_Acct,V_Liability_Services_Acct,V_PrePayment_Acct " + + " FROM C_BP_Group_Acct" + + " WHERE C_BP_Group_ID=" + p_C_BP_Group_ID + + " AND C_AcctSchema_ID=" + p_C_AcctSchema_ID + + "), Updated=SysDate, UpdatedBy=0 " + + "WHERE va.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND EXISTS (SELECT * FROM C_BPartner p " + + "WHERE p.C_BPartner_ID=va.C_BPartner_ID" + + " AND p.C_BP_Group_ID=" + p_C_BP_Group_ID + ")"; + updated = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(updated), "@Updated@ @C_BPartner_ID@ @IsVendor@"); + updatedTotal += updated; + + // Insert new Vendors + sql = "INSERT INTO C_BP_Vendor_Acct " + + "(C_BPartner_ID, C_AcctSchema_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " V_Liability_Acct, V_Liability_Services_Acct, V_PrePayment_Acct) " + + "SELECT p.C_BPartner_ID, acct.C_AcctSchema_ID," + + " p.AD_Client_ID, p.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0," + + " acct.V_Liability_Acct, acct.V_Liability_Services_Acct, acct.V_PrePayment_Acct " + + "FROM C_BPartner p" + + " INNER JOIN C_BP_Group_Acct acct ON (acct.C_BP_Group_ID=p.C_BP_Group_ID)" + + "WHERE acct.C_AcctSchema_ID=" + p_C_AcctSchema_ID // # + + " AND p.C_BP_Group_ID=" + p_C_BP_Group_ID + + " AND NOT EXISTS (SELECT * FROM C_BP_Vendor_Acct va " + + "WHERE va.C_BPartner_ID=p.C_BPartner_ID AND va.C_AcctSchema_ID=acct.C_AcctSchema_ID)"; + created = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(created), "@Created@ @C_BPartner_ID@ @IsVendor@"); + createdTotal += created; + + return "@Created@=" + createdTotal + ", @Updated@=" + updatedTotal; + } // doIt + +} // BPGroupAcctCopy diff --git a/base/src/org/compiere/process/BPartnerOrgLink.java b/base/src/org/compiere/process/BPartnerOrgLink.java new file mode 100644 index 0000000000..600a6cbad5 --- /dev/null +++ b/base/src/org/compiere/process/BPartnerOrgLink.java @@ -0,0 +1,181 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Link Business Partner to Organization. + * Either to existing or create new one + * + * @author Jorg Janke + * @version $Id: BPartnerOrgLink.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class BPartnerOrgLink extends SvrProcess +{ + /** Existing Org */ + private int p_AD_Org_ID; + /** Info for New Org */ + private int p_AD_OrgType_ID; + /** Business Partner */ + private int p_C_BPartner_ID; + /** Role */ + private int p_AD_Role_ID; + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Org_ID")) + p_AD_Org_ID = para[i].getParameterAsInt(); + else if (name.equals("AD_OrgType_ID")) + p_AD_OrgType_ID = para[i].getParameterAsInt(); + else if (name.equals("AD_Role_ID")) + p_AD_Role_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + p_C_BPartner_ID = getRecord_ID(); + } // prepare + + /** + * Perform process. + * @return Message (text with variables) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("C_BPartner_ID=" + p_C_BPartner_ID + + ", AD_Org_ID=" + p_AD_Org_ID + + ", AD_OrgType_ID=" + p_AD_OrgType_ID + + ", AD_Role_ID=" + p_AD_Role_ID); + if (p_C_BPartner_ID == 0) + throw new AdempiereUserError ("No Business Partner ID"); + MBPartner bp = new MBPartner (getCtx(), p_C_BPartner_ID, get_TrxName()); + if (bp.get_ID() == 0) + throw new AdempiereUserError ("Business Partner not found - C_BPartner_ID=" + p_C_BPartner_ID); + // BP Location + MBPartnerLocation[] locs = bp.getLocations(false); + if (locs == null || locs.length == 0) + throw new IllegalArgumentException ("Business Partner has no Location"); + // Location + int C_Location_ID = locs[0].getC_Location_ID(); + if (C_Location_ID == 0) + throw new IllegalArgumentException ("Business Partner Location has no Address"); + + // Create Org + boolean newOrg = p_AD_Org_ID == 0; + MOrg org = new MOrg (getCtx(), p_AD_Org_ID, get_TrxName()); + if (newOrg) + { + org.setValue (bp.getValue()); + org.setName (bp.getName()); + org.setDescription (bp.getDescription()); + if (!org.save()) + throw new Exception ("Organization not saved"); + } + else // check if linked to already + { + int C_BPartner_ID = org.getLinkedC_BPartner_ID(); + if (C_BPartner_ID > 0) + throw new IllegalArgumentException ("Organization '" + org.getName() + + "' already linked (to C_BPartner_ID=" + C_BPartner_ID + ")"); + } + p_AD_Org_ID = org.getAD_Org_ID(); + + // Update Org Info + MOrgInfo oInfo = org.getInfo(); + oInfo.setAD_OrgType_ID (p_AD_OrgType_ID); + if (newOrg) + oInfo.setC_Location_ID(C_Location_ID); + + // Create Warehouse + MWarehouse wh = null; + if (!newOrg) + { + MWarehouse[] whs = MWarehouse.getForOrg(getCtx(), p_AD_Org_ID); + if (whs != null && whs.length > 0) + wh = whs[0]; // pick first + } + // New Warehouse + if (wh == null) + { + wh = new MWarehouse(org); + if (!wh.save()) + throw new Exception ("Warehouse not saved"); + } + // Create Locator + MLocator mLoc = wh.getDefaultLocator(); + if (mLoc == null) + { + mLoc = new MLocator (wh, "Standard"); + mLoc.setIsDefault(true); + mLoc.save(); + } + + // Update/Save Org Info + oInfo.setM_Warehouse_ID(wh.getM_Warehouse_ID()); + if (!oInfo.save()) + throw new Exception ("Organization Info not saved"); + + // Update BPartner + bp.setAD_OrgBP_ID(p_AD_Org_ID); + if (bp.getAD_Org_ID() != 0) + bp.setClientOrg(bp.getAD_Client_ID(), 0); // Shared BPartner + + // Save BP + if (!bp.save()) + throw new Exception ("Business Partner not updated"); + + // Limit to specific Role + if (p_AD_Role_ID != 0) + { + boolean found = false; + MRoleOrgAccess[] orgAccesses = MRoleOrgAccess.getOfOrg (getCtx(), p_AD_Org_ID); + // delete all accesses except the specific + for (int i = 0; i < orgAccesses.length; i++) + { + if (orgAccesses[i].getAD_Role_ID() == p_AD_Role_ID) + found = true; + else + orgAccesses[i].delete(true); + } + // create access + if (!found) + { + MRoleOrgAccess orgAccess = new MRoleOrgAccess (org, p_AD_Role_ID); + orgAccess.save(); + } + } + + // Reset Client Role + MRole.getDefault(getCtx(), true); + + return "Business Partner - Organization Link created"; + } // doIt + +} // BPartnerOrgLink diff --git a/base/src/org/compiere/process/BPartnerOrgUnLink.java b/base/src/org/compiere/process/BPartnerOrgUnLink.java new file mode 100644 index 0000000000..2e0f57a2b1 --- /dev/null +++ b/base/src/org/compiere/process/BPartnerOrgUnLink.java @@ -0,0 +1,75 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.util.logging.*; +import org.compiere.model.*; + +/** + * UnLink Business Partner from Organization + * + * @author Jorg Janke + * @version $Id: BPartnerOrgUnLink.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class BPartnerOrgUnLink extends SvrProcess +{ + /** Business Partner */ + private int p_C_BPartner_ID; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perform process. + * @return Message (text with variables) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("doIt - C_BPartner_ID=" + p_C_BPartner_ID); + if (p_C_BPartner_ID == 0) + throw new IllegalArgumentException ("No Business Partner ID"); + MBPartner bp = new MBPartner (getCtx(), p_C_BPartner_ID, get_TrxName()); + if (bp.get_ID() == 0) + throw new IllegalArgumentException ("Business Partner not found - C_BPartner_ID=" + p_C_BPartner_ID); + // + if (bp.getAD_OrgBP_ID_Int() == 0) + throw new IllegalArgumentException ("Business Partner not linked to an Organization"); + bp.setAD_OrgBP_ID(null); + if (!bp.save()) + throw new IllegalArgumentException ("Business Partner not changed"); + + return "OK"; + } // doIt + +} // BPartnerOrgUnLink diff --git a/base/src/org/compiere/process/BPartnerValidate.java b/base/src/org/compiere/process/BPartnerValidate.java new file mode 100644 index 0000000000..eaba4ae1d9 --- /dev/null +++ b/base/src/org/compiere/process/BPartnerValidate.java @@ -0,0 +1,185 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Validate Business Partner + * + * @author Jorg Janke + * @version $Id: BPartnerValidate.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class BPartnerValidate extends SvrProcess +{ + /** BPartner ID */ + int p_C_BPartner_ID = 0; + /** BPartner Group */ + int p_C_BP_Group_ID = 0; + + /** + * Prepare + */ + protected void prepare () + { + p_C_BPartner_ID = getRecord_ID(); + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = para[i].getParameterAsInt(); + else if (name.equals("C_BP_Group_ID")) + p_C_BP_Group_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("C_BPartner_ID=" + p_C_BPartner_ID + ", C_BP_Group_ID=" + p_C_BP_Group_ID); + if (p_C_BPartner_ID == 0 && p_C_BP_Group_ID == 0) + throw new AdempiereUserError ("No Business Partner/Group selected"); + + if (p_C_BP_Group_ID == 0) + { + MBPartner bp = new MBPartner (getCtx(), p_C_BPartner_ID, get_TrxName()); + if (bp.get_ID() == 0) + throw new AdempiereUserError ("Business Partner not found - C_BPartner_ID=" + p_C_BPartner_ID); + checkBP (bp); + } + else + { + String sql = "SELECT * FROM C_BPartner WHERE C_BP_Group_ID=? AND IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, p_C_BP_Group_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MBPartner bp = new MBPartner (getCtx(), rs, get_TrxName()); + checkBP (bp); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + } + // + return "OK"; + } // doIt + + /** + * Check BP + * @param bp bp + */ + private void checkBP (MBPartner bp) + { + addLog(0, null, null, bp.getName() + ":"); + // See also VMerge.postMerge + checkPayments(bp); + checkInvoices(bp); + // + bp.setTotalOpenBalance(); + bp.setActualLifeTimeValue(); + bp.save(); + // + // if (bp.getSO_CreditUsed().signum() != 0) + addLog(0, null, bp.getSO_CreditUsed(), Msg.getElement(getCtx(), "SO_CreditUsed")); + addLog(0, null, bp.getTotalOpenBalance(), Msg.getElement(getCtx(), "TotalOpenBalance")); + addLog(0, null, bp.getActualLifeTimeValue(), Msg.getElement(getCtx(), "ActualLifeTimeValue")); + // + commit(); + } // checkBP + + + /** + * Check Payments + * @param bp business partner + */ + private void checkPayments (MBPartner bp) + { + // See also VMerge.postMerge + int changed = 0; + MPayment[] payments = MPayment.getOfBPartner(getCtx(), bp.getC_BPartner_ID(), get_TrxName()); + for (int i = 0; i < payments.length; i++) + { + MPayment payment = payments[i]; + if (payment.testAllocation()) + { + payment.save(); + changed++; + } + } + if (changed != 0) + addLog(0, null, new BigDecimal(payments.length), + Msg.getElement(getCtx(), "C_Payment_ID") + " - #" + changed); + } // checkPayments + + /** + * Check Invoices + * @param bp business partner + */ + private void checkInvoices (MBPartner bp) + { + // See also VMerge.postMerge + int changed = 0; + MInvoice[] invoices = MInvoice.getOfBPartner(getCtx(), bp.getC_BPartner_ID(), get_TrxName()); + for (int i = 0; i < invoices.length; i++) + { + MInvoice invoice = invoices[i]; + if (invoice.testAllocation()) + { + invoice.save(); + changed++; + } + } + if (changed != 0) + addLog(0, null, new BigDecimal(invoices.length), + Msg.getElement(getCtx(), "C_Invoice_ID") + " - #" + changed); + } // checkInvoices + +} // BPartnerValidate diff --git a/base/src/org/compiere/process/BankStatementMatcher.java b/base/src/org/compiere/process/BankStatementMatcher.java new file mode 100644 index 0000000000..5fa56e9d64 --- /dev/null +++ b/base/src/org/compiere/process/BankStatementMatcher.java @@ -0,0 +1,167 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + + +import java.util.logging.*; +import org.compiere.impexp.*; +import org.compiere.model.*; + +/** + * Bank Statement Matching + * + * @author Jorg Janke + * @version $Id: BankStatementMatcher.java,v 1.3 2006/09/25 00:59:41 jjanke Exp $ + */ +public class BankStatementMatcher extends SvrProcess +{ + /** Matchers */ + MBankStatementMatcher[] m_matchers = null; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + m_matchers = MBankStatementMatcher.getMatchers(getCtx(), get_TrxName()); + } // prepare + + /** + * Perform process. + * @return Message + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + int Table_ID = getTable_ID(); + int Record_ID = getRecord_ID(); + if (m_matchers == null || m_matchers.length == 0) + throw new IllegalStateException("No Matchers found"); + // + log.info ("doIt - Table_ID=" + Table_ID + ", Record_ID=" + Record_ID + + ", Matchers=" + m_matchers.length); + + if (Table_ID == X_I_BankStatement.Table_ID) + return match (new X_I_BankStatement(getCtx(), Record_ID, get_TrxName())); + else if (Table_ID == MBankStatement.Table_ID) + return match (new MBankStatement(getCtx(), Record_ID, get_TrxName())); + else if (Table_ID == MBankStatementLine.Table_ID) + return match (new MBankStatementLine(getCtx(), Record_ID, get_TrxName())); + + return "??"; + } // doIt + + /** + * Perform Match + * @param ibs import bank statement line + * @return Message + */ + private String match (X_I_BankStatement ibs) + { + if (m_matchers == null || ibs == null || ibs.getC_Payment_ID() != 0) + return "--"; + + log.fine("" + ibs); + BankStatementMatchInfo info = null; + for (int i = 0; i < m_matchers.length; i++) + { + if (m_matchers[i].isMatcherValid()) + { + info = m_matchers[i].getMatcher().findMatch(ibs); + if (info != null && info.isMatched()) + { + if (info.getC_Payment_ID() > 0) + ibs.setC_Payment_ID(info.getC_Payment_ID()); + if (info.getC_Invoice_ID() > 0) + ibs.setC_Invoice_ID(info.getC_Invoice_ID()); + if (info.getC_BPartner_ID() > 0) + ibs.setC_BPartner_ID(info.getC_BPartner_ID()); + ibs.save(); + return "OK"; + } + } + } // for all matchers + return "--"; + } // match + + + /** + * Perform Match + * @param bsl bank statement line + * @return Message + */ + private String match (MBankStatementLine bsl) + { + if (m_matchers == null || bsl == null || bsl.getC_Payment_ID() != 0) + return "--"; + + log.fine("match - " + bsl); + BankStatementMatchInfo info = null; + for (int i = 0; i < m_matchers.length; i++) + { + if (m_matchers[i].isMatcherValid()) + { + info = m_matchers[i].getMatcher().findMatch(bsl); + if (info != null && info.isMatched()) + { + if (info.getC_Payment_ID() > 0) + bsl.setC_Payment_ID(info.getC_Payment_ID()); + if (info.getC_Invoice_ID() > 0) + bsl.setC_Invoice_ID(info.getC_Invoice_ID()); + if (info.getC_BPartner_ID() > 0) + bsl.setC_BPartner_ID(info.getC_BPartner_ID()); + bsl.save(); + return "OK"; + } + } + } // for all matchers + return "--"; + } // match + + /** + * Perform Match + * @param bs bank statement + * @return Message + */ + private String match (MBankStatement bs) + { + if (m_matchers == null || bs == null) + return "--"; + log.fine("match - " + bs); + int count = 0; + MBankStatementLine[] lines = bs.getLines(false); + for (int i = 0; i < lines.length; i++) + { + if (lines[i].getC_Payment_ID() == 0) + { + match(lines[i]); + count++; + } + } + return String.valueOf(count); + } // match + +} // BankStatementMatcher diff --git a/base/src/org/compiere/process/BankStatementPayment.java b/base/src/org/compiere/process/BankStatementPayment.java new file mode 100644 index 0000000000..46e9fc4beb --- /dev/null +++ b/base/src/org/compiere/process/BankStatementPayment.java @@ -0,0 +1,224 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Create Payment from Bank Statement Info + * + * @author Jorg Janke + * @version $Id: BankStatementPayment.java,v 1.3 2006/07/30 00:51:01 jjanke Exp $ + */ +public class BankStatementPayment extends SvrProcess +{ + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perform process. + * @return Message + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + int Table_ID = getTable_ID(); + int Record_ID = getRecord_ID(); + log.info ("Table_ID=" + Table_ID + ", Record_ID=" + Record_ID); + + if (Table_ID == X_I_BankStatement.Table_ID) + return createPayment (new X_I_BankStatement(getCtx(), Record_ID, get_TrxName())); + else if (Table_ID == MBankStatementLine.Table_ID) + return createPayment (new MBankStatementLine(getCtx(), Record_ID, get_TrxName())); + + throw new AdempiereSystemError("??"); + } // doIt + + /** + * Create Payment for Import + * @param ibs import bank statement + * @return Message + * @throws Exception if not successful + */ + private String createPayment (X_I_BankStatement ibs) throws Exception + { + if (ibs == null || ibs.getC_Payment_ID() != 0) + return "--"; + log.fine(ibs.toString()); + if (ibs.getC_Invoice_ID() == 0 && ibs.getC_BPartner_ID() == 0) + throw new AdempiereUserError ("@NotFound@ @C_Invoice_ID@ / @C_BPartner_ID@"); + if (ibs.getC_BankAccount_ID() == 0) + throw new AdempiereUserError ("@NotFound@ @C_BankAccount_ID@"); + // + MPayment payment = createPayment (ibs.getC_Invoice_ID(), ibs.getC_BPartner_ID(), + ibs.getC_Currency_ID(), ibs.getStmtAmt(), ibs.getTrxAmt(), + ibs.getC_BankAccount_ID(), ibs.getStatementLineDate() == null ? ibs.getStatementDate() : ibs.getStatementLineDate(), + ibs.getDateAcct(), ibs.getDescription(), ibs.getAD_Org_ID()); + if (payment == null) + throw new AdempiereSystemError("Could not create Payment"); + + ibs.setC_Payment_ID(payment.getC_Payment_ID()); + ibs.setC_Currency_ID (payment.getC_Currency_ID()); + ibs.setTrxAmt(payment.getPayAmt()); + ibs.save(); + // + String retString = "@C_Payment_ID@ = " + payment.getDocumentNo(); + if (payment.getOverUnderAmt().signum() != 0) + retString += " - @OverUnderAmt@=" + payment.getOverUnderAmt(); + return retString; + } // createPayment - Import + + /** + * Create Payment for BankStatement + * @param bsl bank statement Line + * @return Message + * @throws Exception if not successful + */ + private String createPayment (MBankStatementLine bsl) throws Exception + { + if (bsl == null || bsl.getC_Payment_ID() != 0) + return "--"; + log.fine(bsl.toString()); + if (bsl.getC_Invoice_ID() == 0 && bsl.getC_BPartner_ID() == 0) + throw new AdempiereUserError ("@NotFound@ @C_Invoice_ID@ / @C_BPartner_ID@"); + // + MBankStatement bs = new MBankStatement (getCtx(), bsl.getC_BankStatement_ID(), get_TrxName()); + // + MPayment payment = createPayment (bsl.getC_Invoice_ID(), bsl.getC_BPartner_ID(), + bsl.getC_Currency_ID(), bsl.getStmtAmt(), bsl.getTrxAmt(), + bs.getC_BankAccount_ID(), bsl.getStatementLineDate(), bsl.getDateAcct(), + bsl.getDescription(), bsl.getAD_Org_ID()); + if (payment == null) + throw new AdempiereSystemError("Could not create Payment"); + // update statement + bsl.setPayment(payment); + bsl.save(); + // + String retString = "@C_Payment_ID@ = " + payment.getDocumentNo(); + if (payment.getOverUnderAmt().signum() != 0) + retString += " - @OverUnderAmt@=" + payment.getOverUnderAmt(); + return retString; + } // createPayment + + + /** + * Create actual Payment + * @param C_Invoice_ID invoice + * @param C_BPartner_ID partner ignored when invoice exists + * @param C_Currency_ID currency + * @param StmtAmt statement amount + * @param TrxAmt transaction amt + * @param C_BankAccount_ID bank account + * @param DateTrx transaction date + * @param DateAcct accounting date + * @param Description description + * @param AD_Org_ID org + * @return payment + */ + private MPayment createPayment (int C_Invoice_ID, int C_BPartner_ID, + int C_Currency_ID, BigDecimal StmtAmt, BigDecimal TrxAmt, + int C_BankAccount_ID, Timestamp DateTrx, Timestamp DateAcct, + String Description, int AD_Org_ID) + { + // Trx Amount = Payment overwrites Statement Amount if defined + BigDecimal PayAmt = TrxAmt; + if (PayAmt == null || Env.ZERO.compareTo(PayAmt) == 0) + PayAmt = StmtAmt; + if (C_Invoice_ID == 0 + && (PayAmt == null || Env.ZERO.compareTo(PayAmt) == 0)) + throw new IllegalStateException ("@PayAmt@ = 0"); + if (PayAmt == null) + PayAmt = Env.ZERO; + // + MPayment payment = new MPayment (getCtx(), 0, get_TrxName()); + payment.setAD_Org_ID(AD_Org_ID); + payment.setC_BankAccount_ID(C_BankAccount_ID); + payment.setTenderType(MPayment.TENDERTYPE_Check); + if (DateTrx != null) + payment.setDateTrx(DateTrx); + else if (DateAcct != null) + payment.setDateTrx(DateAcct); + if (DateAcct != null) + payment.setDateAcct(DateAcct); + else + payment.setDateAcct(payment.getDateTrx()); + payment.setDescription(Description); + // + if (C_Invoice_ID != 0) + { + MInvoice invoice = new MInvoice (getCtx(), C_Invoice_ID, null); + payment.setC_DocType_ID(invoice.isSOTrx()); // Receipt + payment.setC_Invoice_ID(invoice.getC_Invoice_ID()); + payment.setC_BPartner_ID (invoice.getC_BPartner_ID()); + if (PayAmt.signum() != 0) // explicit Amount + { + payment.setC_Currency_ID(C_Currency_ID); + if (invoice.isSOTrx()) + payment.setPayAmt(PayAmt); + else // payment is likely to be negative + payment.setPayAmt(PayAmt.negate()); + payment.setOverUnderAmt(invoice.getGrandTotal(true).subtract(payment.getPayAmt())); + } + else // set Pay Amout from Invoice + { + payment.setC_Currency_ID(invoice.getC_Currency_ID()); + payment.setPayAmt(invoice.getGrandTotal(true)); + } + } + else if (C_BPartner_ID != 0) + { + payment.setC_BPartner_ID(C_BPartner_ID); + payment.setC_Currency_ID(C_Currency_ID); + if (PayAmt.signum() < 0) // Payment + { + payment.setPayAmt(PayAmt.abs()); + payment.setC_DocType_ID(false); + } + else // Receipt + { + payment.setPayAmt(PayAmt); + payment.setC_DocType_ID(true); + } + } + else + return null; + payment.save(); + // + payment.processIt(MPayment.DOCACTION_Complete); + payment.save(); + return payment; + } // createPayment + +} // BankStatementPayment diff --git a/base/src/org/compiere/process/C_AcctSchema_Default_Copy.java b/base/src/org/compiere/process/C_AcctSchema_Default_Copy.java new file mode 100644 index 0000000000..47fecac1df --- /dev/null +++ b/base/src/org/compiere/process/C_AcctSchema_Default_Copy.java @@ -0,0 +1,455 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + * Portions created by Carlos Ruiz are Copyright (C) 2005 QSS Ltda. + * Contributor(s): Carlos Ruiz (globalqss) + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Title: Copy Acct Info + * Description: + * Copy Accounting Schema information to elements + * (Existing entities are overwritten) cascade all! + * + * @author Carlos Ruiz (globalqss) + * @version $Id: C_AcctSchema_Default_Copy.java,v 1.0 2005/10/31 14:09:00 globalqss Exp $ + */ +public class C_AcctSchema_Default_Copy extends SvrProcess +{ + + /* + * NOTE: The original oracle procedure C_AcctSchema_Default_Copy had a + * Client_ID parameter for Direct Call not implemented in this class + */ + + /** The Business Partner Group */ + private int ad_Client_ID = -1; + /** The Record */ + private int p_Record_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Client_ID")) + ad_Client_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_Record_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt() throws Exception + { + String sql; + String sqlupd; + String sqlins; + int cntu = 0; + int cnti = 0; + int totu = 0; + int toti = 0; + + log.info("For all Accounting Schema"); + /** + * For all Accounting Schema + */ + sql = "SELECT * FROM C_AcctSchema_Default WHERE AD_Client_ID = " + ad_Client_ID; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + // Update existing Product Category + sqlupd = "UPDATE M_Product_Category_Acct " + + "SET P_Revenue_Acct=" + rs.getInt("P_Revenue_Acct") + ", " + + "P_Expense_Acct=" + rs.getInt("P_Expense_Acct") + ", " + + "P_Asset_Acct=" + rs.getInt("P_Asset_Acct") + ", " + + "P_CoGs_Acct=" + rs.getInt("P_CoGs_Acct") + ", " + + "P_PurchasePriceVariance_Acct=" + rs.getInt("P_PurchasePriceVariance_Acct") + ", " + + "P_InvoicePriceVariance_Acct=" + rs.getInt("P_InvoicePriceVariance_Acct") + ", " + + "P_TradeDiscountRec_Acct=" + rs.getInt("P_TradeDiscountRec_Acct") + ", " + + "P_TradeDiscountGrant_Acct=" + rs.getInt("P_TradeDiscountGrant_Acct") + ", " + + "Updated=SysDate, " + + "UpdatedBy=0 " + + "WHERE M_Product_Category_Acct.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + " " + + "AND EXISTS (SELECT * FROM M_Product_Category p " + + "WHERE p.M_Product_Category_ID=M_Product_Category_Acct.M_Product_Category_ID)"; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + totu += cntu; + // Insert new Product Category + sqlins = "INSERT INTO M_Product_Category_Acct " + + "(M_Product_Category_ID, C_AcctSchema_ID, " + + "AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, " + + "P_Revenue_Acct, P_Expense_Acct, P_Asset_Acct, P_CoGs_Acct, " + + "P_PurchasePriceVariance_Acct, P_InvoicePriceVariance_Acct, " + + "P_TradeDiscountRec_Acct, P_TradeDiscountGrant_Acct) " + + "SELECT p.M_Product_Category_ID, " + rs.getInt("C_AcctSchema_ID") + ", " + + "p.AD_Client_ID, p.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0, " + + rs.getInt("P_Revenue_Acct") + ", " + rs.getInt("P_Expense_Acct") + ", " + + rs.getInt("P_Asset_Acct") + ", " + rs.getInt("P_CoGs_Acct") + ", " + + rs.getInt("P_PurchasePriceVariance_Acct") + ", " + rs.getInt("P_InvoicePriceVariance_Acct") + ", " + + rs.getInt("P_TradeDiscountRec_Acct") + ", " + rs.getInt("P_TradeDiscountGrant_Acct") + " " + + "FROM M_Product_Category p " + + "WHERE AD_Client_ID=" + rs.getInt("AD_Client_ID") + " " + + "AND NOT EXISTS (SELECT * FROM M_Product_Category_Acct pa " + + "WHERE pa.M_Product_Category_ID=p.M_Product_Category_ID " + + "AND pa.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + ")"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + toti += cnti; + log.info("Product Category = " + cntu + " / " + cnti); + + // Business Partner Group + sqlupd = "UPDATE C_BP_Group_Acct " + + "SET C_Receivable_Acct=" + rs.getInt("C_Receivable_Acct") + ", " + + "C_PrePayment_Acct=" + rs.getInt("C_PrePayment_Acct") + ", " + + "V_Liability_Acct=" + rs.getInt("V_Liability_Acct") + ", " + + "V_Liability_Services_Acct=" + rs.getInt("V_Liability_Services_Acct") + ", " + + "V_PrePayment_Acct=" + rs.getInt("V_PrePayment_Acct") + ", " + + "PayDiscount_Exp_Acct=" + rs.getInt("PayDiscount_Exp_Acct") + ", " + + "PayDiscount_Rev_Acct=" + rs.getInt("PayDiscount_Rev_Acct") + ", " + + "WriteOff_Acct=" + rs.getInt("WriteOff_Acct") + ", " + + "NotInvoicedReceipts_Acct=" + rs.getInt("NotInvoicedReceipts_Acct") + ", " + + "UnEarnedRevenue_Acct=" + rs.getInt("UnEarnedRevenue_Acct") + ", " + + "NotInvoicedRevenue_Acct=" + rs.getInt("NotInvoicedRevenue_Acct") + ", " + + "NotInvoicedReceivables_Acct=" + rs.getInt("NotInvoicedReceivables_Acct") + ", " + + "Updated=SysDate, " + + "UpdatedBy=0 " + + "WHERE C_BP_Group_Acct.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + " " + + "AND EXISTS (SELECT * FROM C_BP_Group_Acct x " + + "WHERE x.C_BP_Group_ID=C_BP_Group_Acct.C_BP_Group_ID)"; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + totu += cntu; + // Insert new + sqlins = "INSERT INTO C_BP_Group_Acct " + + "(C_BP_Group_ID, C_AcctSchema_ID, " + + "AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, " + + "C_Receivable_Acct, C_PrePayment_Acct, " + + "V_Liability_Acct, V_Liability_Services_Acct, V_PrePayment_Acct, " + + "PayDiscount_Exp_Acct, PayDiscount_Rev_Acct, WriteOff_Acct, " + + "NotInvoicedReceipts_Acct, UnEarnedRevenue_Acct, " + + "NotInvoicedRevenue_Acct, NotInvoicedReceivables_Acct) " + + "SELECT x.C_BP_Group_ID, " + rs.getInt("C_AcctSchema_ID") + ", " + + "x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0, " + + rs.getInt("C_Receivable_Acct") + ", " + rs.getInt("C_PrePayment_Acct") + ", " + + rs.getInt("V_Liability_Acct") + ", " + rs.getInt("V_Liability_Services_Acct") + ", " + + rs.getInt("V_PrePayment_Acct") + ", " + + rs.getInt("PayDiscount_Exp_Acct") + ", " + rs.getInt("PayDiscount_Rev_Acct") + ", " + + rs.getInt("WriteOff_Acct") + ", " + + rs.getInt("NotInvoicedReceipts_Acct") + ", " + rs.getInt("UnEarnedRevenue_Acct") + ", " + + rs.getInt("NotInvoicedRevenue_Acct") + ", " + rs.getInt("NotInvoicedReceivables_Acct") + " " + + "FROM C_BP_Group x " + + "WHERE AD_Client_ID=" + rs.getInt("AD_Client_ID") + " " + + "AND NOT EXISTS (SELECT * FROM C_BP_Group_Acct a " + + "WHERE a.C_BP_Group_ID=x.C_BP_Group_ID " + + "AND a.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + ")"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + toti += cnti; + log.info("Business Group = " + cntu + " / " + cnti); + + // Business Partner Employee + sqlupd = "UPDATE C_BP_Employee_Acct " + + "SET E_Expense_Acct=" + rs.getInt("E_Expense_Acct") + ", " + + "E_PrePayment_Acct=" + rs.getInt("E_PrePayment_Acct") + ", " + + "Updated=SysDate, " + + "UpdatedBy=0 " + + "WHERE C_BP_Employee_Acct.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + " " + + "AND EXISTS (SELECT * FROM C_BP_Employee_Acct x " + + "WHERE x.C_BPartner_ID=C_BP_Employee_Acct.C_BPartner_ID)"; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + totu += cntu; + // Insert new + sqlins = "INSERT INTO C_BP_Employee_Acct " + + "(C_BPartner_ID, C_AcctSchema_ID, " + + "AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, " + + "E_Expense_Acct, E_PrePayment_Acct) " + + "SELECT x.C_BPartner_ID, " + rs.getInt("C_AcctSchema_ID") + ", " + + "x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0, " + + "" + rs.getInt("E_Expense_Acct") + ", " + rs.getInt("E_PrePayment_Acct") + " " + + "FROM C_BPartner x " + + "WHERE AD_Client_ID=" + rs.getInt("AD_Client_ID") + " " + + "AND NOT EXISTS (SELECT * FROM C_BP_Employee_Acct a " + + "WHERE a.C_BPartner_ID=x.C_BPartner_ID " + + "AND a.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + ")"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + toti += cnti; + log.info("Employees = " + cntu + " / " + cnti); + + // Warehouse + sqlupd = "UPDATE M_Warehouse_Acct " + + "SET W_Inventory_Acct=" + rs.getInt("W_Inventory_Acct") + ", " + + "W_Differences_Acct=" + rs.getInt("W_Differences_Acct") + ", " + + "W_Revaluation_Acct=" + rs.getInt("W_Revaluation_Acct") + ", " + + "W_InvActualAdjust_Acct=" + rs.getInt("W_InvActualAdjust_Acct") + ", " + + "Updated=SysDate, " + + "UpdatedBy=0 " + + "WHERE M_Warehouse_Acct.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + " " + + "AND EXISTS (SELECT * FROM M_Warehouse_Acct x " + + "WHERE x.M_Warehouse_ID=M_Warehouse_Acct.M_Warehouse_ID)"; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + totu += cntu; + // Insert new + sqlins = "INSERT INTO M_Warehouse_Acct " + + "(M_Warehouse_ID, C_AcctSchema_ID, " + + "AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, " + + "W_Inventory_Acct, W_Differences_Acct, W_Revaluation_Acct, W_InvActualAdjust_Acct) " + + "SELECT x.M_Warehouse_ID, " + rs.getInt("C_AcctSchema_ID") + ", " + + "x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0, " + + "" + rs.getInt("W_Inventory_Acct") + ", " + rs.getInt("W_Differences_Acct") + ", " + rs.getInt("W_Revaluation_Acct") + ", " + rs.getInt("W_InvActualAdjust_Acct") + " " + + "FROM M_Warehouse x " + + "WHERE AD_Client_ID=" + rs.getInt("AD_Client_ID") + " " + + "AND NOT EXISTS (SELECT * FROM M_Warehouse_Acct a " + + "WHERE a.M_Warehouse_ID=x.M_Warehouse_ID " + + "AND a.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + ")"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + toti += cnti; + log.info("Warehouse = " + cntu + " / " + cnti); + + // Project + sqlupd = "UPDATE C_Project_Acct " + + "SET PJ_Asset_Acct=" + rs.getInt("PJ_Asset_Acct") + ", " + + "PJ_WIP_Acct=" + rs.getInt("PJ_Asset_Acct") + ", " + + "Updated=SysDate, " + + "UpdatedBy=0 " + + "WHERE C_Project_Acct.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + " " + + "AND EXISTS (SELECT * FROM C_Project_Acct x " + + "WHERE x.C_Project_ID=C_Project_Acct.C_Project_ID)"; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + totu += cntu; + // Insert new + sqlins = "INSERT INTO C_Project_Acct " + + "(C_Project_ID, C_AcctSchema_ID, " + + "AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, " + + "PJ_Asset_Acct, PJ_WIP_Acct) " + + "SELECT x.C_Project_ID, " + rs.getInt("C_AcctSchema_ID") + ", " + + "x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0, " + + "" + rs.getInt("PJ_Asset_Acct") + ", " + rs.getInt("PJ_WIP_Acct") + " " + + "FROM C_Project x " + + "WHERE AD_Client_ID=" + rs.getInt("AD_Client_ID") + " " + + "AND NOT EXISTS (SELECT * FROM C_Project_Acct a " + + "WHERE a.C_Project_ID=x.C_Project_ID " + + "AND a.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + ")"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + toti += cnti; + log.info("Project = " + cntu + " / " + cnti); + + // Tax + sqlupd = "UPDATE C_Tax_Acct " + + "SET T_Due_Acct=" + rs.getInt("T_Due_Acct") + ", " + + "T_Liability_Acct=" + rs.getInt("T_Liability_Acct") + ", " + + "T_Credit_Acct=" + rs.getInt("T_Credit_Acct") + ", " + + "T_Receivables_Acct=" + rs.getInt("T_Receivables_Acct") + ", " + + "T_Expense_Acct=" + rs.getInt("T_Expense_Acct") + ", " + + "Updated=SysDate, " + + "UpdatedBy=0 " + + "WHERE C_Tax_Acct.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + " " + + "AND EXISTS (SELECT * FROM C_Tax_Acct x " + + "WHERE x.C_Tax_ID=C_Tax_Acct.C_Tax_ID)"; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + totu += cntu; + // Insert new + sqlins = "INSERT INTO C_Tax_Acct " + + "(C_Tax_ID, C_AcctSchema_ID, " + + "AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, " + + "T_Due_Acct, T_Liability_Acct, T_Credit_Acct, T_Receivables_Acct, T_Expense_Acct) " + + "SELECT x.C_Tax_ID, " + rs.getInt("C_AcctSchema_ID") + ", " + + "x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0, " + + "" + rs.getInt("T_Due_Acct") + ", " + rs.getInt("T_Liability_Acct") + ", " + rs.getInt("T_Credit_Acct") + ", " + rs.getInt("T_Receivables_Acct") + ", " + rs.getInt("T_Expense_Acct") + " " + + "FROM C_Tax x " + + "WHERE AD_Client_ID=" + rs.getInt("AD_Client_ID") + " " + + "AND NOT EXISTS (SELECT * FROM C_Tax_Acct a " + + "WHERE a.C_Tax_ID=x.C_Tax_ID " + + "AND a.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + ")"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + toti += cnti; + log.info("Tax = " + cntu + " / " + cnti); + + // BankAccount + sqlupd = "UPDATE C_BankAccount_Acct " + + "SET B_InTransit_Acct=" + rs.getInt("B_InTransit_Acct") + ", " + + "B_Asset_Acct=" + rs.getInt("B_Asset_Acct") + ", " + + "B_Expense_Acct=" + rs.getInt("B_Expense_Acct") + ", " + + "B_InterestRev_Acct=" + rs.getInt("B_InterestRev_Acct") + ", " + + "B_InterestExp_Acct=" + rs.getInt("B_InterestExp_Acct") + ", " + + "B_UnIdentified_Acct=" + rs.getInt("B_UnIdentified_Acct") + ", " + + "B_UnAllocatedCash_Acct=" + rs.getInt("B_UnAllocatedCash_Acct") + ", " + + "B_PaymentSelect_Acct=" + rs.getInt("B_PaymentSelect_Acct") + ", " + + "B_SettlementGain_Acct=" + rs.getInt("B_SettlementGain_Acct") + ", " + + "B_SettlementLoss_Acct=" + rs.getInt("B_SettlementLoss_Acct") + ", " + + "B_RevaluationGain_Acct=" + rs.getInt("B_RevaluationGain_Acct") + ", " + + "B_RevaluationLoss_Acct=" + rs.getInt("B_RevaluationLoss_Acct") + ", " + + "Updated=SysDate, " + + "UpdatedBy=0 " + + "WHERE C_BankAccount_Acct.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + " " + + "AND EXISTS (SELECT * FROM C_BankAccount_Acct x " + + "WHERE x.C_BankAccount_ID=C_BankAccount_Acct.C_BankAccount_ID)"; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + totu += cntu; + // Insert new + sqlins = "INSERT INTO C_BankAccount_Acct " + + "(C_BankAccount_ID, C_AcctSchema_ID, " + + "AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, " + + "B_InTransit_Acct, B_Asset_Acct, B_Expense_Acct, B_InterestRev_Acct, B_InterestExp_Acct, " + + "B_UnIdentified_Acct, B_UnAllocatedCash_Acct, B_PaymentSelect_Acct, " + + "B_SettlementGain_Acct, B_SettlementLoss_Acct, " + + "B_RevaluationGain_Acct, B_RevaluationLoss_Acct) " + + "SELECT x.C_BankAccount_ID, " + rs.getInt("C_AcctSchema_ID") + ", " + + "x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0, " + + "" + rs.getInt("B_InTransit_Acct") + ", " + rs.getInt("B_Asset_Acct") + ", " + rs.getInt("B_Expense_Acct") + ", " + rs.getInt("B_InterestRev_Acct") + ", " + rs.getInt("B_InterestExp_Acct") + ", " + + "" + rs.getInt("B_UnIdentified_Acct") + ", " + rs.getInt("B_UnAllocatedCash_Acct") + ", " + rs.getInt("B_PaymentSelect_Acct") + ", " + + "" + rs.getInt("B_SettlementGain_Acct") + ", " + rs.getInt("B_SettlementLoss_Acct") + ", " + + "" + rs.getInt("B_RevaluationGain_Acct") + ", " + rs.getInt("B_RevaluationLoss_Acct") + " " + + "FROM C_BankAccount x " + + "WHERE AD_Client_ID=" + rs.getInt("AD_Client_ID") + " " + + "AND NOT EXISTS (SELECT * FROM C_BankAccount_Acct a " + + "WHERE a.C_BankAccount_ID=x.C_BankAccount_ID " + + "AND a.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + ")"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + toti += cnti; + log.info("Bank Account = " + cntu + " / " + cnti); + + // Withholding + sqlupd = "UPDATE C_Withholding_Acct " + + "SET Withholding_Acct=" + rs.getInt("Withholding_Acct") + ", " + + "Updated=SysDate, " + + "UpdatedBy=0 " + + "WHERE C_Withholding_Acct.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + " " + + "AND EXISTS (SELECT * FROM C_Withholding_Acct x " + + "WHERE x.C_Withholding_ID=C_Withholding_Acct.C_Withholding_ID)"; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + totu += cntu; + // Insert new + sqlins = "INSERT INTO C_Withholding_Acct " + + "(C_Withholding_ID, C_AcctSchema_ID, " + + "AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, " + + "Withholding_Acct) " + + "SELECT x.C_Withholding_ID, " + rs.getInt("C_AcctSchema_ID") + ", " + + "x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0, " + + "" + rs.getInt("Withholding_Acct") + " " + + "FROM C_Withholding x " + + "WHERE AD_Client_ID=" + rs.getInt("AD_Client_ID") + " " + + "AND NOT EXISTS (SELECT * FROM C_Withholding_Acct a " + + "WHERE a.C_Withholding_ID=x.C_Withholding_ID " + + "AND a.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + ")"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + toti += cnti; + log.info("Withholding = " + cntu + " / " + cnti); + + // Charge + sqlupd = "UPDATE C_Charge_Acct " + + "SET Ch_Expense_Acct=" + rs.getInt("Ch_Expense_Acct") + ", " + + "Ch_Revenue_Acct=" + rs.getInt("Ch_Revenue_Acct") + ", " + + "Updated=SysDate, " + + "UpdatedBy=0 " + + "WHERE C_Charge_Acct.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + " " + + "AND EXISTS (SELECT * FROM C_Charge_Acct x " + + "WHERE x.C_Charge_ID=C_Charge_Acct.C_Charge_ID)"; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + totu += cntu; + // Insert new + sqlins = "INSERT INTO C_Charge_Acct " + + "(C_Charge_ID, C_AcctSchema_ID, " + + "AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, " + + "Ch_Expense_Acct, Ch_Revenue_Acct) " + + "SELECT x.C_Charge_ID, " + rs.getInt("C_AcctSchema_ID") + ", " + + "x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0, " + + "" + rs.getInt("Ch_Expense_Acct") + ", " + rs.getInt("Ch_Revenue_Acct") + " " + + "FROM C_Charge x " + + "WHERE AD_Client_ID=" + rs.getInt("AD_Client_ID") + " " + + "AND NOT EXISTS (SELECT * FROM C_Charge_Acct a " + + "WHERE a.C_Charge_ID=x.C_Charge_ID " + + "AND a.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + ")"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + toti += cnti; + log.info("Charge = " + cntu + " / " + cnti); + + // Cashbook + sqlupd = "UPDATE C_Cashbook_Acct " + + "SET CB_Asset_Acct=" + rs.getInt("CB_Asset_Acct") + ", " + + "CB_Differences_Acct=" + rs.getInt("CB_Differences_Acct") + ", " + + "CB_CashTransfer_Acct=" + rs.getInt("CB_CashTransfer_Acct") + ", " + + "CB_Expense_Acct=" + rs.getInt("CB_Expense_Acct") + ", " + + "CB_Receipt_Acct=" + rs.getInt("CB_Receipt_Acct") + ", " + + "Updated=SysDate, " + + "UpdatedBy=0 " + + "WHERE C_Cashbook_Acct.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + " " + + "AND EXISTS (SELECT * FROM C_Cashbook_Acct x " + + "WHERE x.C_Cashbook_ID=C_Cashbook_Acct.C_Cashbook_ID)"; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + totu += cntu; + // Insert new + sqlins = "INSERT INTO C_Cashbook_Acct " + + "(C_Cashbook_ID, C_AcctSchema_ID, " + + "AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, " + + "CB_Asset_Acct, CB_Differences_Acct, CB_CashTransfer_Acct, " + + "CB_Expense_Acct, CB_Receipt_Acct) " + + "SELECT x.C_Cashbook_ID, " + rs.getInt("C_AcctSchema_ID") + ", " + + "x.AD_Client_ID, x.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0, " + + "" + rs.getInt("CB_Asset_Acct") + ", " + rs.getInt("CB_Differences_Acct") + ", " + rs.getInt("CB_CashTransfer_Acct") + ", " + + "" + rs.getInt("CB_Expense_Acct") + ", " + rs.getInt("CB_Receipt_Acct") + " " + + "FROM C_Cashbook x " + + "WHERE AD_Client_ID=" + rs.getInt("AD_Client_ID") + " " + + "AND NOT EXISTS (SELECT * FROM C_Cashbook_Acct a " + + "WHERE C_Cashbook_Acct.C_Cashbook_ID=x.C_Cashbook_ID " + + "AND C_Cashbook_Acct.C_AcctSchema_ID=" + rs.getInt("C_AcctSchema_ID") + ")"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + toti += cnti; + log.info("Cashbook = " + cntu + " / " + cnti); + + } + rs.close(); + pstmt.close(); + pstmt = null; + log.fine("Committing ..."); + DB.commit(true, get_TrxName()); + } + catch (Exception e) + { + log.log(Level.SEVERE, "adding missing elements", e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + return "@Created@=" + cnti + ", @Updated@=" + cntu; + } // doIt + +} // C_AcctSchema_Default_Copy diff --git a/base/src/org/compiere/process/C_BP_Group_Acct_Copy.java b/base/src/org/compiere/process/C_BP_Group_Acct_Copy.java new file mode 100644 index 0000000000..b17e16c83e --- /dev/null +++ b/base/src/org/compiere/process/C_BP_Group_Acct_Copy.java @@ -0,0 +1,176 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + * Portions created by Carlos Ruiz are Copyright (C) 2005 QSS Ltda. + * Contributor(s): Carlos Ruiz (globalqss) + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Title: Copy Acct Info + * Description: + * Copy Accounting Info to all Business Partner Account Info elements + * (existing entries are overwritten) + * + * @author Carlos Ruiz (globalqss) + * @version $Id: C_BP_Group_Acct_Copy.java,v 1.0 2005/09/19 23:13:00 globalqss Exp $ + */ +public class C_BP_Group_Acct_Copy extends SvrProcess +{ + + /* + * NOTE: The original oracle procedure C_BP_Group_Acct_Copy had a + * BP_Group_ID parameter for Direct Call not implemented in this class + */ + + /** The Business Partner Group */ + private int c_BP_Group_ID = -1; + /** The Record */ + private int p_Record_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_BP_Group_ID")) + c_BP_Group_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_Record_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt() throws Exception + { + String sql; + String sqlupd; + String sqlins; + int cntu = 0; + int cnti = 0; + int totu = 0; + int toti = 0; + + log.info("Copy and overwrite Accounts to products of this category"); + + sql = "SELECT C_RECEIVABLE_ACCT, C_PREPAYMENT_ACCT, C_ACCTSCHEMA_ID, C_BP_GROUP_ID, " + + "V_PREPAYMENT_ACCT, V_LIABILITY_ACCT, V_LIABILITY_SERVICES_ACCT " + + "FROM C_BP_Group_Acct " + + "WHERE C_BP_Group_ID = " + c_BP_Group_ID; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + // Update existing Customers + sqlupd = "UPDATE C_BP_Customer_Acct " + + "SET C_Receivable_Acct=" + rs.getInt("C_RECEIVABLE_ACCT") + ", " + + "C_PrePayment_Acct=" + rs.getInt("C_PREPAYMENT_ACCT") + ", " + + "Updated=SysDate, " + + "UpdatedBy=0 " + + "WHERE C_BP_Customer_Acct.C_AcctSchema_ID=" + rs.getInt("C_ACCTSCHEMA_ID") + " " + + "AND EXISTS (SELECT * FROM C_BPartner p " + + "WHERE p.C_BPartner_ID=C_BP_Customer_Acct.C_BPartner_ID AND p.C_BP_Group_ID=" + rs.getInt("C_BP_GROUP_ID") + ")"; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + totu += cntu; + // Insert new Customer + sqlins = "INSERT INTO C_BP_Customer_Acct " + + "(C_BPartner_ID, C_AcctSchema_ID, " + + "AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, " + + "C_Receivable_Acct, C_PrePayment_Acct) " + + "SELECT p.C_BPartner_ID, " + rs.getInt("C_ACCTSCHEMA_ID") + ", " + + "p.AD_Client_ID, p.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0, " + + rs.getInt("C_RECEIVABLE_ACCT") + ", " + rs.getInt("C_PREPAYMENT_ACCT") + " " + + "FROM C_BPartner p " + + "WHERE p.C_BP_Group_ID=" + rs.getInt("C_BP_GROUP_ID") + " " + + "AND NOT EXISTS (SELECT * FROM C_BP_Customer_Acct ca " + + "WHERE ca.C_BPartner_ID=p.C_BPartner_ID AND ca.C_AcctSchema_ID=" + rs.getInt("C_ACCTSCHEMA_ID") + ")"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + toti += cnti; + log.info("Customers = " + cntu + " / " + cnti); + + // Update existing Vendors + sqlupd = "UPDATE C_BP_Vendor_Acct " + + "SET V_Liability_Acct=" + rs.getInt("V_LIABILITY_ACCT") + ", " + + "V_Liability_Services_Acct=" + rs.getInt("V_LIABILITY_SERVICES_ACCT") + ", " + + "V_PrePayment_Acct=" + rs.getInt("V_PREPAYMENT_ACCT") + ", " + + "Updated=SysDate, " + + "UpdatedBy=0 " + + "WHERE C_BP_Vendor_Acct.C_AcctSchema_ID=" + rs.getInt("C_ACCTSCHEMA_ID") + " " + + "AND EXISTS (SELECT * FROM C_BPartner p " + + "WHERE p.C_BPartner_ID=C_BP_Vendor_Acct.C_BPartner_ID AND p.C_BP_Group_ID=" + rs.getInt("C_BP_GROUP_ID") + ")"; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + totu += cntu; + // Insert new Vendors + sqlins = "INSERT INTO C_BP_Vendor_Acct " + + "(C_BPartner_ID, C_AcctSchema_ID, " + + "AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, " + + "V_Liability_Acct, V_Liability_Services_Acct, V_PrePayment_Acct) " + + "SELECT p.C_BPartner_ID, " + rs.getInt("C_ACCTSCHEMA_ID") + ", " + + "p.AD_Client_ID, p.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0, " + + rs.getInt("V_LIABILITY_ACCT") + ", " + rs.getInt("V_LIABILITY_SERVICES_ACCT") + + ", " + rs.getInt("V_PREPAYMENT_ACCT") + " " + + "FROM C_BPartner p " + + "WHERE p.C_BP_Group_ID=" + rs.getInt("C_BP_GROUP_ID") + " " + + "AND NOT EXISTS (SELECT * FROM C_BP_Vendor_Acct va " + + "WHERE va.C_BPartner_ID=p.C_BPartner_ID AND va.C_AcctSchema_ID=" + rs.getInt("C_ACCTSCHEMA_ID") + ")"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + toti += cnti; + log.info("Vendors = " + cntu + " / " + cnti); + + } + rs.close(); + pstmt.close(); + pstmt = null; + log.fine("Committing ..."); + DB.commit(true, get_TrxName()); + } + catch (Exception e) + { + log.log(Level.SEVERE, "adding missing elements", e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + return "@Created@=" + cnti + ":2, @Updated@=" + cntu + ":2"; + } // doIt + +} // C_BP_Group_Acct_Copy diff --git a/base/src/org/compiere/process/CacheReset.java b/base/src/org/compiere/process/CacheReset.java new file mode 100644 index 0000000000..4be8a54150 --- /dev/null +++ b/base/src/org/compiere/process/CacheReset.java @@ -0,0 +1,49 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import org.compiere.util.*; + +/** + * Reset Cache + * + * @author Jorg Janke + * @version $Id: CacheReset.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class CacheReset extends SvrProcess +{ + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + } // prepare + + + /** + * Perform process. + * @return Message to be translated + * @throws Exception + */ + protected String doIt() throws java.lang.Exception + { + log.info(""); + Env.reset(false); // not final + return "Cache Reset"; + } // doIt + +} // CacheReset diff --git a/base/src/org/compiere/process/ChangeLogProcess.java b/base/src/org/compiere/process/ChangeLogProcess.java new file mode 100644 index 0000000000..abdf4e5fdc --- /dev/null +++ b/base/src/org/compiere/process/ChangeLogProcess.java @@ -0,0 +1,408 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Process Change Logs + * + * @author Jorg Janke + * @version $Id: ChangeLogProcess.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ChangeLogProcess extends SvrProcess +{ + /** The Change Log (when applied directly) */ + private int p_AD_ChangeLog_ID = 0; + + /** UnDo - Check New Value */ + private Boolean p_CheckNewValue = null; + /** ReDo - Check Old Value */ + private Boolean p_CheckOldValue = null; + /** Set Customization */ + private boolean p_SetCustomization = false; + + /** The Update Set Command */ + private StringBuffer m_sqlUpdate = null; + /** The Where Clause */ + private StringBuffer m_sqlUpdateWhere = null; + /** Is it an insert command */ + private boolean m_isInsert = false; + /** The Insert Command */ + private StringBuffer m_sqlInsert = null; + /** The Insert Value clause */ + private StringBuffer m_sqlInsertValue = null; + + /** The Table */ + private MTable m_table = null; + /** The Column */ + private MColumn m_column = null; + /** Old Record ID */ + private int m_oldRecord_ID = 0; + /** Key Column Name */ + private String m_keyColumn = null; + /** Number of Columns */ + private int m_numberColumns = 0; + /** Array of Columns */ + private ArrayList m_columns = new ArrayList(); + + /** Number of Errors */ + private int m_errors = 0; + /** Number of Failures */ + private int m_checkFailed = 0; + /** Number of Successes */ + private int m_ok = 0; + + + /** + * Prepare + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("CheckNewValue")) + p_CheckNewValue = new Boolean("Y".equals(para[i].getParameter())); + else if (name.equals("CheckOldValue")) + p_CheckOldValue = new Boolean("Y".equals(para[i].getParameter())); + else if (name.equals("SetCustomization")) + p_SetCustomization = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_AD_ChangeLog_ID = getRecord_ID(); + } // prepare + + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt () throws Exception + { + if (p_SetCustomization) + return setCustomization(); + + log.info("AD_ChangeLog_ID=" + p_AD_ChangeLog_ID + + ", CheckOldValue=" + p_CheckOldValue + ", CheckNewValue=" + p_CheckNewValue); + + // Single Change or All Customizations + String sql = "SELECT * FROM AD_ChangeLog WHERE AD_ChangeLog_ID=? " + + "ORDER BY AD_Table_ID, Record_ID, AD_Column_ID"; + if (p_AD_ChangeLog_ID == 0) + sql = "SELECT * FROM AD_ChangeLog WHERE IsCustomization='Y' AND IsActive='Y' " + + "ORDER BY AD_Table_ID, AD_ChangeLog_ID, Record_ID, AD_Column_ID"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + if (p_AD_ChangeLog_ID != 0) + pstmt.setInt (1, p_AD_ChangeLog_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + createStatement (new MChangeLog(getCtx(), rs, get_TrxName()), get_TrxName()); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // final call + executeStatement(); + + return "@OK@: " + m_ok + " - @Errors@: " + m_errors + " - @Failed@: " + m_checkFailed; + } // doIt + + + /** + * Create Statement + * @param cLog log + * @param trxName trx + */ + private void createStatement (MChangeLog cLog, String trxName) + { + // New Table + if (m_table != null) + { + if (cLog.getAD_Table_ID() != m_table.getAD_Table_ID()) + { + executeStatement(); + m_table = null; + } + } + if (m_table == null) + m_table = new MTable (getCtx(), cLog.getAD_Table_ID(), trxName); + + // New Record + if (m_sqlUpdate != null && cLog.getRecord_ID() != m_oldRecord_ID) + executeStatement(); + + // Column Info + m_column = new MColumn (getCtx(), cLog.getAD_Column_ID(), get_TrxName()); + // Same Column twice + if (m_columns.contains(m_column.getColumnName())) + executeStatement(); + m_columns.add(m_column.getColumnName()); + + // Create new Statement + if (m_sqlUpdate == null) + { + String tableName = m_table.getTableName(); + m_keyColumn = m_table.getTableName() + "_ID"; + if (tableName.equals("AD_Ref_Table")) + m_keyColumn = "AD_Reference_ID"; + // + m_sqlUpdate = new StringBuffer ("UPDATE ") + .append(tableName) + .append(" SET "); + // Single Key Only + m_sqlUpdateWhere = new StringBuffer (" WHERE ") + .append(m_keyColumn).append("=").append(cLog.getRecord_ID()); + m_oldRecord_ID = cLog.getRecord_ID(); + + // Insert - new value is null and UnDo only + m_isInsert = cLog.isNewNull() && p_CheckNewValue != null; + if (m_isInsert) + { + m_sqlInsert = new StringBuffer ("INSERT INTO ") + .append(tableName).append("(") + .append(m_keyColumn); + m_sqlInsertValue = new StringBuffer (") VALUES (") + .append(cLog.getRecord_ID()); + if (!m_keyColumn.equals(m_column.getColumnName())) + { + m_sqlInsert.append(",").append(m_column.getColumnName()); + m_sqlInsertValue.append(",").append(getSQLValue(cLog.getOldValue())); + } + } + m_numberColumns = 1; + } + // Just new Column + else + { + m_sqlUpdate.append(", "); + // Insert + if (m_isInsert) + m_isInsert = cLog.isNewNull(); + if (m_isInsert && !m_keyColumn.equals(m_column.getColumnName())) + { + m_sqlInsert.append(",").append(m_column.getColumnName()); + m_sqlInsertValue.append(",").append(getSQLValue(cLog.getOldValue())); + } + m_numberColumns++; + } + + // Update Set clause -- columnName=value + m_sqlUpdate.append(m_column.getColumnName()) + .append("="); + // UnDo a <- (b) + if (p_CheckNewValue != null) + { + m_sqlUpdate.append(getSQLValue(cLog.getOldValue())); + if (p_CheckNewValue.booleanValue()) + m_sqlUpdateWhere.append(" AND ").append(m_column.getColumnName()) + .append("=").append(getSQLValue(cLog.getNewValue())); + } + // ReDo (a) -> b + else if (p_CheckOldValue != null) + { + m_sqlUpdate.append(getSQLValue(cLog.getNewValue())); + if (p_CheckOldValue.booleanValue()) + m_sqlUpdateWhere.append(" AND ").append(m_column.getColumnName()) + .append("=").append(getSQLValue(cLog.getOldValue())); + } + } // createStatement + + /** + * Get SQL Value + * @param value string value + * @return sql compliant value + */ + private String getSQLValue (String value) + { + if (value == null || value.length() == 0 || value.equals("NULL")) + return "NULL"; + + // Data Types + if (DisplayType.isNumeric (m_column.getAD_Reference_ID()) + || DisplayType.isID (m_column.getAD_Reference_ID()) ) + return value; + if (DisplayType.YesNo == m_column.getAD_Reference_ID()) + { + if (value.equals("true")) + return "'Y'"; + else + return "'N'"; + } + if (DisplayType.isDate(m_column.getAD_Reference_ID()) ) + return DB.TO_DATE (Timestamp.valueOf(value)); + + // String, etc. + return DB.TO_STRING(value); + } // getSQLValue + + + /** + * Execute Statement + * @return true if OK + */ + private boolean executeStatement() + { + if (m_sqlUpdate == null) + return false; + int no = 0; + + // Insert SQL + if (m_isInsert && m_numberColumns > 2) + { + m_sqlInsert.append(m_sqlInsertValue).append(")"); + log.info(m_sqlInsert.toString()); + // + no = DB.executeUpdate(m_sqlInsert.toString(), get_TrxName()); + if (no == -1) + { + // log.warning("Insert failed - " + m_sqlInsert); + m_errors++; + } + else if (no == 0) + { + log.warning("Insert failed - " + m_sqlInsert); + m_checkFailed++; + } + else + m_ok++; + } + else // Update SQL + { + m_sqlUpdate.append(m_sqlUpdateWhere); + log.info(m_sqlUpdate.toString()); + // + no = DB.executeUpdate(m_sqlUpdate.toString(), get_TrxName()); + if (no == -1) + { + // log.warning("Failed - " + m_sqlUpdate); + m_errors++; + } + else if (no == 0) + { + log.warning("Failed - " + m_sqlUpdate); + m_checkFailed++; + } + else + m_ok++; + } + // Reset + m_sqlUpdate = null; + m_sqlUpdateWhere = null; + m_sqlInsert = null; + m_sqlInsertValue = null; + m_columns = new ArrayList(); + return no > 0; + } // executeStatement + + /** + * Set Customization Flag + * @return summary + */ + private String setCustomization() + { + log.info(""); + String sql = "UPDATE AD_ChangeLog SET IsCustomization='N' WHERE IsCustomization='Y'"; + int resetNo = DB.executeUpdate(sql, get_TrxName()); + + int updateNo = 0; + // Get Tables + sql = "SELECT * FROM AD_Table t " + // Table with EntityType + + "WHERE EXISTS (SELECT * FROM AD_Column c " + + "WHERE t.AD_Table_ID=c.AD_Table_ID AND c.ColumnName='EntityType')" + // Changed Tables + + " AND EXISTS (SELECT * FROM AD_ChangeLog l " + + "WHERE t.AD_Table_ID=l.AD_Table_ID)"; + StringBuffer update = null; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MTable table = new MTable (getCtx(), rs, get_TrxName()); + + String tableName = table.getTableName(); + String columnName = tableName + "_ID"; + if (tableName.equals("AD_Ref_Table")) + columnName = "AD_Reference_ID"; + update = new StringBuffer ("UPDATE AD_ChangeLog SET IsCustomization='Y' " + + "WHERE AD_Table_ID=").append(table.getAD_Table_ID()); + update.append (" AND Record_ID IN (SELECT ") + .append (columnName) + .append (" FROM ").append(tableName) + .append (" WHERE EntityType IN ('D','C'))"); + int no = DB.executeUpdate(update.toString(), get_TrxName()); + log.config(table.getTableName() + " = " + no); + updateNo += no; + + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql + " --- " + update, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + return "@Reset@: " + resetNo + " - @Updated@: " + updateNo; + } // setCustomization + +} // ChangeLogProcess diff --git a/base/src/org/compiere/process/ColumnEncryption.java b/base/src/org/compiere/process/ColumnEncryption.java new file mode 100644 index 0000000000..f35a824e8d --- /dev/null +++ b/base/src/org/compiere/process/ColumnEncryption.java @@ -0,0 +1,178 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Column Encryption Test + * + * @author Jorg Janke + * @version $Id: ColumnEncryption.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ColumnEncryption extends SvrProcess +{ + /** Enable/Disable Encryption */ + private boolean p_IsEncrypted = false; + /** Change Encryption Settings */ + private boolean p_ChangeSetting = false; + /** Maximum Length */ + private int p_MaxLength = 0; + /** Test Value */ + private String p_TestValue = null; + /** The Column */ + private int p_AD_Column_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("IsEncrypted")) + p_IsEncrypted = "Y".equals(para[i].getParameter()); + else if (name.equals("ChangeSetting")) + p_ChangeSetting = "Y".equals(para[i].getParameter()); + else if (name.equals("MaxLength")) + p_MaxLength = para[i].getParameterAsInt(); + else if (name.equals("TestValue")) + p_TestValue = (String)para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_AD_Column_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("AD_Column_ID=" + p_AD_Column_ID + + ", IsEncrypted=" + p_IsEncrypted + + ", ChangeSetting=" + p_ChangeSetting + + ", MaxLength=" + p_MaxLength); + MColumn column = new MColumn (getCtx(), p_AD_Column_ID, null); + if (column.get_ID() == 0 || column.get_ID() != p_AD_Column_ID) + throw new AdempiereUserError("@NotFound@ @AD_Column_ID@ - " + p_AD_Column_ID); + // + String columnName = column.getColumnName(); + int dt = column.getAD_Reference_ID(); + + // Can it be enabled? + if (column.isKey() + || column.isParent() + || column.isStandardColumn() + || column.isVirtualColumn() + || column.isIdentifier() + || column.isTranslated() + || DisplayType.isLookup(dt) + || DisplayType.isLOB(dt) + || "DocumentNo".equalsIgnoreCase(column.getColumnName()) + || "Value".equalsIgnoreCase(column.getColumnName()) + || "Name".equalsIgnoreCase(column.getColumnName())) + { + if (column.isEncrypted()) + { + column.setIsEncrypted(false); + column.save(); + } + return columnName + ": cannot be encrypted"; + } + + // Start + addLog(0, null, null, "Encryption Class = " + SecureEngine.getClassName()); + boolean error = false; + + // Test Value + if (p_TestValue != null && p_TestValue.length() > 0) + { + String encString = SecureEngine.encrypt(p_TestValue); + addLog(0, null, null, "Encrypted Test Value=" + encString); + String clearString = SecureEngine.decrypt(encString); + if (p_TestValue.equals(clearString)) + addLog(0, null, null, "Decrypted=" + clearString + + " (same as test value)"); + else + { + addLog(0, null, null, "Decrypted=" + clearString + + " (NOT the same as test value - check algorithm)"); + error = true; + } + int encLength = encString.length(); + addLog(0, null, null, "Test Length=" + p_TestValue.length() + " -> " + encLength); + if (encLength <= column.getFieldLength()) + addLog(0, null, null, "Encrypted Length (" + encLength + + ") fits into field (" + column.getFieldLength() + ")"); + else + { + addLog(0, null, null, "Encrypted Length (" + encLength + + ") does NOT fit into field (" + column.getFieldLength() + ") - resize field"); + error = true; + } + } + + // Length Test + if (p_MaxLength != 0) + { + String testClear = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + while (testClear.length() < p_MaxLength) + testClear += testClear; + testClear = testClear.substring(0, p_MaxLength); + log.config("Test=" + testClear + " (" + p_MaxLength + ")"); + // + String encString = SecureEngine.encrypt(testClear); + int encLength = encString.length(); + addLog(0, null, null, "Test Max Length=" + testClear.length() + " -> " + encLength); + if (encLength <= column.getFieldLength()) + addLog(0, null, null, "Encrypted Max Length (" + encLength + + ") fits into field (" + column.getFieldLength() + ")"); + else + { + addLog(0, null, null, "Encrypted Max Length (" + encLength + + ") does NOT fit into field (" + column.getFieldLength() + ") - resize field"); + error = true; + } + } + + if (p_IsEncrypted != column.isEncrypted()) + { + if (error || !p_ChangeSetting) + addLog(0, null, null, "Encryption NOT changed - Encryption=" + column.isEncrypted()); + else + { + column.setIsEncrypted(p_IsEncrypted); + if (column.save()) + addLog(0, null, null, "Encryption CHANGED - Encryption=" + column.isEncrypted()); + else + addLog(0, null, null, "Save Error"); + } + } + return "Encryption=" + column.isEncrypted(); + } // doIt + +} // EncryptionTest diff --git a/base/src/org/compiere/process/ColumnSync.java b/base/src/org/compiere/process/ColumnSync.java new file mode 100644 index 0000000000..9c66f723e6 --- /dev/null +++ b/base/src/org/compiere/process/ColumnSync.java @@ -0,0 +1,140 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.math.*; +import java.util.logging.*; + +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Synchronize Column with Database + * + * @author Victor P�rez, Jorg Janke + * @version $Id: ColumnSync.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ColumnSync extends SvrProcess +{ + /** The Column */ + private int p_AD_Column_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_AD_Column_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info("C_Column_ID=" + p_AD_Column_ID); + if (p_AD_Column_ID == 0) + throw new AdempiereUserError("@No@ @AD_Column_ID@"); + MColumn column = new MColumn (getCtx(), p_AD_Column_ID, get_TrxName()); + if (column.get_ID() == 0) + throw new AdempiereUserError("@NotFound@ @AD_Column_ID@ " + p_AD_Column_ID); + + MTable table = MTable.get(getCtx(), column.getAD_Table_ID()); + if (table.get_ID() == 0) + throw new AdempiereUserError("@NotFound@ @AD_Table_ID@ " + column.getAD_Table_ID()); + + // Find Column in Database + DatabaseMetaData md = DB.getConnectionRO().getMetaData(); + String catalog = DB.getDatabase().getCatalog(); + String schema = DB.getDatabase().getSchema(); + String tableName = table.getTableName(); + if (DB.isOracle()) + tableName = tableName.toUpperCase(); + + // begin vpj-cd e-evolution 08/01/2005 PostgreSQL + if (DB.isPostgreSQL()) + tableName = tableName.toLowerCase(); + // end vpj-cd e-evolution 08/01/2005 PostgreSQL + + int noColumns = 0; + String sql = null; + // + ResultSet rs = md.getColumns(catalog, schema, tableName, null); + while (rs.next()) + { + noColumns++; + String columnName = rs.getString ("COLUMN_NAME"); + if (!columnName.equalsIgnoreCase(column.getColumnName())) + continue; + + // update existing column + boolean notNull = DatabaseMetaData.columnNoNulls == rs.getInt("NULLABLE"); + sql = column.getSQLModify(table, column.isMandatory() != notNull); + break; + } + rs.close(); + rs = null; + + // No Table + if (noColumns == 0) + sql = table.getSQLCreate (); + // No existing column + else if (sql == null) + sql = column.getSQLAdd(table); + + int no = 0; + if (sql.indexOf(DB.SQLSTATEMENT_SEPARATOR) == -1) + { + no = DB.executeUpdate(sql, false, get_TrxName()); + addLog (0, null, new BigDecimal(no), sql); + } + else + { + String statements[] = sql.split(DB.SQLSTATEMENT_SEPARATOR); + for (int i = 0; i < statements.length; i++) + { + int count = DB.executeUpdate(statements[i], false, get_TrxName()); + addLog (0, null, new BigDecimal(count), statements[i]); + no += count; + } + } + + if (no == -1) + { + String msg = "@Error@ "; + ValueNamePair pp = CLogger.retrieveError(); + if (pp != null) + msg = pp.getName() + " - "; + msg += sql; + throw new AdempiereUserError (msg); + } + return sql; + } // doIt + +} // ColumnSync diff --git a/base/src/org/compiere/process/CommissionAPInvoice.java b/base/src/org/compiere/process/CommissionAPInvoice.java new file mode 100644 index 0000000000..3e9adf1707 --- /dev/null +++ b/base/src/org/compiere/process/CommissionAPInvoice.java @@ -0,0 +1,97 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + + +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Create AP Invoices for Commission + * + * @author Jorg Janke + * @version $Id: CommissionAPInvoice.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class CommissionAPInvoice extends SvrProcess +{ + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Perform process. + * @return Message (variables are parsed) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("doIt - C_CommissionRun_ID=" + getRecord_ID()); + // Load Data + MCommissionRun comRun = new MCommissionRun (getCtx(), getRecord_ID(), get_TrxName()); + if (comRun.get_ID() == 0) + throw new IllegalArgumentException("CommissionAPInvoice - No Commission Run"); + if (Env.ZERO.compareTo(comRun.getGrandTotal()) == 0) + throw new IllegalArgumentException("@GrandTotal@ = 0"); + MCommission com = new MCommission (getCtx(), comRun.getC_Commission_ID(), get_TrxName()); + if (com.get_ID() == 0) + throw new IllegalArgumentException("CommissionAPInvoice - No Commission"); + if (com.getC_Charge_ID() == 0) + throw new IllegalArgumentException("CommissionAPInvoice - No Charge on Commission"); + MBPartner bp = new MBPartner (getCtx(), com.getC_BPartner_ID(), get_TrxName()); + if (bp.get_ID() == 0) + throw new IllegalArgumentException("CommissionAPInvoice - No BPartner"); + + // Create Invoice + MInvoice invoice = new MInvoice (getCtx(), 0, null); + invoice.setClientOrg(com.getAD_Client_ID(), com.getAD_Org_ID()); + invoice.setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_APInvoice); // API + invoice.setBPartner(bp); + // invoice.setDocumentNo (comRun.getDocumentNo()); // may cause unique constraint + invoice.setSalesRep_ID(getAD_User_ID()); // caller + // + if (com.getC_Currency_ID() != invoice.getC_Currency_ID()) + throw new IllegalArgumentException("CommissionAPInvoice - Currency of PO Price List not Commission Currency"); + // + if (!invoice.save()) + throw new IllegalStateException("CommissionAPInvoice - cannot save Invoice"); + + // Create Invoice Line + MInvoiceLine iLine = new MInvoiceLine(invoice); + iLine.setC_Charge_ID(com.getC_Charge_ID()); + iLine.setQty(1); + iLine.setPrice(comRun.getGrandTotal()); + iLine.setTax(); + if (!iLine.save()) + throw new IllegalStateException("CommissionAPInvoice - cannot save Invoice Line"); + // + return "@C_Invoice_ID@ = " + invoice.getDocumentNo(); + } // doIt + +} // CommissionAPInvoice diff --git a/base/src/org/compiere/process/CommissionCalc.java b/base/src/org/compiere/process/CommissionCalc.java new file mode 100644 index 0000000000..e8dd72802f --- /dev/null +++ b/base/src/org/compiere/process/CommissionCalc.java @@ -0,0 +1,380 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.text.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Commission Calculation + * + * @author Jorg Janke + * @version $Id: CommissionCalc.java,v 1.3 2006/09/25 00:59:41 jjanke Exp $ + */ +public class CommissionCalc extends SvrProcess +{ + private Timestamp p_StartDate; + // + private Timestamp m_EndDate; + private MCommission m_com; + // + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("StartDate")) + p_StartDate = (Timestamp)para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perform process. + * @return Message (text with variables) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("C_Commission_ID=" + getRecord_ID() + ", StartDate=" + p_StartDate); + if (p_StartDate == null) + p_StartDate = new Timestamp (System.currentTimeMillis()); + m_com = new MCommission (getCtx(), getRecord_ID(), get_TrxName()); + if (m_com.get_ID() == 0) + throw new AdempiereUserError ("No Commission"); + + // Create Commission + MCommissionRun comRun = new MCommissionRun (m_com); + setStartEndDate(); + comRun.setStartDate(p_StartDate); + // 01-Jan-2000 - 31-Jan-2001 - USD + SimpleDateFormat format = DisplayType.getDateFormat(DisplayType.Date); + String description = format.format(p_StartDate) + + " - " + format.format(m_EndDate) + + " - " + MCurrency.getISO_Code(getCtx(), m_com.getC_Currency_ID()); + comRun.setDescription(description); + if (!comRun.save()) + throw new AdempiereSystemError ("Could not save Commission Run"); + + MCommissionLine[] lines = m_com.getLines(); + for (int i = 0; i < lines.length; i++) + { + // Amt for Line - Updated By Trigger + MCommissionAmt comAmt = new MCommissionAmt (comRun, lines[i].getC_CommissionLine_ID()); + if (!comAmt.save()) + throw new AdempiereSystemError ("Could not save Commission Amt"); + // + StringBuffer sql = new StringBuffer(); + if (MCommission.DOCBASISTYPE_Receipt.equals(m_com.getDocBasisType())) + { + if (m_com.isListDetails()) + { + sql.append("SELECT h.C_Currency_ID, (l.LineNetAmt*al.Amount/h.GrandTotal) AS Amt," + + " (l.QtyInvoiced*al.Amount/h.GrandTotal) AS Qty," + + " NULL, l.C_InvoiceLine_ID, p.DocumentNo||'_'||h.DocumentNo," + + " COALESCE(prd.Value,l.Description), h.DateInvoiced " + + "FROM C_Payment p" + + " INNER JOIN C_AllocationLine al ON (p.C_Payment_ID=al.C_Payment_ID)" + + " INNER JOIN C_Invoice h ON (al.C_Invoice_ID = h.C_Invoice_ID)" + + " INNER JOIN C_InvoiceLine l ON (h.C_Invoice_ID = l.C_Invoice_ID) " + + " LEFT OUTER JOIN M_Product prd ON (l.M_Product_ID = prd.M_Product_ID) " + + "WHERE p.DocStatus IN ('CL','CO','RE')" + + " AND h.IsSOTrx='Y'" + + " AND p.AD_Client_ID = ?" + + " AND p.DateTrx BETWEEN ? AND ?"); + } + else + { + sql.append("SELECT h.C_Currency_ID, SUM(l.LineNetAmt*al.Amount/h.GrandTotal) AS Amt," + + " SUM(l.QtyInvoiced*al.Amount/h.GrandTotal) AS Qty," + + " NULL, NULL, NULL, NULL, MAX(h.DateInvoiced) " + + "FROM C_Payment p" + + " INNER JOIN C_AllocationLine al ON (p.C_Payment_ID=al.C_Payment_ID)" + + " INNER JOIN C_Invoice h ON (al.C_Invoice_ID = h.C_Invoice_ID)" + + " INNER JOIN C_InvoiceLine l ON (h.C_Invoice_ID = l.C_Invoice_ID) " + + "WHERE p.DocStatus IN ('CL','CO','RE')" + + " AND h.IsSOTrx='Y'" + + " AND p.AD_Client_ID = ?" + + " AND p.DateTrx BETWEEN ? AND ?"); + } + } + else if (MCommission.DOCBASISTYPE_Order.equals(m_com.getDocBasisType())) + { + if (m_com.isListDetails()) + { + sql.append("SELECT h.C_Currency_ID, l.LineNetAmt, l.QtyOrdered, " + + "l.C_OrderLine_ID, NULL, h.DocumentNo," + + " COALESCE(prd.Value,l.Description),h.DateOrdered " + + "FROM C_Order h" + + " INNER JOIN C_OrderLine l ON (h.C_Order_ID = l.C_Order_ID)" + + " LEFT OUTER JOIN M_Product prd ON (l.M_Product_ID = prd.M_Product_ID) " + + "WHERE h.DocStatus IN ('CL','CO')" + + " AND h.IsSOTrx='Y'" + + " AND h.AD_Client_ID = ?" + + " AND h.DateOrdered BETWEEN ? AND ?"); + } + else + { + sql.append("SELECT h.C_Currency_ID, SUM(l.LineNetAmt) AS Amt," + + " SUM(l.QtyOrdered) AS Qty, " + + "NULL, NULL, NULL, NULL, MAX(h.DateOrdered) " + + "FROM C_Order h" + + " INNER JOIN C_OrderLine l ON (h.C_Order_ID = l.C_Order_ID) " + + "WHERE h.DocStatus IN ('CL','CO')" + + " AND h.IsSOTrx='Y'" + + " AND h.AD_Client_ID = ?" + + " AND h.DateOrdered BETWEEN ? AND ?"); + } + } + else // Invoice Basis + { + if (m_com.isListDetails()) + { + sql.append("SELECT h.C_Currency_ID, l.LineNetAmt, l.QtyInvoiced, " + + "NULL, l.C_InvoiceLine_ID, h.DocumentNo," + + " COALESCE(prd.Value,l.Description),h.DateInvoiced " + + "FROM C_Invoice h" + + " INNER JOIN C_InvoiceLine l ON (h.C_Invoice_ID = l.C_Invoice_ID)" + + " LEFT OUTER JOIN M_Product prd ON (l.M_Product_ID = prd.M_Product_ID) " + + "WHERE h.DocStatus IN ('CL','CO','RE')" + + " AND h.IsSOTrx='Y'" + + " AND h.AD_Client_ID = ?" + + " AND h.DateInvoiced BETWEEN ? AND ?"); + } + else + { + sql.append("SELECT h.C_Currency_ID, SUM(l.LineNetAmt) AS Amt," + + " SUM(l.QtyInvoiced) AS Qty, " + + "NULL, NULL, NULL, NULL, MAX(h.DateInvoiced) " + + "FROM C_Invoice h" + + " INNER JOIN C_InvoiceLine l ON (h.C_Invoice_ID = l.C_Invoice_ID) " + + "WHERE h.DocStatus IN ('CL','CO','RE')" + + " AND h.IsSOTrx='Y'" + + " AND h.AD_Client_ID = ?" + + " AND h.DateInvoiced BETWEEN ? AND ?"); + } + } + // CommissionOrders/Invoices + if (lines[i].isCommissionOrders()) + { + MUser[] users = MUser.getOfBPartner(getCtx(), m_com.getC_BPartner_ID()); + if (users == null || users.length == 0) + throw new AdempiereUserError ("Commission Business Partner has no Users/Contact"); + if (users.length == 1) + { + int SalesRep_ID = users[0].getAD_User_ID(); + sql.append(" AND h.SalesRep_ID=").append(SalesRep_ID); + } + else + { + log.warning("Not 1 User/Contact for C_BPartner_ID=" + + m_com.getC_BPartner_ID() + " but " + users.length); + sql.append(" AND h.SalesRep_ID IN (SELECT AD_User_ID FROM AD_User WHERE C_BPartner_ID=") + .append(m_com.getC_BPartner_ID()).append(")"); + } + } + // Organization + if (lines[i].getOrg_ID() != 0) + sql.append(" AND h.AD_Org_ID=").append(lines[i].getOrg_ID()); + // BPartner + if (lines[i].getC_BPartner_ID() != 0) + sql.append(" AND h.C_BPartner_ID=").append(lines[i].getC_BPartner_ID()); + // BPartner Group + if (lines[i].getC_BP_Group_ID() != 0) + sql.append(" AND h.C_BPartner_ID IN " + + "(SELECT C_BPartner_ID FROM C_BPartner WHERE C_BP_Group_ID=").append(lines[i].getC_BP_Group_ID()).append(")"); + // Sales Region + if (lines[i].getC_SalesRegion_ID() != 0) + sql.append(" AND h.C_BPartner_Location_ID IN " + + "(SELECT C_BPartner_Location_ID FROM C_BPartner_Location WHERE C_SalesRegion_ID=").append(lines[i].getC_SalesRegion_ID()).append(")"); + // Product + if (lines[i].getM_Product_ID() != 0) + sql.append(" AND l.M_Product_ID=").append(lines[i].getM_Product_ID()); + // Product Category + if (lines[i].getM_Product_Category_ID() != 0) + sql.append(" AND l.M_Product_ID IN " + + "(SELECT M_Product_ID FROM M_Product WHERE M_Product_Category_ID=").append(lines[i].getM_Product_Category_ID()).append(")"); + // Grouping + if (!m_com.isListDetails()) + sql.append(" GROUP BY h.C_Currency_ID"); + // + log.fine("Line=" + lines[i].getLine() + " - " + sql); + // + createDetail(sql.toString(), comAmt); + comAmt.calculateCommission(); + comAmt.save(); + } // for all commission lines + + // comRun.updateFromAmt(); + // comRun.save(); + + // Save Last Run + m_com.setDateLastRun (p_StartDate); + m_com.save(); + + return "@C_CommissionRun_ID@ = " + comRun.getDocumentNo() + + " - " + comRun.getDescription(); + } // doIt + + /** + * Set Start and End Date + */ + private void setStartEndDate() + { + GregorianCalendar cal = new GregorianCalendar(Language.getLoginLanguage().getLocale()); + cal.setTimeInMillis(p_StartDate.getTime()); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + // Yearly + if (MCommission.FREQUENCYTYPE_Yearly.equals(m_com.getFrequencyType())) + { + cal.set(Calendar.DAY_OF_YEAR, 1); + p_StartDate = new Timestamp (cal.getTimeInMillis()); + // + cal.add(Calendar.YEAR, 1); + cal.add(Calendar.DAY_OF_YEAR, -1); + m_EndDate = new Timestamp (cal.getTimeInMillis()); + + } + // Quarterly + else if (MCommission.FREQUENCYTYPE_Quarterly.equals(m_com.getFrequencyType())) + { + cal.set(Calendar.DAY_OF_MONTH, 1); + int month = cal.get(Calendar.MONTH); + if (month < Calendar.APRIL) + cal.set(Calendar.MONTH, Calendar.JANUARY); + else if (month < Calendar.JULY) + cal.set(Calendar.MONTH, Calendar.APRIL); + else if (month < Calendar.OCTOBER) + cal.set(Calendar.MONTH, Calendar.JULY); + else + cal.set(Calendar.MONTH, Calendar.OCTOBER); + p_StartDate = new Timestamp (cal.getTimeInMillis()); + // + cal.add(Calendar.MONTH, 3); + cal.add(Calendar.DAY_OF_YEAR, -1); + m_EndDate = new Timestamp (cal.getTimeInMillis()); + } + // Weekly + else if (MCommission.FREQUENCYTYPE_Weekly.equals(m_com.getFrequencyType())) + { + cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); + p_StartDate = new Timestamp (cal.getTimeInMillis()); + // + cal.add(Calendar.DAY_OF_YEAR, 7); + m_EndDate = new Timestamp (cal.getTimeInMillis()); + } + // Monthly + else + { + cal.set(Calendar.DAY_OF_MONTH, 1); + p_StartDate = new Timestamp (cal.getTimeInMillis()); + // + cal.add(Calendar.MONTH, 1); + cal.add(Calendar.DAY_OF_YEAR, -1); + m_EndDate = new Timestamp (cal.getTimeInMillis()); + } + log.fine("setStartEndDate = " + p_StartDate + " - " + m_EndDate); + + /** + String sd = DB.TO_DATE(p_StartDate, true); + StringBuffer sql = new StringBuffer ("SELECT "); + if (MCommission.FREQUENCYTYPE_Quarterly.equals(m_com.getFrequencyType())) + sql.append("TRUNC(").append(sd).append(", 'Q'), TRUNC(").append(sd).append("+92, 'Q')-1"); + else if (MCommission.FREQUENCYTYPE_Weekly.equals(m_com.getFrequencyType())) + sql.append("TRUNC(").append(sd).append(", 'DAY'), TRUNC(").append(sd).append("+7, 'DAY')-1"); + else // Month + sql.append("TRUNC(").append(sd).append(", 'MM'), TRUNC(").append(sd).append("+31, 'MM')-1"); + sql.append(" FROM DUAL"); + **/ + } // setStartEndDate + + /** + * Create Commission Detail + * @param sql sql statement + * @param comAmt parent + */ + private void createDetail (String sql, MCommissionAmt comAmt) + { + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, m_com.getAD_Client_ID()); + pstmt.setTimestamp(2, p_StartDate); + pstmt.setTimestamp(3, m_EndDate); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + // CommissionAmount, C_Currency_ID, Amt, Qty, + MCommissionDetail cd = new MCommissionDetail (comAmt, + rs.getInt(1), rs.getBigDecimal(2), rs.getBigDecimal(3)); + + // C_OrderLine_ID, C_InvoiceLine_ID, + cd.setLineIDs(rs.getInt(4), rs.getInt(5)); + + // Reference, Info, + String s = rs.getString(6); + if (s != null) + cd.setReference(s); + s = rs.getString(7); + if (s != null) + cd.setInfo(s); + + // Date + Timestamp date = rs.getTimestamp(8); + cd.setConvertedAmt(date); + + // + if (!cd.save()) // creates memory leak + throw new IllegalArgumentException ("CommissionCalc - Detail Not saved"); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "createDetail", e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + } // createDetail + +} // CommissionCalc diff --git a/base/src/org/compiere/process/CommissionCopy.java b/base/src/org/compiere/process/CommissionCopy.java new file mode 100644 index 0000000000..deba738436 --- /dev/null +++ b/base/src/org/compiere/process/CommissionCopy.java @@ -0,0 +1,76 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Copy Commission + * + * @author Jorg Janke + * @version $Id: CommissionCopy.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class CommissionCopy extends SvrProcess +{ + /** From Commission */ + private int p_C_Commission_ID = 0; + /** To Commission */ + private int p_C_CommissionTo_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_Commission_ID")) + p_C_Commission_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + p_C_CommissionTo_ID = getRecord_ID(); + } // prepare + + /** + * Process - copy + * @return message + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("doIt - C_Commission_ID=" + p_C_Commission_ID + " - copy to " + p_C_CommissionTo_ID); + MCommission comFrom = new MCommission (getCtx(), p_C_Commission_ID, get_TrxName()); + if (comFrom.get_ID() == 0) + throw new AdempiereUserError ("No From Commission"); + MCommission comTo = new MCommission (getCtx(), p_C_CommissionTo_ID, get_TrxName()); + if (comTo.get_ID() == 0) + throw new AdempiereUserError ("No To Commission"); + + // + int no = comTo.copyLinesFrom(comFrom); + return "@Copied@: " + no; + } // doIt + +} // CommissionCopy diff --git a/base/src/org/compiere/process/CopyFromInvoice.java b/base/src/org/compiere/process/CopyFromInvoice.java new file mode 100644 index 0000000000..960fe7ca50 --- /dev/null +++ b/base/src/org/compiere/process/CopyFromInvoice.java @@ -0,0 +1,72 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.util.logging.*; +import org.compiere.model.*; + +/** + * Copy Invoice Lines + * + * @author Jorg Janke + * @version $Id: CopyFromInvoice.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class CopyFromInvoice extends SvrProcess +{ + private int m_C_Invoice_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_Invoice_ID")) + m_C_Invoice_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Perform process. + * @return Message + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + int To_C_Invoice_ID = getRecord_ID(); + log.info("From C_Invoice_ID=" + m_C_Invoice_ID + " to " + To_C_Invoice_ID); + if (To_C_Invoice_ID == 0) + throw new IllegalArgumentException("Target C_Invoice_ID == 0"); + if (m_C_Invoice_ID == 0) + throw new IllegalArgumentException("Source C_Invoice_ID == 0"); + MInvoice from = new MInvoice (getCtx(), m_C_Invoice_ID, null); + MInvoice to = new MInvoice (getCtx(), To_C_Invoice_ID, null); + // + int no = to.copyLinesFrom (from, false, false); + // + return "@Copied@=" + no; + } // doIt + +} // CopyFromInvoice diff --git a/base/src/org/compiere/process/CopyFromJournal.java b/base/src/org/compiere/process/CopyFromJournal.java new file mode 100644 index 0000000000..5039be9372 --- /dev/null +++ b/base/src/org/compiere/process/CopyFromJournal.java @@ -0,0 +1,73 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + + +import java.math.*; +import java.util.logging.*; +import org.compiere.model.*; + +/** + * Copy GL Batch Journal/Lines + * + * @author Jorg Janke + * @version $Id: CopyFromJournal.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class CopyFromJournal extends SvrProcess +{ + private int m_GL_JournalBatch_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("GL_JournalBatch_ID")) + m_GL_JournalBatch_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + int To_GL_JournalBatch_ID = getRecord_ID(); + log.info("doIt - From GL_JournalBatch_ID=" + m_GL_JournalBatch_ID + " to " + To_GL_JournalBatch_ID); + if (To_GL_JournalBatch_ID == 0) + throw new IllegalArgumentException("Target GL_JournalBatch_ID == 0"); + if (m_GL_JournalBatch_ID == 0) + throw new IllegalArgumentException("Source GL_JournalBatch_ID == 0"); + MJournalBatch from = new MJournalBatch (getCtx(), m_GL_JournalBatch_ID, get_TrxName()); + MJournalBatch to = new MJournalBatch (getCtx(), To_GL_JournalBatch_ID, get_TrxName()); + // + int no = to.copyDetailsFrom (from); + // + return "@Copied@=" + no; + } // doIt + +} diff --git a/base/src/org/compiere/process/CopyFromOrder.java b/base/src/org/compiere/process/CopyFromOrder.java new file mode 100644 index 0000000000..e8cd43e106 --- /dev/null +++ b/base/src/org/compiere/process/CopyFromOrder.java @@ -0,0 +1,73 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.util.logging.*; +import org.compiere.model.*; + +/** + * Copy Order Lines + * + * @author Jorg Janke + * @version $Id: CopyFromOrder.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class CopyFromOrder extends SvrProcess +{ + /** The Order */ + private int p_C_Order_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_Order_ID")) + p_C_Order_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + int To_C_Order_ID = getRecord_ID(); + log.info("From C_Order_ID=" + p_C_Order_ID + " to " + To_C_Order_ID); + if (To_C_Order_ID == 0) + throw new IllegalArgumentException("Target C_Order_ID == 0"); + if (p_C_Order_ID == 0) + throw new IllegalArgumentException("Source C_Order_ID == 0"); + MOrder from = new MOrder (getCtx(), p_C_Order_ID, get_TrxName()); + MOrder to = new MOrder (getCtx(), To_C_Order_ID, get_TrxName()); + // + int no = to.copyLinesFrom (from, false, false); // no Attributes + // + return "@Copied@=" + no; + } // doIt + +} // CopyFromOrder diff --git a/base/src/org/compiere/process/CopyFromProject.java b/base/src/org/compiere/process/CopyFromProject.java new file mode 100644 index 0000000000..c2d297c335 --- /dev/null +++ b/base/src/org/compiere/process/CopyFromProject.java @@ -0,0 +1,72 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.util.logging.*; +import org.compiere.model.*; + +/** + * Copy Project Details + * + * @author Jorg Janke + * @version $Id: CopyFromProject.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class CopyFromProject extends SvrProcess +{ + private int m_C_Project_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_Project_ID")) + m_C_Project_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + int To_C_Project_ID = getRecord_ID(); + log.info("doIt - From C_Project_ID=" + m_C_Project_ID + " to " + To_C_Project_ID); + if (To_C_Project_ID == 0) + throw new IllegalArgumentException("Target C_Project_ID == 0"); + if (m_C_Project_ID == 0) + throw new IllegalArgumentException("Source C_Project_ID == 0"); + MProject from = new MProject (getCtx(), m_C_Project_ID, get_TrxName()); + MProject to = new MProject (getCtx(), To_C_Project_ID, get_TrxName()); + // + int no = to.copyDetailsFrom (from); + + return "@Copied@=" + no; + } // doIt + +} // CopyFromProject diff --git a/base/src/org/compiere/process/CopyOrder.java b/base/src/org/compiere/process/CopyOrder.java new file mode 100644 index 0000000000..755570076e --- /dev/null +++ b/base/src/org/compiere/process/CopyOrder.java @@ -0,0 +1,108 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; + +import org.compiere.model.*; + +/** + * Copy Order and optionally close + * + * @author Jorg Janke + * @version $Id: CopyOrder.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class CopyOrder extends SvrProcess +{ + /** Order to Copy */ + private int p_C_Order_ID = 0; + /** Document Type of new Order */ + private int p_C_DocType_ID = 0; + /** New Doc Date */ + private Timestamp p_DateDoc = null; + /** Close/Process Old Order */ + private boolean p_IsCloseDocument = false; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_Order_ID")) + p_C_Order_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_DocType_ID")) + p_C_DocType_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("DateDoc")) + p_DateDoc = (Timestamp)para[i].getParameter(); + else if (name.equals("IsCloseDocument")) + p_IsCloseDocument = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("C_Order_ID=" + p_C_Order_ID + + ", C_DocType_ID=" + p_C_DocType_ID + + ", CloseDocument=" + p_IsCloseDocument); + if (p_C_Order_ID == 0) + throw new IllegalArgumentException("No Order"); + MDocType dt = MDocType.get(getCtx(), p_C_DocType_ID); + if (dt.get_ID() == 0) + throw new IllegalArgumentException("No DocType"); + if (p_DateDoc == null) + p_DateDoc = new Timestamp (System.currentTimeMillis()); + // + MOrder from = new MOrder (getCtx(), p_C_Order_ID, get_TrxName()); + MOrder newOrder = MOrder.copyFrom (from, p_DateDoc, + dt.getC_DocType_ID(), dt.isSOTrx(), false, true, null); // copy ASI + newOrder.setC_DocTypeTarget_ID(p_C_DocType_ID); + boolean OK = newOrder.save(); + if (!OK) + throw new IllegalStateException("Could not create new Order"); + // + if (p_IsCloseDocument) + { + MOrder original = new MOrder (getCtx(), p_C_Order_ID, get_TrxName()); + original.setDocAction(MOrder.DOCACTION_Complete); + original.processIt(MOrder.DOCACTION_Complete); + original.save(); + original.setDocAction(MOrder.DOCACTION_Close); + original.processIt(MOrder.DOCACTION_Close); + original.save(); + } + // + // Env.setSOTrx(getCtx(), newOrder.isSOTrx()); + // return "@C_Order_ID@ " + newOrder.getDocumentNo(); + return dt.getName() + ": " + newOrder.getDocumentNo(); + } // doIt + +} // CopyOrder diff --git a/base/src/org/compiere/process/CostCreate.java b/base/src/org/compiere/process/CostCreate.java new file mode 100644 index 0000000000..5afc08ee71 --- /dev/null +++ b/base/src/org/compiere/process/CostCreate.java @@ -0,0 +1,73 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; + +import org.compiere.util.*; +import org.compiere.model.*; + +/** + * Create/Update Costing for Product + * + * @author Jorg Janke + * @version $Id: CostCreate.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class CostCreate extends SvrProcess +{ + /** Product */ + private int p_M_Product_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + // log.fine("prepare - " + para[i]); + if (para[i].getParameter() == null) + ; + else if (name.equals("M_Product_ID")) + p_M_Product_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perform process. + * @return Message (text with variables) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("M_Product_ID=" + p_M_Product_ID); + if (p_M_Product_ID == 0) + throw new AdempiereUserError("@NotFound@: @M_Product_ID@ = " + p_M_Product_ID); + MProduct product = MProduct.get(getCtx(), p_M_Product_ID); + if (product.get_ID() != p_M_Product_ID) + throw new AdempiereUserError("@NotFound@: @M_Product_ID@ = " + p_M_Product_ID); + // + if (MCostDetail.processProduct(product, get_TrxName())) + return "@OK@"; + return "@Error@"; + } // doIt + +} // CostCreate diff --git a/base/src/org/compiere/process/CostUpdate.java b/base/src/org/compiere/process/CostUpdate.java new file mode 100644 index 0000000000..1de560a468 --- /dev/null +++ b/base/src/org/compiere/process/CostUpdate.java @@ -0,0 +1,580 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Standard Cost Update + * + * @author Jorg Janke + * @version $Id: CostUpdate.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class CostUpdate extends SvrProcess +{ + /** Product Category */ + private int p_M_Product_Category_ID = 0; + /** Future Costs */ + private String p_SetFutureCostTo = null; + /** Standard Costs */ + private String p_SetStandardCostTo = null; + /** PLV */ + private int p_M_PriceList_Version_ID = 0; + + + private static final String TO_AveragePO = "A"; + private static final String TO_AverageInvoiceHistory = "DI"; + private static final String TO_AveragePOHistory = "DP"; + private static final String TO_FiFo = "F"; + private static final String TO_AverageInvoice = "I"; + private static final String TO_LiFo = "L"; + private static final String TO_PriceListLimit = "LL"; + private static final String TO_StandardCost = "S"; + private static final String TO_FutureStandardCost = "f"; + private static final String TO_LastInvoicePrice = "i"; + private static final String TO_LastPOPrice = "p"; + private static final String TO_OldStandardCost = "x"; + + /** Standard Cost Element */ + private MCostElement m_ce = null; + /** Client Accounting SChema */ + private MAcctSchema[] m_ass = null; + /** Map of Cost Elements */ + private HashMap m_ces = new HashMap(); + + + /** + * Prepare + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + // log.fine("prepare - " + para[i]); + if (para[i].getParameter() == null) + ; + else if (name.equals("M_Product_Category_ID")) + p_M_Product_Category_ID = para[i].getParameterAsInt(); + else if (name.equals("SetFutureCostTo")) + p_SetFutureCostTo = (String)para[i].getParameter(); + else if (name.equals("SetStandardCostTo")) + p_SetStandardCostTo = (String)para[i].getParameter(); + else if (name.equals("M_PriceList_Version_ID")) + p_M_PriceList_Version_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info("M_Product_Category_ID=" + p_M_Product_Category_ID + + ", Future=" + p_SetFutureCostTo + + ", Standard=" + p_SetStandardCostTo + + "; M_PriceList_Version_ID=" + p_M_PriceList_Version_ID); + if (p_SetFutureCostTo == null) + p_SetFutureCostTo = ""; + if (p_SetStandardCostTo == null) + p_SetStandardCostTo = ""; + // Nothing to Do + if (p_SetFutureCostTo.length() == 0 && p_SetStandardCostTo.length() == 0) + { + return "-"; + } + // PLV required + if (p_M_PriceList_Version_ID == 0 + && (p_SetFutureCostTo.equals(TO_PriceListLimit) || p_SetStandardCostTo.equals(TO_PriceListLimit))) + throw new AdempiereUserError ("@FillMandatory@ @M_PriceList_Version_ID@"); + + // Validate Source + if (!isValid(p_SetFutureCostTo)) + throw new AdempiereUserError ("@NotFound@ @M_CostElement_ID@ (Future) " + p_SetFutureCostTo); + if (!isValid(p_SetStandardCostTo)) + throw new AdempiereUserError ("@NotFound@ @M_CostElement_ID@ (Standard) " + p_SetStandardCostTo); + + // Prepare + MClient client = MClient.get(getCtx()); + m_ce = MCostElement.getMaterialCostElement(client, MAcctSchema.COSTINGMETHOD_StandardCosting); + if (m_ce.get_ID() == 0) + throw new AdempiereUserError ("@NotFound@ @M_CostElement_ID@ (StdCost)"); + log.config(m_ce.toString()); + m_ass = MAcctSchema.getClientAcctSchema(getCtx(), client.getAD_Client_ID()); + for (int i = 0; i < m_ass.length; i++) + createNew(m_ass[i]); + commit(); + + // Update Cost + int counter = update(); + + return "#" + counter; + } // doIt + + /** + * Costing Method must exist + * @param to test + * @return true valid + */ + private boolean isValid(String to) + { + if (p_SetFutureCostTo.length() == 0) + return true; + + String toTarget = to; + if (to.equals(TO_AverageInvoiceHistory)) + to = TO_AverageInvoice; + if (to.equals(TO_AveragePOHistory)) + to = TO_AveragePO; + if (to.equals(TO_FutureStandardCost)) + to = TO_StandardCost; + // + if (to.equals(TO_AverageInvoice) + || to.equals(TO_AveragePO) + || to.equals(TO_FiFo) + || to.equals(TO_LiFo) + || to.equals(TO_StandardCost)) + { + MCostElement ce = getCostElement(p_SetFutureCostTo); + return ce != null; + } + return true; + } // isValid + + /************************************************************************** + * Create New Standard Costs + * @param as accounting schema + */ + private void createNew (MAcctSchema as) + { + if (!as.getCostingLevel().equals(MAcctSchema.COSTINGLEVEL_Client)) + { + String txt = "Costing Level prevents creating new Costing records for " + as.getName(); + log.warning(txt); + addLog(0, null, null, txt); + return; + } + String sql = "SELECT * FROM M_Product p " + + "WHERE NOT EXISTS (SELECT * FROM M_Cost c WHERE c.M_Product_ID=p.M_Product_ID" + + " AND c.M_CostType_ID=? AND c.C_AcctSchema_ID=? AND c.M_CostElement_ID=?" + + " AND c.M_AttributeSetInstance_ID=0) " + + "AND AD_Client_ID=?"; + if (p_M_Product_Category_ID != 0) + sql += " AND M_Product_Category_ID=?"; + int counter = 0; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, as.getM_CostType_ID()); + pstmt.setInt (2, as.getC_AcctSchema_ID()); + pstmt.setInt (3, m_ce.getM_CostElement_ID()); + pstmt.setInt (4, as.getAD_Client_ID()); + if (p_M_Product_Category_ID != 0) + pstmt.setInt (5, p_M_Product_Category_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + if (createNew (new MProduct (getCtx(), rs, null), as)) + counter++; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + log.info("#" + counter); + addLog(0, null, new BigDecimal(counter), "Created for " + as.getName()); + } // createNew + + /** + * Create New Client level Costing Record + * @param product product + * @param as acct schema + * @return true if created + */ + private boolean createNew (MProduct product, MAcctSchema as) + { + MCost cost = MCost.get(product, 0, as, 0, m_ce.getM_CostElement_ID()); + if (cost.is_new()) + return cost.save(); + return false; + } // createNew + + /************************************************************************** + * Update Cost Records + * @return no updated + */ + private int update() + { + int counter = 0; + String sql = "SELECT * FROM M_Cost c WHERE M_CostElement_ID=?"; + if (p_M_Product_Category_ID != 0) + sql += " AND EXISTS (SELECT * FROM M_Product p " + + "WHERE c.M_Product_ID=p.M_Product_ID AND p.M_Product_Category_ID=?)"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, m_ce.getM_CostElement_ID()); + if (p_M_Product_Category_ID != 0) + pstmt.setInt (2, p_M_Product_Category_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MCost cost = new MCost (getCtx(), rs, get_TrxName()); + for (int i = 0; i < m_ass.length; i++) + { + // Update Costs only for default Cost Type + if (m_ass[i].getC_AcctSchema_ID() == cost.getC_AcctSchema_ID() + && m_ass[i].getM_CostType_ID() == cost.getM_CostType_ID()) + { + if (update (cost)) + counter++; + } + } + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + log.info("#" + counter); + addLog(0, null, new BigDecimal(counter), "@Updated@"); + return counter; + } // update + + /** + * Update Cost Records + * @param cost cost + * @return true if updated + * @throws Exception + */ + private boolean update (MCost cost) throws Exception + { + boolean updated = false; + if (p_SetFutureCostTo.equals(p_SetStandardCostTo)) + { + BigDecimal costs = getCosts(cost, p_SetFutureCostTo); + if (costs != null && costs.signum() != 0) + { + cost.setFutureCostPrice(costs); + cost.setCurrentCostPrice(costs); + updated = true; + } + } + else + { + if (p_SetStandardCostTo.length() > 0) + { + BigDecimal costs = getCosts(cost, p_SetStandardCostTo); + if (costs != null && costs.signum() != 0) + { + cost.setCurrentCostPrice(costs); + updated = true; + } + } + if (p_SetFutureCostTo.length() > 0) + { + BigDecimal costs = getCosts(cost, p_SetFutureCostTo); + if (costs != null && costs.signum() != 0) + { + cost.setFutureCostPrice(costs); + updated = true; + } + } + } + if (updated) + updated = cost.save(); + return updated; + } // update + + /** + * Get Costs + * @param cost cost + * @param to where to get costs from + * @return costs (could be 0) or null if not found + * @throws Exception + */ + private BigDecimal getCosts (MCost cost, String to) throws Exception + { + BigDecimal retValue = null; + + // Average Invoice + if (to.equals(TO_AverageInvoice)) + { + MCostElement ce = getCostElement(TO_AverageInvoice); + if (ce == null) + throw new AdempiereSystemError("CostElement not found: " + TO_AverageInvoice); + MCost xCost = MCost.get(getCtx(), cost.getAD_Client_ID(), cost.getAD_Org_ID(), cost.getM_Product_ID(), cost.getM_CostType_ID(), cost.getC_AcctSchema_ID(), ce.getM_CostElement_ID(), cost.getM_AttributeSetInstance_ID()); + if (xCost != null) + retValue = xCost.getCurrentCostPrice(); + } + // Average Invoice History + else if (to.equals(TO_AverageInvoiceHistory)) + { + MCostElement ce = getCostElement(TO_AverageInvoice); + if (ce == null) + throw new AdempiereSystemError("CostElement not found: " + TO_AverageInvoice); + MCost xCost = MCost.get(getCtx(), cost.getAD_Client_ID(), cost.getAD_Org_ID(), cost.getM_Product_ID(), cost.getM_CostType_ID(), cost.getC_AcctSchema_ID(), ce.getM_CostElement_ID(), cost.getM_AttributeSetInstance_ID()); + if (xCost != null) + retValue = xCost.getHistoryAverage(); + } + + // Average PO + else if (to.equals(TO_AveragePO)) + { + MCostElement ce = getCostElement(TO_AveragePO); + if (ce == null) + throw new AdempiereSystemError("CostElement not found: " + TO_AveragePO); + MCost xCost = MCost.get(getCtx(), cost.getAD_Client_ID(), cost.getAD_Org_ID(), cost.getM_Product_ID(), cost.getM_CostType_ID(), cost.getC_AcctSchema_ID(), ce.getM_CostElement_ID(), cost.getM_AttributeSetInstance_ID()); + if (xCost != null) + retValue = xCost.getCurrentCostPrice(); + } + // Average PO History + else if (to.equals(TO_AveragePOHistory)) + { + MCostElement ce = getCostElement(TO_AveragePO); + if (ce == null) + throw new AdempiereSystemError("CostElement not found: " + TO_AveragePO); + MCost xCost = MCost.get(getCtx(), cost.getAD_Client_ID(), cost.getAD_Org_ID(), cost.getM_Product_ID(), cost.getM_CostType_ID(), cost.getC_AcctSchema_ID(), ce.getM_CostElement_ID(), cost.getM_AttributeSetInstance_ID()); + if (xCost != null) + retValue = xCost.getHistoryAverage(); + } + + // FiFo + else if (to.equals(TO_FiFo)) + { + MCostElement ce = getCostElement(TO_FiFo); + if (ce == null) + throw new AdempiereSystemError("CostElement not found: " + TO_FiFo); + MCost xCost = MCost.get(getCtx(), cost.getAD_Client_ID(), cost.getAD_Org_ID(), cost.getM_Product_ID(), cost.getM_CostType_ID(), cost.getC_AcctSchema_ID(), ce.getM_CostElement_ID(), cost.getM_AttributeSetInstance_ID()); + if (xCost != null) + retValue = xCost.getCurrentCostPrice(); + } + + // Future Std Costs + else if (to.equals(TO_FutureStandardCost)) + retValue = cost.getFutureCostPrice(); + + // Last Inv Price + else if (to.equals(TO_LastInvoicePrice)) + { + MCostElement ce = getCostElement(TO_LastInvoicePrice); + if (ce != null) + { + MCost xCost = MCost.get(getCtx(), cost.getAD_Client_ID(), cost.getAD_Org_ID(), cost.getM_Product_ID(), cost.getM_CostType_ID(), cost.getC_AcctSchema_ID(), ce.getM_CostElement_ID(), cost.getM_AttributeSetInstance_ID()); + if (xCost != null) + retValue = xCost.getCurrentCostPrice(); + } + if (retValue == null) + { + MProduct product = MProduct.get(getCtx(), cost.getM_Product_ID()); + MAcctSchema as = MAcctSchema.get(getCtx(), cost.getC_AcctSchema_ID()); + retValue = MCost.getLastInvoicePrice(product, + cost.getM_AttributeSetInstance_ID(), cost.getAD_Org_ID(), as.getC_Currency_ID()); + } + } + + // Last PO Price + else if (to.equals(TO_LastPOPrice)) + { + MCostElement ce = getCostElement(TO_LastPOPrice); + if (ce != null) + { + MCost xCost = MCost.get(getCtx(), cost.getAD_Client_ID(), cost.getAD_Org_ID(), cost.getM_Product_ID(), cost.getM_CostType_ID(), cost.getC_AcctSchema_ID(), ce.getM_CostElement_ID(), cost.getM_AttributeSetInstance_ID()); + if (xCost != null) + retValue = xCost.getCurrentCostPrice(); + } + if (retValue == null) + { + MProduct product = MProduct.get(getCtx(), cost.getM_Product_ID()); + MAcctSchema as = MAcctSchema.get(getCtx(), cost.getC_AcctSchema_ID()); + retValue = MCost.getLastPOPrice(product, + cost.getM_AttributeSetInstance_ID(), cost.getAD_Org_ID(), as.getC_Currency_ID()); + } + } + + // FiFo + else if (to.equals(TO_LiFo)) + { + MCostElement ce = getCostElement(TO_LiFo); + if (ce == null) + throw new AdempiereSystemError("CostElement not found: " + TO_LiFo); + MCost xCost = MCost.get(getCtx(), cost.getAD_Client_ID(), cost.getAD_Org_ID(), cost.getM_Product_ID(), cost.getM_CostType_ID(), cost.getC_AcctSchema_ID(), ce.getM_CostElement_ID(), cost.getM_AttributeSetInstance_ID()); + if (xCost != null) + retValue = xCost.getCurrentCostPrice(); + } + + // Old Std Costs + else if (to.equals(TO_OldStandardCost)) + retValue = getOldCurrentCostPrice(cost); + + // Price List + else if (to.equals(TO_PriceListLimit)) + retValue = getPrice(cost); + + // Standard Costs + else if (to.equals(TO_StandardCost)) + retValue = cost.getCurrentCostPrice(); + + return retValue; + } // getCosts + + + /** + * Get Cost Element + * @param CostingMethod method + * @return costing element or null + */ + private MCostElement getCostElement (String CostingMethod) + { + MCostElement ce = m_ces.get(CostingMethod); + if (ce == null) + { + ce = MCostElement.getMaterialCostElement(getCtx(), CostingMethod); + m_ces.put(CostingMethod, ce); + } + return ce; + } // getCostElement + + /** + * Get Old Current Cost Price + * @param cost costs + * @return price if found + */ + private BigDecimal getOldCurrentCostPrice(MCost cost) + { + BigDecimal retValue = null; + String sql = "SELECT CostStandard, CurrentCostPrice " + + "FROM M_Product_Costing " + + "WHERE M_Product_ID=? AND C_AcctSchema_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, cost.getM_Product_ID()); + pstmt.setInt (2, cost.getC_AcctSchema_ID()); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + retValue = rs.getBigDecimal(1); + if (retValue == null || retValue.signum() == 0) + retValue = rs.getBigDecimal(2); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return retValue; + } // getOldCurrentCostPrice + + /** + * Get Price from Price List + * @param cost cost record + * @return price or null + */ + private BigDecimal getPrice (MCost cost) + { + BigDecimal retValue = null; + String sql = "SELECT PriceLimit " + + "FROM M_ProductPrice " + + "WHERE M_Product_ID=? AND M_PriceList_Version_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, cost.getM_Product_ID()); + pstmt.setInt (2, p_M_PriceList_Version_ID); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + retValue = rs.getBigDecimal(1); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return retValue; + } // getPrice + +} // CostUpdate diff --git a/base/src/org/compiere/process/DiscountSchemaReSeq.java b/base/src/org/compiere/process/DiscountSchemaReSeq.java new file mode 100644 index 0000000000..3b53fa31a1 --- /dev/null +++ b/base/src/org/compiere/process/DiscountSchemaReSeq.java @@ -0,0 +1,61 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Renumber Discount Schema + * + * @author Jorg Janke + * @version $Id: DiscountSchemaReSeq.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class DiscountSchemaReSeq extends SvrProcess +{ + /** Discount Schema */ + private int p_M_DiscountSchema_ID = 0; + + /** + * Prepare + * @see org.compiere.process.SvrProcess#prepare() + */ + protected void prepare () + { + p_M_DiscountSchema_ID = getRecord_ID(); + } // prepare + + /** + * Execute + * @return info + */ + protected String doIt () throws Exception + { + log.info("M_DiscountSchema_ID=" + p_M_DiscountSchema_ID); + if (p_M_DiscountSchema_ID == 0) + throw new AdempiereUserError("@M_DiscountSchema_ID@ = 0"); + MDiscountSchema ds = new MDiscountSchema(getCtx(), p_M_DiscountSchema_ID, get_TrxName()); + if (ds.get_ID() == 0) + throw new AdempiereUserError("@NotFound@ M_DiscountSchema_ID=" + p_M_DiscountSchema_ID); + // + int updated = ds.reSeq(); + + return "@Updated@ #" + updated; + } // doIt + +} // DiscountSchemaRenumber diff --git a/base/src/org/compiere/process/DistributionCreate.java b/base/src/org/compiere/process/DistributionCreate.java new file mode 100644 index 0000000000..773f0527ae --- /dev/null +++ b/base/src/org/compiere/process/DistributionCreate.java @@ -0,0 +1,218 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Create Distribution List Order + * + * @author Jorg Janke + * @version $Id: DistributionCreate.java,v 1.3 2006/07/30 00:51:01 jjanke Exp $ + */ +public class DistributionCreate extends SvrProcess +{ + /** Product */ + private int p_M_Product_ID = 0; + /** Quantity */ + private BigDecimal p_Qty; + /** Single Order */ + private boolean p_IsCreateSingleOrder; + /** Single Order BP */ + private int p_Bill_BPartner_ID; + /** SingleOrder Location */ + private int p_Bill_Location_ID; + /** Test Mode */ + private boolean p_IsTest; + /** Distribution List */ + private int p_M_DistributionList_ID; + +// DatePromised +// C_DocType_ID + + /** Distribution List */ + private MDistributionList m_dl; + /** Single Order */ + private MOrder m_singleOrder = null; + /** Product */ + private MProduct m_product = null; + /** Total Quantity */ + private BigDecimal m_totalQty = Env.ZERO; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + // log.fine("prepare - " + para[i]); + if (para[i].getParameter() == null) + ; + else if (name.equals("M_Product_ID")) + p_M_Product_ID = para[i].getParameterAsInt(); + else if (name.equals("Qty")) + p_Qty = (BigDecimal)para[i].getParameter(); + else if (name.equals("IsCreateSingleOrder")) + p_IsCreateSingleOrder = "Y".equals(para[i].getParameter()); + else if (name.equals("Bill_BPartner_ID")) + p_Bill_BPartner_ID = para[i].getParameterAsInt(); + else if (name.equals("p_Bill_Location_ID")) + p_Bill_Location_ID = para[i].getParameterAsInt(); + else if (name.equals("IsTest")) + p_IsTest = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_M_DistributionList_ID = getRecord_ID(); + } // prepare + + /** + * Perform process. + * @return Message (text with variables) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("M_DistributionList_ID=" + p_M_DistributionList_ID + + ", M_Product_ID=" + p_M_Product_ID + ", Qty=" + p_Qty + + ", Test=" + p_IsTest); + if (p_IsCreateSingleOrder) + log.info("SingleOrder=" + p_IsCreateSingleOrder + + ", BPartner_ID=" + p_Bill_BPartner_ID + + ", Location_ID=" + p_Bill_Location_ID); + // + if (p_M_DistributionList_ID == 0) + throw new IllegalArgumentException ("No Distribution List ID"); + m_dl = new MDistributionList(getCtx(), p_M_DistributionList_ID, get_TrxName()); + if (m_dl.get_ID() == 0) + throw new Exception ("Distribution List not found - M_DistributionList_ID=" + p_M_DistributionList_ID); + // + if (p_M_Product_ID == 0) + throw new IllegalArgumentException ("No Product"); + m_product = MProduct.get (getCtx(), p_M_Product_ID); + if (m_product.get_ID() == 0) + throw new Exception ("Product not found - M_Product_ID=" + p_M_Product_ID); + if (p_Qty == null || p_Qty.signum() != 1) + throw new IllegalArgumentException ("No Quantity"); + // + if (p_IsCreateSingleOrder && p_Bill_BPartner_ID == 0) + throw new IllegalArgumentException ("Invoice Business Partner required for single Order"); + // Create Single Order + if (!p_IsTest && p_IsCreateSingleOrder) + { + MBPartner bp = new MBPartner (getCtx(), p_Bill_BPartner_ID, get_TrxName()); + if (bp.get_ID() == 0) + throw new IllegalArgumentException("Single Business Partner not found - C_BPartner_ID=" + p_Bill_BPartner_ID); + // + m_singleOrder = new MOrder (getCtx(), 0, get_TrxName()); + m_singleOrder.setIsSOTrx(true); + m_singleOrder.setC_DocTypeTarget_ID(MOrder.DocSubTypeSO_Standard); + m_singleOrder.setBPartner(bp); + if (p_Bill_Location_ID != 0) + m_singleOrder.setC_BPartner_Location_ID(p_Bill_Location_ID); + if (!m_singleOrder.save()) + throw new IllegalStateException("Single Order not created"); + } + + MDistributionListLine[] lines = m_dl.getLines(); + int counter = 0; + for (int i = 0; i < lines.length; i++) + { + if (createOrder(lines[i])) + counter++; + } + + // Update Qty + if (m_singleOrder != null) + { + m_singleOrder.setDescription("# " + counter + " - " + m_totalQty); + m_singleOrder.save(); + } + + return "@Created@ #" + counter + " - @Qty@=" + m_totalQty; + } // doIt + + /** + * Create Order for Distribution Line + * @param dll Distribution Line + * @return true if created + */ + private boolean createOrder (MDistributionListLine dll) + { + MBPartner bp = new MBPartner (getCtx(), dll.getC_BPartner_ID(), get_TrxName()); + if (bp.get_ID() == 0) + throw new IllegalArgumentException("Business Partner not found - C_BPartner_ID=" + dll.getC_BPartner_ID()); + + // Create Order + MOrder order = m_singleOrder; + if (!p_IsTest && order == null) + { + order = new MOrder (getCtx(), 0, get_TrxName()); + order.setIsSOTrx(true); + order.setC_DocTypeTarget_ID(MOrder.DocSubTypeSO_Standard); + order.setBPartner(bp); + if (dll.getC_BPartner_Location_ID() != 0) + order.setC_BPartner_Location_ID(dll.getC_BPartner_Location_ID()); + if (!order.save()) + { + log.log(Level.SEVERE, "Order not saved"); + return false; + } + } + // Calculate Qty + BigDecimal ratio = dll.getRatio(); + BigDecimal qty = p_Qty.multiply(ratio); + if (qty.compareTo(Env.ZERO) != 0) + qty = qty.divide(m_dl.getRatioTotal(), m_product.getUOMPrecision(), BigDecimal.ROUND_HALF_UP); + BigDecimal minQty = dll.getMinQty(); + if (qty.compareTo(minQty) < 0) + qty = minQty; + m_totalQty = m_totalQty.add(qty); + // + if (p_IsTest) + { + addLog(0,null, qty, bp.getName()); + return false; + } + + // Create Order Line + MOrderLine line = new MOrderLine(order); + line.setC_BPartner_ID(dll.getC_BPartner_ID()); + if (dll.getC_BPartner_Location_ID() != 0) + line.setC_BPartner_Location_ID(dll.getC_BPartner_Location_ID()); + // + line.setM_Product_ID(p_M_Product_ID, true); + line.setQty(qty); + line.setPrice(); + if (!line.save()) + { + log.log(Level.SEVERE, "OrderLine not saved"); + return false; + } + + addLog(0,null, qty, order.getDocumentNo() + ": " + bp.getName()); + return true; + } // createOrder + +} // DistributionCreate diff --git a/base/src/org/compiere/process/DistributionRun.java b/base/src/org/compiere/process/DistributionRun.java new file mode 100644 index 0000000000..4c039c4a03 --- /dev/null +++ b/base/src/org/compiere/process/DistributionRun.java @@ -0,0 +1,505 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Create Distribution + * + * @author Jorg Janke + * @version $Id: DistributionRun.java,v 1.4 2006/07/30 00:51:02 jjanke Exp $ + */ +public class DistributionRun extends SvrProcess +{ + /** The Run to execute */ + private int p_M_DistributionRun_ID = 0; + /** Date Promised */ + private Timestamp p_DatePromised = null; + /** Dicument Type */ + private int p_C_DocType_ID = 0; + /** Test Mode */ + private boolean p_IsTest = false; + + /** Distribution Run */ + private MDistributionRun m_run = null; + /** Distribution Run Lines */ + private MDistributionRunLine[] m_runLines = null; + /** Distribution Run Details */ + private MDistributionRunDetail[] m_details = null; + + /** Date Ordered */ + private Timestamp m_DateOrdered = null; + /** Orders Created */ + private int m_counter = 0; + /** Document Type */ + private MDocType m_docType = null; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + // log.fine("prepare - " + para[i]); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_DocType_ID")) + p_C_DocType_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("DatePromised")) + p_DatePromised = (Timestamp)para[i].getParameter(); + else if (name.equals("IsTest")) + p_IsTest = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + p_M_DistributionRun_ID = getRecord_ID(); + } // prepare + + /** + * Perform process. + * @return Message (text with variables) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("M_DistributionRun_ID=" + p_M_DistributionRun_ID + + ", C_DocType_ID=" + p_C_DocType_ID + + ", DatePromised=" + p_DatePromised + + ", Test=" + p_IsTest); + // Distribution Run + if (p_M_DistributionRun_ID == 0) + throw new IllegalArgumentException ("No Distribution Run ID"); + m_run = new MDistributionRun(getCtx(), p_M_DistributionRun_ID, get_TrxName()); + if (m_run.get_ID() == 0) + throw new Exception ("Distribution Run not found - M_DistributionRun_ID=" + p_M_DistributionRun_ID); + m_runLines = m_run.getLines(true); + if (m_runLines == null || m_runLines.length == 0) + throw new Exception ("No active, non-zero Distribution Run Lines found"); + + // Document Type + if (p_C_DocType_ID == 0) + throw new IllegalArgumentException ("No Document Type ID"); + m_docType = new MDocType(getCtx(), p_C_DocType_ID, null); // outside trx + if (m_docType.get_ID() == 0) + throw new Exception ("Document Type not found - C_DocType_ID=" + p_C_DocType_ID); + // + m_DateOrdered = new Timestamp (System.currentTimeMillis()); + if (p_DatePromised == null) + p_DatePromised = m_DateOrdered; + + // Create Temp Lines + if (insertDetails() == 0) + throw new Exception ("No Lines"); + + // Order By Distribution Run Line + m_details = MDistributionRunDetail.get(getCtx(), p_M_DistributionRun_ID, false, get_TrxName()); + // First Run -- Add & Round + addAllocations (); + + // Do Allocation + int loops = 0; + while (!isAllocationEqTotal ()) + { + adjustAllocation(); + addAllocations(); + if (++loops > 10) + throw new Exception ("Loop detected - more than 10 Allocation attempts"); + } + + // Order By Business Partner + m_details = MDistributionRunDetail.get(getCtx(), p_M_DistributionRun_ID, true, get_TrxName()); + // Create Orders + createOrders(); + + return "@Created@ #" + m_counter; + } // doIt + + + /** + * Insert Details + * @return number of rows inserted + */ + private int insertDetails() + { + // Handle NULL + String sql = "UPDATE M_DistributionRunLine SET MinQty = 0 WHERE MinQty IS NULL"; + int no = DB.executeUpdate(sql, get_TrxName()); + sql = "UPDATE M_DistributionListLine SET MinQty = 0 WHERE MinQty IS NULL"; + no = DB.executeUpdate(sql, get_TrxName()); + // Total Ratio + sql = "UPDATE M_DistributionList l " + + "SET RatioTotal = (SELECT SUM(Ratio) FROM M_DistributionListLine ll " + + " WHERE l.M_DistributionList_ID=ll.M_DistributionList_ID) " + + "WHERE EXISTS (SELECT * FROM M_DistributionRunLine rl" + + " WHERE l.M_DistributionList_ID=rl.M_DistributionList_ID" + + " AND rl.M_DistributionRun_ID=" + p_M_DistributionRun_ID + ")"; + no = DB.executeUpdate(sql, get_TrxName()); + + // Delete Old + sql = "DELETE FROM T_DistributionRunDetail WHERE M_DistributionRun_ID=" + + p_M_DistributionRun_ID; + no = DB.executeUpdate(sql, get_TrxName()); + log.fine("insertDetails - deleted #" + no); + // Insert New + sql = "INSERT INTO T_DistributionRunDetail " + + "(M_DistributionRun_ID, M_DistributionRunLine_ID, M_DistributionList_ID, M_DistributionListLine_ID," + + "AD_Client_ID,AD_Org_ID, IsActive, Created,CreatedBy, Updated,UpdatedBy," + + "C_BPartner_ID, C_BPartner_Location_ID, M_Product_ID," + + "Ratio, MinQty, Qty) " + // + + "SELECT rl.M_DistributionRun_ID, rl.M_DistributionRunLine_ID," + + "ll.M_DistributionList_ID, ll.M_DistributionListLine_ID, " + + "rl.AD_Client_ID,rl.AD_Org_ID, rl.IsActive, rl.Created,rl.CreatedBy, rl.Updated,rl.UpdatedBy," + + "ll.C_BPartner_ID, ll.C_BPartner_Location_ID, rl.M_Product_ID, " + + "ll.Ratio, " + + "CASE WHEN rl.MinQty > ll.MinQty THEN rl.MinQty ELSE ll.MinQty END, " + + "(ll.Ratio/l.RatioTotal*rl.TotalQty)" + + "FROM M_DistributionRunLine rl" + + " INNER JOIN M_DistributionList l ON (rl.M_DistributionList_ID=l.M_DistributionList_ID)" + + " INNER JOIN M_DistributionListLine ll ON (rl.M_DistributionList_ID=ll.M_DistributionList_ID) " + + "WHERE rl.M_DistributionRun_ID=" + p_M_DistributionRun_ID + + " AND l.RatioTotal<>0 AND rl.IsActive='Y' AND ll.IsActive='Y'"; + no = DB.executeUpdate(sql, get_TrxName()); + log.fine("inserted #" + no); + return no; + } // insertDetails + + + /************************************************************************** + * Add up Allocations + */ + private void addAllocations () + { + // Reset + for (int j = 0; j < m_runLines.length; j++) + { + MDistributionRunLine runLine = m_runLines[j]; + runLine.resetCalculations(); + } + // Add Up + for (int i = 0; i < m_details.length; i++) + { + MDistributionRunDetail detail = m_details[i]; + for (int j = 0; j < m_runLines.length; j++) + { + MDistributionRunLine runLine = m_runLines[j]; + if (runLine.getM_DistributionRunLine_ID() == detail.getM_DistributionRunLine_ID()) + { + // Round + detail.round(runLine.getUOMPrecision()); + // Add + runLine.addActualMin(detail.getMinQty()); + runLine.addActualQty(detail.getQty()); + runLine.addActualAllocation(detail.getActualAllocation()); + runLine.setMaxAllocation(detail.getActualAllocation(), false); + // + log.fine("RunLine=" + runLine.getLine() + + ": BP_ID=" + detail.getC_BPartner_ID() + + ", Min=" + detail.getMinQty() + + ", Qty=" + detail.getQty() + + ", Allocation=" + detail.getActualAllocation()); + continue; + } + } + } // for all detail lines + + // Info + for (int j = 0; j < m_runLines.length; j++) + { + MDistributionRunLine runLine = m_runLines[j]; + log.fine("Run - " + runLine.getInfo()); + } + } // addAllocations + + + /** + * Is Allocation Equals Total + * @return true if allocation eq total + * @throws Exception + */ + private boolean isAllocationEqTotal() throws Exception + { + boolean allocationEqTotal = true; + // Check total min qty & delta + for (int j = 0; j < m_runLines.length; j++) + { + MDistributionRunLine runLine = m_runLines[j]; + if (runLine.isActualMinGtTotal()) + throw new Exception ("Line " + runLine.getLine() + + " Sum of Min Qty=" + runLine.getActualMin() + + " is greater than Total Qty=" + runLine.getTotalQty()); + if (allocationEqTotal && !runLine.isActualAllocationEqTotal()) + allocationEqTotal = false; + } // for all run lines + log.info("=" + allocationEqTotal); + return allocationEqTotal; + } // isAllocationEqTotal + + + /** + * Adjust Allocation + * @throws Exception + */ + private void adjustAllocation() throws Exception + { + for (int j = 0; j < m_runLines.length; j++) + adjustAllocation(j); + } // adjustAllocation + + /** + * Adjust Run Line Allocation + * @param index run line index + * @throws Exception + */ + private void adjustAllocation(int index) throws Exception + { + MDistributionRunLine runLine = m_runLines[index]; + BigDecimal difference = runLine.getActualAllocationDiff(); + if (difference.compareTo(Env.ZERO) == 0) + return; + // Adjust when difference is -1->1 or last difference is the same + boolean adjustBiggest = difference.abs().compareTo(Env.ONE) <= 0 + || difference.abs().compareTo(runLine.getLastDifference().abs()) == 0; + log.fine("Line=" + runLine.getLine() + + ", Diff=" + difference + ", Adjust=" + adjustBiggest); + // Adjust Biggest Amount + if (adjustBiggest) + { + for (int i = 0; i < m_details.length; i++) + { + MDistributionRunDetail detail = m_details[i]; + if (runLine.getM_DistributionRunLine_ID() == detail.getM_DistributionRunLine_ID()) + { + log.fine("Biggest - DetailAllocation=" + detail.getActualAllocation() + + ", MaxAllocation=" + runLine.getMaxAllocation() + + ", Qty Difference=" + difference); + if (detail.getActualAllocation().compareTo(runLine.getMaxAllocation()) == 0 + && detail.isCanAdjust()) + { + detail.adjustQty(difference); + detail.save(); + return; + } + } + } // for all detail lines + throw new Exception ("Cannot adjust Difference = " + difference + + " - You need to change Total Qty or Min Qty"); + } + else // Distibute + { + // New Total Ratio + BigDecimal ratioTotal = Env.ZERO; + for (int i = 0; i < m_details.length; i++) + { + MDistributionRunDetail detail = m_details[i]; + if (runLine.getM_DistributionRunLine_ID() == detail.getM_DistributionRunLine_ID()) + { + if (detail.isCanAdjust()) + ratioTotal = ratioTotal.add(detail.getRatio()); + } + } + if (ratioTotal.compareTo(Env.ZERO) == 0) + throw new Exception ("Cannot distribute Difference = " + difference + + " - You need to change Total Qty or Min Qty"); + // Distribute + for (int i = 0; i < m_details.length; i++) + { + MDistributionRunDetail detail = m_details[i]; + if (runLine.getM_DistributionRunLine_ID() == detail.getM_DistributionRunLine_ID()) + { + if (detail.isCanAdjust()) + { + BigDecimal diffRatio = detail.getRatio().multiply(difference) + .divide(ratioTotal, BigDecimal.ROUND_HALF_UP); // precision from total + log.fine("Detail=" + detail.toString() + + ", Allocation=" + detail.getActualAllocation() + + ", DiffRatio=" + diffRatio); + detail.adjustQty(diffRatio); + detail.save(); + } + } + } + } + runLine.setLastDifference(difference); + } // adjustAllocation + + + /************************************************************************** + * Create Orders + * @return true if created + */ + private boolean createOrders() + { + // Get Counter Org/BP + int runAD_Org_ID = m_run.getAD_Org_ID(); + if (runAD_Org_ID == 0) + runAD_Org_ID = Env.getAD_Org_ID(getCtx()); + MOrg runOrg = MOrg.get(getCtx(), runAD_Org_ID); + int runC_BPartner_ID = runOrg.getLinkedC_BPartner_ID(); + boolean counter = !m_run.isCreateSingleOrder() // no single Order + && runC_BPartner_ID > 0 // Org linked to BP + && !m_docType.isSOTrx(); // PO + MBPartner runBPartner = counter ? new MBPartner(getCtx(), runC_BPartner_ID, get_TrxName()) : null; + if (!counter || runBPartner == null || runBPartner.get_ID() != runC_BPartner_ID) + counter = false; + if (counter) + log.info("RunBP=" + runBPartner + + " - " + m_docType); + log.info("Single=" + m_run.isCreateSingleOrder() + + " - " + m_docType + ",SO=" + m_docType.isSOTrx()); + log.fine("Counter=" + counter + + ",C_BPartner_ID=" + runC_BPartner_ID + "," + runBPartner); + // + MBPartner bp = null; + MOrder singleOrder = null; + MProduct product = null; + // Consolidated Order + if (m_run.isCreateSingleOrder()) + { + bp = new MBPartner (getCtx(), m_run.getC_BPartner_ID(), get_TrxName()); + if (bp.get_ID() == 0) + throw new IllegalArgumentException("Business Partner not found - C_BPartner_ID=" + m_run.getC_BPartner_ID()); + // + if (!p_IsTest) + { + singleOrder = new MOrder (getCtx(), 0, get_TrxName()); + singleOrder.setC_DocTypeTarget_ID(m_docType.getC_DocType_ID()); + singleOrder.setC_DocType_ID(m_docType.getC_DocType_ID()); + singleOrder.setIsSOTrx(m_docType.isSOTrx()); + singleOrder.setBPartner(bp); + if (m_run.getC_BPartner_Location_ID() != 0) + singleOrder.setC_BPartner_Location_ID(m_run.getC_BPartner_Location_ID()); + singleOrder.setDateOrdered(m_DateOrdered); + singleOrder.setDatePromised(p_DatePromised); + if (!singleOrder.save()) + { + log.log(Level.SEVERE, "Order not saved"); + return false; + } + m_counter++; + } + } + + int lastC_BPartner_ID = 0; + int lastC_BPartner_Location_ID = 0; + MOrder order = null; + // For all lines + for (int i = 0; i < m_details.length; i++) + { + MDistributionRunDetail detail = m_details[i]; + + // Create Order Header + if (m_run.isCreateSingleOrder()) + order = singleOrder; + // New Business Partner + else if (lastC_BPartner_ID != detail.getC_BPartner_ID() + || lastC_BPartner_Location_ID != detail.getC_BPartner_Location_ID()) + { + // finish order + order = null; + } + lastC_BPartner_ID = detail.getC_BPartner_ID(); + lastC_BPartner_Location_ID = detail.getC_BPartner_Location_ID(); + + // New Order + if (order == null) + { + bp = new MBPartner (getCtx(), detail.getC_BPartner_ID(), get_TrxName()); + if (!p_IsTest) + { + order = new MOrder (getCtx(), 0, get_TrxName()); + order.setC_DocTypeTarget_ID(m_docType.getC_DocType_ID()); + order.setC_DocType_ID(m_docType.getC_DocType_ID()); + order.setIsSOTrx(m_docType.isSOTrx()); + // Counter Doc + if (counter && bp.getAD_OrgBP_ID_Int() > 0) + { + log.fine("Counter - From_BPOrg=" + bp.getAD_OrgBP_ID_Int() + + "-" + bp + ", To_BP=" + runBPartner); + order.setAD_Org_ID(bp.getAD_OrgBP_ID_Int()); + MOrgInfo oi = MOrgInfo.get(getCtx(), bp.getAD_OrgBP_ID_Int()); + if (oi.getM_Warehouse_ID() > 0) + order.setM_Warehouse_ID(oi.getM_Warehouse_ID()); + order.setBPartner(runBPartner); + } + else // normal + { + log.fine("From_Org=" + runAD_Org_ID + + ", To_BP=" + bp); + order.setAD_Org_ID(runAD_Org_ID); + order.setBPartner(bp); + if (detail.getC_BPartner_Location_ID() != 0) + order.setC_BPartner_Location_ID(detail.getC_BPartner_Location_ID()); + } + order.setDateOrdered(m_DateOrdered); + order.setDatePromised(p_DatePromised); + if (!order.save()) + { + log.log(Level.SEVERE, "Order not saved"); + return false; + } + } + } + + // Line + if (product == null || product.getM_Product_ID() != detail.getM_Product_ID()) + product = MProduct.get (getCtx(), detail.getM_Product_ID()); + if (p_IsTest) + { + addLog(0,null, detail.getActualAllocation(), + bp.getName() + " - " + product.getName()); + continue; + } + + // Create Order Line + MOrderLine line = new MOrderLine(order); + if (counter && bp.getAD_OrgBP_ID_Int() > 0) + ; // don't overwrite counter doc + else // normal - optionally overwrite + { + line.setC_BPartner_ID(detail.getC_BPartner_ID()); + if (detail.getC_BPartner_Location_ID() != 0) + line.setC_BPartner_Location_ID(detail.getC_BPartner_Location_ID()); + } + // + line.setProduct(product); + line.setQty(detail.getActualAllocation()); + line.setPrice(); + if (!line.save()) + { + log.log(Level.SEVERE, "OrderLine not saved"); + return false; + } + addLog(0,null, detail.getActualAllocation(), order.getDocumentNo() + + ": " + bp.getName() + " - " + product.getName()); + } + // finish order + order = null; + + + return true; + } // createOrders + +} // DistributionRun diff --git a/base/src/org/compiere/process/DistributionVerify.java b/base/src/org/compiere/process/DistributionVerify.java new file mode 100644 index 0000000000..cf186399d4 --- /dev/null +++ b/base/src/org/compiere/process/DistributionVerify.java @@ -0,0 +1,61 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Verify GL Distribution + * + * @author Jorg Janke + * @version $Id: DistributionVerify.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class DistributionVerify extends SvrProcess +{ + + /** + * Prepare + */ + protected void prepare () + { + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("doIt - GL_Distribution_ID=" + getRecord_ID()); + MDistribution distribution = new MDistribution (getCtx(), getRecord_ID(), get_TrxName()); + if (distribution.get_ID() == 0) + throw new AdempiereUserError("Not found GL_Distribution_ID=" + getRecord_ID()); + + String error = distribution.validate(); + boolean saved = distribution.save(); + if (error != null) + throw new AdempiereUserError(error); + if (!saved) + throw new AdempiereSystemError("@NotSaved@"); + + return "@OK@"; + } // doIt + +} // DistributionVerify diff --git a/base/src/org/compiere/process/DocTypeCounterValidate.java b/base/src/org/compiere/process/DocTypeCounterValidate.java new file mode 100644 index 0000000000..2b4932ec6a --- /dev/null +++ b/base/src/org/compiere/process/DocTypeCounterValidate.java @@ -0,0 +1,61 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import org.compiere.model.*; + +/** + * Validate Counter Document + * + * @author Jorg Janke + * @version $Id: DocTypeCounterValidate.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class DocTypeCounterValidate extends SvrProcess +{ + /** Counter Document */ + private int p_C_DocTypeCounter_ID = 0; + /** Document Relationship */ + private MDocTypeCounter m_counter = null; + + /** + * Prepare + */ + protected void prepare () + { + p_C_DocTypeCounter_ID = getRecord_ID(); + } // prepare + + /** + * Do It + * @return message + */ + protected String doIt () throws Exception + { + log.info("C_DocTypeCounter_ID=" + p_C_DocTypeCounter_ID); + m_counter = new MDocTypeCounter (getCtx(), p_C_DocTypeCounter_ID, get_TrxName()); + if (m_counter == null || m_counter.get_ID() == 0) + throw new IllegalArgumentException("Not found C_DocTypeCounter_ID=" + p_C_DocTypeCounter_ID); + // + String error = m_counter.validate(); + m_counter.save(); + if (error != null) + throw new Exception(error); + + return "OK"; + } // doIt + +} // DocTypeCounterValidate diff --git a/base/src/org/compiere/process/DocumentTypeVerify.java b/base/src/org/compiere/process/DocumentTypeVerify.java new file mode 100644 index 0000000000..113d6cd788 --- /dev/null +++ b/base/src/org/compiere/process/DocumentTypeVerify.java @@ -0,0 +1,208 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Verify Document Types. + * - Make sure that there is a DocumentType for all Document Base Types + * - Create missing Period Controls for Document Type + * + * @author Jorg Janke + * @version $Id: DocumentTypeVerify.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class DocumentTypeVerify extends SvrProcess +{ + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (DocumentTypeVerify.class); + + + /** + * No Parameters (Nop) + * @see org.compiere.process.SvrProcess#prepare() + */ + protected void prepare() + { + } // prepare + + /** + * Execute process + * @see org.compiere.process.SvrProcess#doIt() + * @return info + * @throws Exception + */ + protected String doIt() throws Exception + { + createDocumentTypes(getCtx(), getAD_Client_ID(), this, get_TrxName()); + createPeriodControls(getCtx(), getAD_Client_ID(), this, get_TrxName()); + return "OK"; + } // doIt + + + /************************************************************************** + * Create Missing Document Types + * @param ctx context + * @param AD_Client_ID client + * @param sp server process + * @param trxName transaction + */ + public static void createDocumentTypes(Properties ctx, int AD_Client_ID, + SvrProcess sp, String trxName) + { + s_log.info("AD_Client_ID=" + AD_Client_ID); + String sql = "SELECT rl.Value, rl.Name " + + "FROM AD_Ref_List rl " + + "WHERE rl.AD_Reference_ID=183" + + " AND rl.IsActive='Y' AND NOT EXISTS " + + " (SELECT * FROM C_DocType dt WHERE dt.AD_Client_ID=? AND rl.Value=dt.DocBaseType)"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, AD_Client_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + String name = rs.getString(2); + String value = rs.getString(1); + s_log.config(name + "=" + value); + MDocType dt = new MDocType (ctx, value, name, trxName); + if (dt.save()) + { + if (sp != null) + sp.addLog (0, null, null, name); + else + s_log.fine(name); + } + else + { + if (sp != null) + sp.addLog (0, null, null, "Not created: " + name); + else + s_log.warning("Not created: " + name); + } + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + } // createDocumentTypes + + + /** + * Create Period Controls + * @param ctx context + * @param AD_Client_ID client + * @param sp server process + * @param trxName transaction + */ + public static void createPeriodControls(Properties ctx, int AD_Client_ID, + SvrProcess sp, String trxName) + { + s_log.info("AD_Client_ID=" + AD_Client_ID); + + // Delete Duplicates + String sql = "DELETE C_PeriodControl pc1 " + + "WHERE (C_Period_ID, DocBaseType) IN " + + "(SELECT C_Period_ID, DocBaseType " + + "FROM C_PeriodControl pc2 " + + "GROUP BY C_Period_ID, DocBaseType " + + "HAVING COUNT(*) > 1)" + + " AND C_PeriodControl_ID NOT IN " + + "(SELECT MIN(C_PeriodControl_ID) " + + "FROM C_PeriodControl pc3 " + + "GROUP BY C_Period_ID, DocBaseType)"; + int no = DB.executeUpdate(sql, false, trxName); + s_log.info("Duplicates deleted #" + no); + + // Insert Missing + sql = "SELECT DISTINCT p.AD_Client_ID, p.C_Period_ID, dt.DocBaseType " + + "FROM C_Period p" + + " FULL JOIN C_DocType dt ON (p.AD_Client_ID=dt.AD_Client_ID) " + + "WHERE p.AD_Client_ID=?" + + " AND NOT EXISTS" + + " (SELECT * FROM C_PeriodControl pc " + + "WHERE pc.C_Period_ID=p.C_Period_ID AND pc.DocBaseType=dt.DocBaseType)"; + PreparedStatement pstmt = null; + int counter = 0; + try + { + pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, AD_Client_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + int Client_ID = rs.getInt(1); + int C_Period_ID = rs.getInt(2); + String DocBaseType = rs.getString(3); + s_log.config("AD_Client_ID=" + Client_ID + + ", C_Period_ID=" + C_Period_ID + ", DocBaseType=" + DocBaseType); + // + MPeriodControl pc = new MPeriodControl (ctx, Client_ID, + C_Period_ID, DocBaseType, trxName); + if (pc.save()) + { + counter++; + s_log.fine(pc.toString()); + } + else + s_log.warning("Not saved: " + pc); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (sp != null) + sp.addLog (0, null, new BigDecimal(counter), "@C_PeriodControl_ID@ @Created@"); + s_log.info("Inserted #" + counter); + } // createPeriodControls + +} // DocumentTypeVerify diff --git a/base/src/org/compiere/process/DunningPrint.java b/base/src/org/compiere/process/DunningPrint.java new file mode 100644 index 0000000000..ad7d405e60 --- /dev/null +++ b/base/src/org/compiere/process/DunningPrint.java @@ -0,0 +1,216 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.io.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.print.*; +import org.compiere.util.*; + + + +/** + * Dunning Letter Print + * + * @author Jorg Janke + * @version $Id: DunningPrint.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class DunningPrint extends SvrProcess +{ + /** Mail PDF */ + private boolean p_EMailPDF = false; + /** Mail Template */ + private int p_R_MailText_ID = 0; + /** Dunning Run */ + private int p_C_DunningRun_ID = 0; + /** Print only Outstanding */ + private boolean p_IsOnlyIfBPBalance = true; + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("EMailPDF")) + p_EMailPDF = "Y".equals(para[i].getParameter()); + else if (name.equals("R_MailText_ID")) + p_R_MailText_ID = para[i].getParameterAsInt(); + else if (name.equals("C_DunningRun_ID")) + p_C_DunningRun_ID = para[i].getParameterAsInt(); + else if (name.equals("IsOnlyIfBPBalance")) + p_IsOnlyIfBPBalance = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Pocess + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("C_DunningRun_ID=" + p_C_DunningRun_ID + ",R_MailText_ID=" + p_R_MailText_ID + + ", EmailPDF=" + p_EMailPDF + ",IsOnlyIfBPBalance=" + p_IsOnlyIfBPBalance); + + // Need to have Template + if (p_EMailPDF && p_R_MailText_ID == 0) + throw new AdempiereUserError ("@NotFound@: @R_MailText_ID@"); + String subject = ""; + MMailText mText = null; + if (p_EMailPDF) + { + mText = new MMailText (getCtx(), p_R_MailText_ID, get_TrxName()); + if (p_EMailPDF && mText.get_ID() == 0) + throw new AdempiereUserError ("@NotFound@: @R_MailText_ID@ - " + p_R_MailText_ID); + subject = mText.getMailHeader(); + } + // + MDunningRun run = new MDunningRun (getCtx(), p_C_DunningRun_ID, get_TrxName()); + if (run.get_ID() == 0) + throw new AdempiereUserError ("@NotFound@: @C_DunningRun_ID@ - " + p_C_DunningRun_ID); + // Print Format on Dunning Level + MDunningLevel level = new MDunningLevel (getCtx(), run.getC_DunningLevel_ID(), get_TrxName()); + MPrintFormat format = MPrintFormat.get (getCtx(), level.getDunning_PrintFormat_ID(), false); + + MClient client = MClient.get(getCtx()); + + int count = 0; + int errors = 0; + MDunningRunEntry[] entries = run.getEntries(false); + for (int i = 0; i < entries.length; i++) + { + MDunningRunEntry entry = entries[i]; + if (p_IsOnlyIfBPBalance && entry.getAmt().signum() <= 0) + continue; + // To BPartner + MBPartner bp = new MBPartner (getCtx(), entry.getC_BPartner_ID(), get_TrxName()); + if (bp.get_ID() == 0) + { + addLog (entry.get_ID(), null, null, "@NotFound@: @C_BPartner_ID@ " + entry.getC_BPartner_ID()); + errors++; + continue; + } + // To User + MUser to = new MUser (getCtx(), entry.getAD_User_ID(), get_TrxName()); + if (p_EMailPDF) + { + if (to.get_ID() == 0) + { + addLog (entry.get_ID(), null, null, "@NotFound@: @AD_User_ID@ - " + bp.getName()); + errors++; + continue; + } + else if (to.getEMail() == null || to.getEMail().length() == 0) + { + addLog (entry.get_ID(), null, null, "@NotFound@: @EMail@ - " + to.getName()); + errors++; + continue; + } + } + // BP Language + Language language = Language.getLoginLanguage(); // Base Language + String tableName = "C_Dunning_Header_v"; + if (client.isMultiLingualDocument()) + { + tableName += "t"; + String AD_Language = bp.getAD_Language(); + if (AD_Language != null) + language = Language.getLanguage(AD_Language); + } + format.setLanguage(language); + format.setTranslationLanguage(language); + // query + MQuery query = new MQuery(tableName); + query.addRestriction("C_DunningRunEntry_ID", MQuery.EQUAL, + new Integer(entry.getC_DunningRunEntry_ID())); + + // Engine + PrintInfo info = new PrintInfo( + bp.getName(), + X_C_DunningRunEntry.Table_ID, + entry.getC_DunningRunEntry_ID(), + entry.getC_BPartner_ID()); + info.setDescription(bp.getName() + ", Amt=" + entry.getAmt()); + ReportEngine re = new ReportEngine(getCtx(), format, query, info); + boolean printed = false; + if (p_EMailPDF) + { + EMail email = client.createEMail(to.getEMail(), null, null); + if (!email.isValid()) + { + addLog (entry.get_ID(), null, null, + "@RequestActionEMailError@ Invalid EMail: " + to); + errors++; + continue; + } + mText.setUser(to); // variable context + mText.setBPartner(bp); + mText.setPO(entry); + String message = mText.getMailText(true); + if (mText.isHtml()) + email.setMessageHTML(mText.getMailHeader(), message); + else + { + email.setSubject (mText.getMailHeader()); + email.setMessageText (message); + } + // + File attachment = re.getPDF(File.createTempFile("Dunning", ".pdf")); + log.fine(to + " - " + attachment); + email.addAttachment(attachment); + // + String msg = email.send(); + MUserMail um = new MUserMail(mText, entry.getAD_User_ID(), email); + um.save(); + if (msg.equals(EMail.SENT_OK)) + { + addLog (entry.get_ID(), null, null, + bp.getName() + " @RequestActionEMailOK@"); + count++; + printed = true; + } + else + { + addLog (entry.get_ID(), null, null, + bp.getName() + " @RequestActionEMailError@ " + msg); + errors++; + } + } + else + { + re.print (); + count++; + printed = true; + } + + } // for all dunning letters + if (p_EMailPDF) + return "@Sent@=" + count + " - @Errors@=" + errors; + return "@Printed@=" + count; + } // doIt + +} // DunningPrint diff --git a/base/src/org/compiere/process/DunningRunCreate.java b/base/src/org/compiere/process/DunningRunCreate.java new file mode 100644 index 0000000000..8ba2b57c1b --- /dev/null +++ b/base/src/org/compiere/process/DunningRunCreate.java @@ -0,0 +1,352 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Create Dunning Run Entries/Lines + * + * @author Jorg Janke + * @version $Id: DunningRunCreate.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class DunningRunCreate extends SvrProcess +{ + private boolean p_IncludeInDispute = false; + private boolean p_OnlySOTrx = false; + private int p_SalesRep_ID = 0; + private int p_C_Currency_ID = 0; + private int p_C_BPartner_ID = 0; + private int p_C_BP_Group_ID = 0; + private int p_C_DunningRun_ID = 0; + + private MDunningRun m_run = null; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("IncludeInDispute")) + p_IncludeInDispute = "Y".equals(para[i].getParameter()); + else if (name.equals("OnlySOTrx")) + p_OnlySOTrx = "Y".equals(para[i].getParameter()); + else if (name.equals("SalesRep_ID")) + p_SalesRep_ID = para[i].getParameterAsInt(); + else if (name.equals("C_Currency_ID")) + p_C_Currency_ID = para[i].getParameterAsInt(); + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = para[i].getParameterAsInt(); + else if (name.equals("C_BP_Group_ID")) + p_C_BP_Group_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_C_DunningRun_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("C_DunningRun_ID=" + p_C_DunningRun_ID + + ", Dispute=" + p_IncludeInDispute + + ", C_BP_Group_ID=" + p_C_BP_Group_ID + + ", C_BPartner_ID=" + p_C_BPartner_ID); + m_run = new MDunningRun (getCtx(),p_C_DunningRun_ID, get_TrxName()); + if (m_run.get_ID() == 0) + throw new IllegalArgumentException ("Not found MDunningRun"); + if (!m_run.deleteEntries(true)) + throw new IllegalArgumentException ("Cannot delete existing entries"); + if (p_SalesRep_ID == 0) + throw new IllegalArgumentException ("No SalesRep"); + if (p_C_Currency_ID == 0) + throw new IllegalArgumentException ("No Currency"); + // + int inv = addInvoices(); + int pay = addPayments(); + + return "@C_Invoice_ID@ #" + inv + " - @C_Payment_ID@=" + pay; + } // doIt + + + /************************************************************************** + * Add Invoices to Run + * @return no of invoices + */ + private int addInvoices() + { + int count = 0; + String sql = "SELECT i.C_Invoice_ID, i.C_Currency_ID," + + " i.GrandTotal*i.MultiplierAP," + + " invoiceOpen(i.C_Invoice_ID,i.C_InvoicePaySchedule_ID)*MultiplierAP," + + " COALESCE(daysBetween(?,ips.DueDate),paymentTermDueDays(i.C_PaymentTerm_ID,i.DateInvoiced,?))," // ##1/2 + + " i.IsInDispute, i.C_BPartner_ID " + + "FROM C_Invoice_v i " + + " LEFT OUTER JOIN C_InvoicePaySchedule ips ON (i.C_InvoicePaySchedule_ID=ips.C_InvoicePaySchedule_ID) " + + "WHERE i.IsPaid='N' AND i.AD_Client_ID=?" // ##3 + + " AND i.DocStatus IN ('CO','CL')" + // Only BP(Group) with Dunning defined + + " AND EXISTS (SELECT * FROM C_DunningLevel dl " + + "WHERE dl.C_DunningLevel_ID=?" // // ##4 + + " AND dl.C_Dunning_ID IN " + + "(SELECT COALESCE(bp.C_Dunning_ID, bpg.C_Dunning_ID) " + + "FROM C_BPartner bp" + + " INNER JOIN C_BP_Group bpg ON (bp.C_BP_Group_ID=bpg.C_BP_Group_ID) " + + "WHERE i.C_BPartner_ID=bp.C_BPartner_ID))"; + if (p_C_BPartner_ID != 0) + sql += " AND i.C_BPartner_ID=?"; // ##5 + else if (p_C_BP_Group_ID != 0) + sql += " AND EXISTS (SELECT * FROM C_BPartner bp " + + "WHERE i.C_BPartner_ID=bp.C_BPartner_ID AND bp.C_BP_Group_ID=?)"; // ##5 + if (p_OnlySOTrx) + sql += " AND i.IsSOTrx='Y'"; + // log.info(sql); + + // Sub Query + String sql2 = "SELECT COUNT(*), COALESCE(TRUNC(SysDate-MAX(dr.DunningDate)),0) " + + "FROM C_DunningRun dr" + + " INNER JOIN C_DunningRunEntry dre ON (dr.C_DunningRun_ID=dre.C_DunningRun_ID)" + + " INNER JOIN C_DunningRunLine drl ON (dre.C_DunningRunEntry_ID=drl.C_DunningRunEntry_ID) " + + "WHERE drl.Processed='Y' AND drl.C_Invoice_ID=?"; + + BigDecimal DaysAfterDue = m_run.getLevel().getDaysAfterDue(); + int DaysBetweenDunning = m_run.getLevel().getDaysBetweenDunning(); + + PreparedStatement pstmt = null; + PreparedStatement pstmt2 = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setTimestamp(1, m_run.getDunningDate()); + pstmt.setTimestamp(2, m_run.getDunningDate()); + pstmt.setInt (3, m_run.getAD_Client_ID()); + pstmt.setInt(4, m_run.getC_DunningLevel_ID()); + if (p_C_BPartner_ID != 0) + pstmt.setInt (5, p_C_BPartner_ID); + else if (p_C_BP_Group_ID != 0) + pstmt.setInt (5, p_C_BP_Group_ID); + // + pstmt2 = DB.prepareStatement (sql2, get_TrxName()); + // + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + int C_Invoice_ID = rs.getInt(1); + int C_Currency_ID = rs.getInt(2); + BigDecimal GrandTotal = rs.getBigDecimal(3); + BigDecimal Open = rs.getBigDecimal(4); + int DaysDue = rs.getInt(5); + boolean IsInDispute = "Y".equals(rs.getString(6)); + int C_BPartner_ID = rs.getInt(7); + // + if (!p_IncludeInDispute && IsInDispute) + continue; + if (DaysDue < DaysAfterDue.intValue()) + continue; + if (Env.ZERO.compareTo(Open) == 0) + continue; + // + int TimesDunned = 0; + int DaysAfterLast = 0; + // SubQuery + pstmt2.setInt (1, C_Invoice_ID); + ResultSet rs2 = pstmt2.executeQuery (); + if (rs2.next()) + { + TimesDunned = rs2.getInt(1); + DaysAfterLast = rs2.getInt(2); + } + rs2.close(); + // SubQuery + if (DaysBetweenDunning != 0 && DaysAfterLast < DaysBetweenDunning) + continue; + // + createInvoiceLine (C_Invoice_ID, C_Currency_ID, GrandTotal, Open, + DaysDue, IsInDispute, C_BPartner_ID, + TimesDunned, DaysAfterLast); + count++; + } + rs.close (); + pstmt.close (); + pstmt = null; + pstmt2.close(); + pstmt2 = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "addInvoices", e); + } + try + { + if (pstmt != null) + pstmt.close (); + if (pstmt2 != null) + pstmt2.close (); + pstmt = null; + pstmt2 = null; + } + catch (Exception e) + { + pstmt = null; + pstmt2 = null; + } + return count; + } // addInvoices + + /** + * Create Invoice Line + * @param C_Invoice_ID + * @param C_Currency_ID + * @param GrandTotal + * @param Open + * @param DaysDue + * @param IsInDispute + * @param C_BPartner_ID + * @param TimesDunned + * @param DaysAfterLast + */ + private void createInvoiceLine (int C_Invoice_ID, int C_Currency_ID, + BigDecimal GrandTotal, BigDecimal Open, + int DaysDue, boolean IsInDispute, + int C_BPartner_ID, int TimesDunned, int DaysAfterLast) + { + MDunningRunEntry entry = m_run.getEntry (C_BPartner_ID, p_C_Currency_ID, p_SalesRep_ID); + if (entry.get_ID() == 0) + if (!entry.save()) + throw new IllegalStateException("Cannot save MDunningRunEntry"); + // + MDunningRunLine line = new MDunningRunLine (entry); + line.setInvoice(C_Invoice_ID, C_Currency_ID, GrandTotal, Open, + DaysDue, IsInDispute, TimesDunned, DaysAfterLast); + if (!line.save()) + throw new IllegalStateException("Cannot save MDunningRunLine"); + } // createInvoiceLine + + + /************************************************************************** + * Add Payments to Run + * @return no of payments + */ + private int addPayments() + { + String sql = "SELECT C_Payment_ID, C_Currency_ID, PayAmt," + + " paymentAvailable(C_Payment_ID), C_BPartner_ID " + + "FROM C_Payment_v p " + + "WHERE AD_Client_ID=?" // ##1 + + " AND IsAllocated='N' AND C_BPartner_ID IS NOT NULL" + + " AND C_Charge_ID IS NULL" + + " AND DocStatus IN ('CO','CL')" + // Only BP with Dunning defined + + " AND EXISTS (SELECT * FROM C_BPartner bp " + + "WHERE p.C_BPartner_ID=bp.C_BPartner_ID" + + " AND bp.C_Dunning_ID=(SELECT C_Dunning_ID FROM C_DunningLevel WHERE C_DunningLevel_ID=?))"; // ##2 + if (p_C_BPartner_ID != 0) + sql += " AND C_BPartner_ID=?"; // ##3 + else if (p_C_BP_Group_ID != 0) + sql += " AND EXISTS (SELECT * FROM C_BPartner bp " + + "WHERE p.C_BPartner_ID=bp.C_BPartner_ID AND bp.C_BP_Group_ID=?)"; // ##3 + if (p_OnlySOTrx) + sql += " AND IsReceipt='Y'"; + + int count = 0; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getAD_Client_ID()); + pstmt.setInt (2, m_run.getC_DunningLevel_ID()); + if (p_C_BPartner_ID != 0) + pstmt.setInt (3, p_C_BPartner_ID); + else if (p_C_BP_Group_ID != 0) + pstmt.setInt (3, p_C_BP_Group_ID); + + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + int C_Payment_ID = rs.getInt(1); + int C_Currency_ID = rs.getInt(2); + BigDecimal PayAmt = rs.getBigDecimal(3).negate(); + BigDecimal OpenAmt = rs.getBigDecimal(4).negate(); + int C_BPartner_ID = rs.getInt(5); + // + if (Env.ZERO.compareTo(OpenAmt) == 0) + continue; + // + createPaymentLine (C_Payment_ID, C_Currency_ID, PayAmt, OpenAmt, + C_BPartner_ID); + count++; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return count; + } // addPayments + + /** + * Create Payment Line + * @param C_Payment_ID + * @param C_Currency_ID + * @param PayAmt + * @param OpenAmt + * @param C_BPartner_ID + */ + private void createPaymentLine (int C_Payment_ID, int C_Currency_ID, + BigDecimal PayAmt, BigDecimal OpenAmt, int C_BPartner_ID) + { + MDunningRunEntry entry = m_run.getEntry (C_BPartner_ID, p_C_Currency_ID, p_SalesRep_ID); + if (entry.get_ID() == 0) + if (!entry.save()) + throw new IllegalStateException("Cannot save MDunningRunEntry"); + // + MDunningRunLine line = new MDunningRunLine (entry); + line.setPayment(C_Payment_ID, C_Currency_ID, PayAmt, OpenAmt); + if (!line.save()) + throw new IllegalStateException("Cannot save MDunningRunLine"); + } // createPaymentLine + + +} // DunningRunCreate diff --git a/base/src/org/compiere/process/EMailTest.java b/base/src/org/compiere/process/EMailTest.java new file mode 100644 index 0000000000..a2e754b539 --- /dev/null +++ b/base/src/org/compiere/process/EMailTest.java @@ -0,0 +1,82 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.io.*; + +import org.compiere.util.*; +import org.compiere.model.*; + +/** + * Client EMail Test + * + * @author Jorg Janke + * @version $Id: EMailTest.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class EMailTest extends SvrProcess +{ + /** Client Parameter */ + protected int p_AD_Client_ID = 0; + + /** + * Get Parameters + */ + protected void prepare () + { + p_AD_Client_ID = getRecord_ID(); + if (p_AD_Client_ID == 0) + p_AD_Client_ID = Env.getAD_Client_ID(getCtx()); + } // prepare + + /** + * Process - Test EMail + * @return info + */ + protected String doIt () throws Exception + { + MClient client = MClient.get (getCtx(), p_AD_Client_ID); + log.info(client.toString()); + + // Test Client Mail + String clientTest = client.testEMail(); + addLog(0, null, null, client.getName() + ": " + clientTest); + + // Test Client DocumentDir + if (!Ini.isClient()) + { + String documentDir = client.getDocumentDir(); + if (documentDir == null || documentDir.length() == 0) + documentDir = "."; + File file = new File (documentDir); + if (file.exists() && file.isDirectory()) + addLog(0, null, null, "Found Directory: " + client.getDocumentDir()); + else + addLog(0, null, null, "Not Found Directory: " + client.getDocumentDir()); + } + + MStore[] wstores = MStore.getOfClient(client); + for (int i = 0; i < wstores.length; i++) + { + MStore store = wstores[i]; + String test = store.testEMail(); + addLog(0, null, null, store.getName() + ": " + test); + } + + return clientTest; + } // doIt + +} // EMailTest diff --git a/base/src/org/compiere/process/EntityTypeRegister.java b/base/src/org/compiere/process/EntityTypeRegister.java new file mode 100644 index 0000000000..9cb2de7a94 --- /dev/null +++ b/base/src/org/compiere/process/EntityTypeRegister.java @@ -0,0 +1,59 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Register Entity Type + * + * @author Jorg Janke + * @version $Id: EntityTypeRegister.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class EntityTypeRegister extends SvrProcess +{ + /** Register Entity Type */ + protected int p_AD_EntityType_ID = 0; + + /** + * Prepare + */ + protected void prepare () + { + p_AD_EntityType_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return summary + * @throws Exception + */ + protected String doIt () + throws Exception + { + log.info("AD_EntityType_ID=" + p_AD_EntityType_ID); + MEntityType et = new MEntityType(getCtx(), p_AD_EntityType_ID, get_TrxName()); + if (et.isSystemMaintained()) + throw new AdempiereUserError("You cannot register a System maintained entity"); + + throw new AdempiereSystemError("To register an Entity Type, contact Adempiere directly"); + + // return "Not Supported Yet"; + } // doIt + +} // EntityTypeRegister diff --git a/base/src/org/compiere/process/ExpenseAPInvoice.java b/base/src/org/compiere/process/ExpenseAPInvoice.java new file mode 100644 index 0000000000..06bb99a7f5 --- /dev/null +++ b/base/src/org/compiere/process/ExpenseAPInvoice.java @@ -0,0 +1,221 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Create AP Invoices from Expense Reports + * + * @author Jorg Janke + * @version $Id: ExpenseAPInvoice.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class ExpenseAPInvoice extends SvrProcess +{ + private int m_C_BPartner_ID = 0; + private Timestamp m_DateFrom = null; + private Timestamp m_DateTo = null; + private int m_noInvoices = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_BPartner_ID")) + m_C_BPartner_ID = para[i].getParameterAsInt(); + else if (name.equals("DateReport")) + { + m_DateFrom = (Timestamp)para[i].getParameter(); + m_DateTo = (Timestamp)para[i].getParameter_To(); + } + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + + /** + * Perform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws java.lang.Exception + { + StringBuffer sql = new StringBuffer ("SELECT * " + + "FROM S_TimeExpense e " + + "WHERE e.Processed='Y'" + + " AND e.AD_Client_ID=?"); // #1 + if (m_C_BPartner_ID != 0) + sql.append(" AND e.C_BPartner_ID=?"); // #2 + if (m_DateFrom != null) + sql.append(" AND e.DateReport >= ?"); // #3 + if (m_DateTo != null) + sql.append(" AND e.DateReport <= ?"); // #4 + sql.append(" AND EXISTS (SELECT * FROM S_TimeExpenseLine el " + + "WHERE e.S_TimeExpense_ID=el.S_TimeExpense_ID" + + " AND el.C_InvoiceLine_ID IS NULL" + + " AND el.ConvertedAmt<>0) " + + "ORDER BY e.C_BPartner_ID, e.S_TimeExpense_ID"); + // + int old_BPartner_ID = -1; + MInvoice invoice = null; + // + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql.toString (), get_TrxName()); + int par = 1; + pstmt.setInt(par++, getAD_Client_ID()); + if (m_C_BPartner_ID != 0) + pstmt.setInt (par++, m_C_BPartner_ID); + if (m_DateFrom != null) + pstmt.setTimestamp (par++, m_DateFrom); + if (m_DateTo != null) + pstmt.setTimestamp (par++, m_DateTo); + ResultSet rs = pstmt.executeQuery (); + while (rs.next()) // ********* Expense Line Loop + { + MTimeExpense te = new MTimeExpense (getCtx(), rs, get_TrxName()); + + // New BPartner - New Order + if (te.getC_BPartner_ID() != old_BPartner_ID) + { + completeInvoice (invoice); + MBPartner bp = new MBPartner (getCtx(), te.getC_BPartner_ID(), get_TrxName()); + // + log.info("New Invoice for " + bp); + invoice = new MInvoice (getCtx(), 0, null); + invoice.setClientOrg(te.getAD_Client_ID(), te.getAD_Org_ID()); + invoice.setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_APInvoice); // API + invoice.setDocumentNo (te.getDocumentNo()); + // + invoice.setBPartner(bp); + if (invoice.getC_BPartner_Location_ID() == 0) + { + log.log(Level.SEVERE, "No BP Location: " + bp); + addLog(0, te.getDateReport(), + null, "No Location: " + te.getDocumentNo() + " " + bp.getName()); + invoice = null; + break; + } + invoice.setM_PriceList_ID(te.getM_PriceList_ID()); + invoice.setSalesRep_ID(te.getDoc_User_ID()); + String descr = Msg.translate(getCtx(), "S_TimeExpense_ID") + + ": " + te.getDocumentNo() + " " + + DisplayType.getDateFormat(DisplayType.Date).format(te.getDateReport()); + invoice.setDescription(descr); + if (!invoice.save()) + new IllegalStateException("Cannot save Invoice"); + old_BPartner_ID = bp.getC_BPartner_ID(); + } + MTimeExpenseLine[] tel = te.getLines(false); + for (int i = 0; i < tel.length; i++) + { + MTimeExpenseLine line = tel[i]; + + // Already Invoiced or nothing to be reimbursed + if (line.getC_InvoiceLine_ID() != 0 + || Env.ZERO.compareTo(line.getQtyReimbursed()) == 0 + || Env.ZERO.compareTo(line.getPriceReimbursed()) == 0) + continue; + + // Update Header info + if (line.getC_Activity_ID() != 0 && line.getC_Activity_ID() != invoice.getC_Activity_ID()) + invoice.setC_Activity_ID(line.getC_Activity_ID()); + if (line.getC_Campaign_ID() != 0 && line.getC_Campaign_ID() != invoice.getC_Campaign_ID()) + invoice.setC_Campaign_ID(line.getC_Campaign_ID()); + if (line.getC_Project_ID() != 0 && line.getC_Project_ID() != invoice.getC_Project_ID()) + invoice.setC_Project_ID(line.getC_Project_ID()); + if (!invoice.save()) + new IllegalStateException("Cannot save Invoice"); + + // Create OrderLine + MInvoiceLine il = new MInvoiceLine (invoice); + // + if (line.getM_Product_ID() != 0) + il.setM_Product_ID(line.getM_Product_ID(), true); + il.setQty(line.getQtyReimbursed()); // Entered/Invoiced + il.setDescription(line.getDescription()); + // + il.setC_Project_ID(line.getC_Project_ID()); + il.setC_ProjectPhase_ID(line.getC_ProjectPhase_ID()); + il.setC_ProjectTask_ID(line.getC_ProjectTask_ID()); + il.setC_Activity_ID(line.getC_Activity_ID()); + il.setC_Campaign_ID(line.getC_Campaign_ID()); + // + // il.setPrice(); // not really a list/limit price for reimbursements + il.setPrice(line.getPriceReimbursed()); // + il.setTax(); + if (!il.save()) + new IllegalStateException("Cannot save Invoice Line"); + // Update TEL + line.setC_InvoiceLine_ID(il.getC_InvoiceLine_ID()); + line.save(); + } // for all expense lines + } // ********* Expense Line Loop + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + completeInvoice (invoice); + return "@Created@=" + m_noInvoices; + } // doIt + + /** + * Complete Invoice + * @param invoice invoice + */ + private void completeInvoice (MInvoice invoice) + { + if (invoice == null) + return; + invoice.setDocAction(DocAction.ACTION_Prepare); + invoice.processIt(DocAction.ACTION_Prepare); + if (!invoice.save()) + new IllegalStateException("Cannot save Invoice"); + // + m_noInvoices++; + addLog(invoice.get_ID(), invoice.getDateInvoiced(), + invoice.getGrandTotal(), invoice.getDocumentNo()); + } // completeInvoice + +} // ExpenseAPInvoice diff --git a/base/src/org/compiere/process/ExpenseSOrder.java b/base/src/org/compiere/process/ExpenseSOrder.java new file mode 100644 index 0000000000..917ebfbb2f --- /dev/null +++ b/base/src/org/compiere/process/ExpenseSOrder.java @@ -0,0 +1,280 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Create Sales Orders from Expense Reports + * + * @author Jorg Janke + * @version $Id: ExpenseSOrder.java,v 1.3 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ExpenseSOrder extends SvrProcess +{ + /** BPartner */ + private int p_C_BPartner_ID = 0; + /** Date Drom */ + private Timestamp p_DateFrom = null; + /** Date To */ + private Timestamp m_DateTo = null; + + /** No SO generated */ + private int m_noOrders = 0; + /** Current Order */ + private MOrder m_order = null; + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = para[i].getParameterAsInt(); + else if (name.equals("DateExpense")) + { + p_DateFrom = (Timestamp)para[i].getParameter(); + m_DateTo = (Timestamp)para[i].getParameter_To(); + } + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + + /** + * Perform process. + * @return Message to be translated + * @throws Exception + */ + protected String doIt() throws java.lang.Exception + { + StringBuffer sql = new StringBuffer("SELECT * FROM S_TimeExpenseLine el " + + "WHERE el.AD_Client_ID=?" // #1 + + " AND el.C_BPartner_ID>0 AND el.IsInvoiced='Y'" // Business Partner && to be invoiced + + " AND el.C_OrderLine_ID IS NULL" // not invoiced yet + + " AND EXISTS (SELECT * FROM S_TimeExpense e " // processed only + + "WHERE el.S_TimeExpense_ID=e.S_TimeExpense_ID AND e.Processed='Y')"); + if (p_C_BPartner_ID != 0) + sql.append(" AND el.C_BPartner_ID=?"); // #2 + if (p_DateFrom != null || m_DateTo != null) + { + sql.append(" AND EXISTS (SELECT * FROM S_TimeExpense e " + + "WHERE el.S_TimeExpense_ID=e.S_TimeExpense_ID"); + if (p_DateFrom != null) + sql.append(" AND e.DateReport >= ?"); // #3 + if (m_DateTo != null) + sql.append(" AND e.DateReport <= ?"); // #4 + sql.append(")"); + } + sql.append(" ORDER BY el.C_BPartner_ID, el.C_Project_ID, el.S_TimeExpense_ID, el.Line"); + + // + MBPartner oldBPartner = null; + int old_Project_ID = -1; + MTimeExpense te = null; + // + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql.toString(), get_TrxName()); + int par = 1; + pstmt.setInt(par++, getAD_Client_ID()); + if (p_C_BPartner_ID != 0) + pstmt.setInt(par++, p_C_BPartner_ID); + if (p_DateFrom != null) + pstmt.setTimestamp(par++, p_DateFrom); + if (m_DateTo != null) + pstmt.setTimestamp(par++, m_DateTo); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) // ********* Expense Line Loop + { + MTimeExpenseLine tel = new MTimeExpenseLine(getCtx(), rs, get_TrxName()); + if (!tel.isInvoiced()) + continue; + + // New BPartner - New Order + if (oldBPartner == null + || oldBPartner.getC_BPartner_ID() != tel.getC_BPartner_ID()) + { + completeOrder (); + oldBPartner = new MBPartner (getCtx(), tel.getC_BPartner_ID(), get_TrxName()); + } + // New Project - New Order + if (old_Project_ID != tel.getC_Project_ID()) + { + completeOrder (); + old_Project_ID = tel.getC_Project_ID(); + } + if (te == null || te.getS_TimeExpense_ID() != tel.getS_TimeExpense_ID()) + te = new MTimeExpense (getCtx(), tel.getS_TimeExpense_ID(), get_TrxName()); + // + processLine (te, tel, oldBPartner); + } // ********* Expense Line Loop + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + completeOrder (); + + return "@Created@=" + m_noOrders; + } // doIt + + /** + * Process Expense Line + * @param te header + * @param tel line + * @param bp bp + */ + private void processLine (MTimeExpense te, MTimeExpenseLine tel, MBPartner bp) + { + if (m_order == null) + { + log.info("New Order for " + bp + ", Project=" + tel.getC_Project_ID()); + m_order = new MOrder (getCtx(), 0, get_TrxName()); + m_order.setAD_Org_ID(tel.getAD_Org_ID()); + m_order.setC_DocTypeTarget_ID(MOrder.DocSubTypeSO_OnCredit); + // + m_order.setBPartner(bp); + if (m_order.getC_BPartner_Location_ID() == 0) + { + log.log(Level.SEVERE, "No BP Location: " + bp); + addLog(0, te.getDateReport(), + null, "No Location: " + te.getDocumentNo() + " " + bp.getName()); + m_order = null; + return; + } + m_order.setM_Warehouse_ID(te.getM_Warehouse_ID()); + if (tel.getC_Activity_ID() != 0) + m_order.setC_Activity_ID(tel.getC_Activity_ID()); + if (tel.getC_Campaign_ID() != 0) + m_order.setC_Campaign_ID(tel.getC_Campaign_ID()); + if (tel.getC_Project_ID() != 0) + { + m_order.setC_Project_ID(tel.getC_Project_ID()); + // Optionally Overwrite BP Price list from Project + MProject project = new MProject (getCtx(), tel.getC_Project_ID(), get_TrxName()); + if (project.getM_PriceList_ID() != 0) + m_order.setM_PriceList_ID(project.getM_PriceList_ID()); + } + m_order.setSalesRep_ID(te.getDoc_User_ID()); + // + if (!m_order.save()) + { + throw new IllegalStateException("Cannot save Order"); + } + } + else + { + // Update Header info + if (tel.getC_Activity_ID() != 0 && tel.getC_Activity_ID() != m_order.getC_Activity_ID()) + m_order.setC_Activity_ID(tel.getC_Activity_ID()); + if (tel.getC_Campaign_ID() != 0 && tel.getC_Campaign_ID() != m_order.getC_Campaign_ID()) + m_order.setC_Campaign_ID(tel.getC_Campaign_ID()); + if (!m_order.save()) + new IllegalStateException("Cannot save Order"); + } + + // OrderLine + MOrderLine ol = new MOrderLine (m_order); + // + if (tel.getM_Product_ID() != 0) + ol.setM_Product_ID(tel.getM_Product_ID(), + tel.getC_UOM_ID()); + if (tel.getS_ResourceAssignment_ID() != 0) + ol.setS_ResourceAssignment_ID(tel.getS_ResourceAssignment_ID()); + ol.setQty(tel.getQtyInvoiced()); // + ol.setDescription(tel.getDescription()); + // + ol.setC_Project_ID(tel.getC_Project_ID()); + ol.setC_ProjectPhase_ID(tel.getC_ProjectPhase_ID()); + ol.setC_ProjectTask_ID(tel.getC_ProjectTask_ID()); + ol.setC_Activity_ID(tel.getC_Activity_ID()); + ol.setC_Campaign_ID(tel.getC_Campaign_ID()); + // + BigDecimal price = tel.getPriceInvoiced(); // + if (price != null && price.compareTo(Env.ZERO) != 0) + { + if (tel.getC_Currency_ID() != m_order.getC_Currency_ID()) + price = MConversionRate.convert(getCtx(), price, + tel.getC_Currency_ID(), m_order.getC_Currency_ID(), + m_order.getAD_Client_ID(), m_order.getAD_Org_ID()); + ol.setPrice(price); + } + else + ol.setPrice(); + if (tel.getC_UOM_ID() != 0 && ol.getC_UOM_ID() == 0) + ol.setC_UOM_ID(tel.getC_UOM_ID()); + ol.setTax(); + if (!ol.save()) + { + throw new IllegalStateException("Cannot save Order Line"); + } + // Update TimeExpense Line + tel.setC_OrderLine_ID(ol.getC_OrderLine_ID()); + if (tel.save()) + log.fine("Updated " + tel + " with C_OrderLine_ID"); + else + log.log(Level.SEVERE, "Not Updated " + tel + " with C_OrderLine_ID"); + + } // processLine + + + /** + * Complete Order + */ + private void completeOrder () + { + if (m_order == null) + return; + m_order.setDocAction(DocAction.ACTION_Prepare); + m_order.processIt(DocAction.ACTION_Prepare); + if (!m_order.save()) + throw new IllegalStateException("Cannot save Order"); + m_noOrders++; + addLog (m_order.get_ID(), m_order.getDateOrdered(), m_order.getGrandTotal(), m_order.getDocumentNo()); + m_order = null; + } // completeOrder + +} // ExpenseSOrder diff --git a/base/src/org/compiere/process/FactAcctReset.java b/base/src/org/compiere/process/FactAcctReset.java new file mode 100644 index 0000000000..b10c0ddad5 --- /dev/null +++ b/base/src/org/compiere/process/FactAcctReset.java @@ -0,0 +1,237 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.report.*; +import org.compiere.util.*; + +/** + * Accounting Fact Reset + * + * @author Jorg Janke + * @version $Id: FactAcctReset.java,v 1.5 2006/09/21 21:05:02 jjanke Exp $ + */ +public class FactAcctReset extends SvrProcess +{ + /** Client Parameter */ + private int p_AD_Client_ID = 0; + /** Table Parameter */ + private int p_AD_Table_ID = 0; + /** Delete Parameter */ + private boolean p_DeletePosting = false; + + private int m_countReset = 0; + private int m_countDelete = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Client_ID")) + p_AD_Client_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("AD_Table_ID")) + p_AD_Table_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("DeletePosting")) + p_DeletePosting = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("AD_Client_ID=" + p_AD_Client_ID + + ", AD_Table_ID=" + p_AD_Table_ID + ", DeletePosting=" + p_DeletePosting); + // List of Tables with Accounting Consequences + String sql = "SELECT AD_Table_ID, TableName " + + "FROM AD_Table t " + + "WHERE t.IsView='N'"; + if (p_AD_Table_ID > 0) + sql += " AND t.AD_Table_ID=" + p_AD_Table_ID; + sql += " AND EXISTS (SELECT * FROM AD_Column c " + + "WHERE t.AD_Table_ID=c.AD_Table_ID AND c.ColumnName='Posted' AND c.IsActive='Y')"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + int AD_Table_ID = rs.getInt(1); + String TableName = rs.getString(2); + if (p_DeletePosting) + delete (TableName, AD_Table_ID); + else + reset (TableName); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // Balances + if (p_DeletePosting) + FinBalance.updateBalanceClient(getCtx(), p_AD_Client_ID, true); // delete + // + return "@Updated@ = " + m_countReset + ", @Deleted@ = " + m_countDelete; + } // doIt + + /** + * Reset Accounting Table and update count + * @param TableName table + */ + private void reset (String TableName) + { + String sql = "UPDATE " + TableName + + " SET Processing='N' WHERE AD_Client_ID=" + p_AD_Client_ID + + " AND (Processing<>'N' OR Processing IS NULL)"; + int unlocked = DB.executeUpdate(sql, get_TrxName()); + // + sql = "UPDATE " + TableName + + " SET Posted='N' WHERE AD_Client_ID=" + p_AD_Client_ID + + " AND (Posted NOT IN ('Y','N') OR Posted IS NULL) AND Processed='Y'"; + int invalid = DB.executeUpdate(sql, get_TrxName()); + // + if (unlocked + invalid != 0) + log.fine(TableName + " - Unlocked=" + unlocked + " - Invalid=" + invalid); + m_countReset += unlocked + invalid; + } // reset + + /** + * Delete Accounting Table where period status is open and update count. + * @param TableName table name + * @param AD_Table_ID table + */ + private void delete (String TableName, int AD_Table_ID) + { + reset(TableName); + m_countReset = 0; + // + String docBaseType = null; + if (AD_Table_ID == MInvoice.Table_ID) + docBaseType = "IN ('" + MPeriodControl.DOCBASETYPE_APInvoice + + "','" + MPeriodControl.DOCBASETYPE_APCreditMemo + + "','" + MPeriodControl.DOCBASETYPE_ARInvoice + + "','" + MPeriodControl.DOCBASETYPE_ARCreditMemo + + "','" + MPeriodControl.DOCBASETYPE_ARProFormaInvoice + "')"; + else if (AD_Table_ID == MInOut.Table_ID) + docBaseType = "IN ('" + MPeriodControl.DOCBASETYPE_MaterialDelivery + + "','" + MPeriodControl.DOCBASETYPE_MaterialReceipt + "')"; + else if (AD_Table_ID == MPayment.Table_ID) + docBaseType = "IN ('" + MPeriodControl.DOCBASETYPE_APPayment + + "','" + MPeriodControl.DOCBASETYPE_ARReceipt + "')"; + else if (AD_Table_ID == MOrder.Table_ID) + docBaseType = "IN ('" + MPeriodControl.DOCBASETYPE_SalesOrder + + "','" + MPeriodControl.DOCBASETYPE_PurchaseOrder + "')"; + else if (AD_Table_ID == MProjectIssue.Table_ID) + docBaseType = "= '" + MPeriodControl.DOCBASETYPE_ProjectIssue + "'"; + else if (AD_Table_ID == MBankStatement.Table_ID) + docBaseType = "= '" + MPeriodControl.DOCBASETYPE_BankStatement + "'"; + else if (AD_Table_ID == MCash.Table_ID) + docBaseType = "= '" + MPeriodControl.DOCBASETYPE_CashJournal + "'"; + else if (AD_Table_ID == MAllocationHdr.Table_ID) + docBaseType = "= '" + MPeriodControl.DOCBASETYPE_PaymentAllocation + "'"; + else if (AD_Table_ID == MJournal.Table_ID) + docBaseType = "= '" + MPeriodControl.DOCBASETYPE_GLJournal + "'"; + // else if (AD_Table_ID == M.Table_ID) + // docBaseType = "= '" + MPeriodControl.DOCBASETYPE_GLDocument + "'"; + else if (AD_Table_ID == MMovement.Table_ID) + docBaseType = "= '" + MPeriodControl.DOCBASETYPE_MaterialMovement + "'"; + else if (AD_Table_ID == MRequisition.Table_ID) + docBaseType = "= '" + MPeriodControl.DOCBASETYPE_PurchaseRequisition + "'"; + else if (AD_Table_ID == MInventory.Table_ID) + docBaseType = "= '" + MPeriodControl.DOCBASETYPE_MaterialPhysicalInventory + "'"; + else if (AD_Table_ID == X_M_Production.Table_ID) + docBaseType = "= '" + MPeriodControl.DOCBASETYPE_MaterialProduction + "'"; + else if (AD_Table_ID == MMatchInv.Table_ID) + docBaseType = "= '" + MPeriodControl.DOCBASETYPE_MatchInvoice + "'"; + else if (AD_Table_ID == MMatchPO.Table_ID) + docBaseType = "= '" + MPeriodControl.DOCBASETYPE_MatchPO + "'"; + // + if (docBaseType == null) + { + String s = TableName + ": Unknown DocBaseType"; + log.severe(s); + addLog(s); + docBaseType = ""; + return; + } + else + docBaseType = " AND pc.DocBaseType " + docBaseType; + + // Doc + String sql1 = "UPDATE " + TableName + " doc" + + " SET Posted='N', Processing='N' " + + "WHERE AD_Client_ID=" + p_AD_Client_ID + + " AND (Posted<>'N' OR Posted IS NULL OR Processing<>'N' OR Processing IS NULL)" + + " AND EXISTS (SELECT * FROM C_PeriodControl pc" + + " INNER JOIN Fact_Acct fact ON (fact.C_Period_ID=pc.C_Period_ID) " + + "WHERE pc.PeriodStatus = 'O'" + docBaseType + + " AND fact.AD_Table_ID=" + AD_Table_ID + + " AND fact.Record_ID=doc." + TableName + "_ID)"; + int reset = DB.executeUpdate(sql1, get_TrxName()); + // Fact + String sql2 = "DELETE Fact_Acct fact " + + "WHERE AD_Client_ID=" + p_AD_Client_ID + + " AND AD_Table_ID=" + AD_Table_ID + + " AND EXISTS (SELECT * FROM C_PeriodControl pc " + + "WHERE pc.PeriodStatus = 'O'" + docBaseType + + " AND fact.C_Period_ID=pc.C_Period_ID)"; + int deleted = DB.executeUpdate(sql2, get_TrxName()); + // + log.info(TableName + "(" + AD_Table_ID + ") - Reset=" + reset + " - Deleted=" + deleted); + String s = TableName + " - Reset=" + reset + " - Deleted=" + deleted; + addLog(s); + if (reset == 0) + log.finest(sql1); + if (deleted == 0) + log.finest(sql2); + // + m_countReset += reset; + m_countDelete += deleted; + } // delete + +} // FactAcctReset diff --git a/base/src/org/compiere/process/ImportAccount.java b/base/src/org/compiere/process/ImportAccount.java new file mode 100644 index 0000000000..2f5d4c021f --- /dev/null +++ b/base/src/org/compiere/process/ImportAccount.java @@ -0,0 +1,617 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Import Accounts from I_ElementValue + * + * @author Jorg Janke + * @version $Id: ImportAccount.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class ImportAccount extends SvrProcess +{ + /** Client to be imported to */ + private int m_AD_Client_ID = 0; + /** Default Element */ + private int m_C_Element_ID = 0; + /** Update Default Accounts */ + private boolean m_updateDefaultAccounts = false; + /** Create New Combination */ + private boolean m_createNewCombination = true; + + /** Delete old Imported */ + private boolean m_deleteOldImported = false; + + /** Organization to be imported to */ + private int m_AD_Org_ID = 0; + + /** Effective */ + private Timestamp m_DateValue = null; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Client_ID")) + m_AD_Client_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_Element_ID")) + m_C_Element_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("UpdateDefaultAccounts")) + m_updateDefaultAccounts = "Y".equals(para[i].getParameter()); + else if (name.equals("CreateNewCombination")) + m_createNewCombination = "Y".equals(para[i].getParameter()); + else if (name.equals("DeleteOldImported")) + m_deleteOldImported = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + if (m_DateValue == null) + m_DateValue = new Timestamp (System.currentTimeMillis()); + } // prepare + + + /** + * Perrform process. + * @return Message + * @throws Exception + */ + protected String doIt() throws java.lang.Exception + { + StringBuffer sql = null; + int no = 0; + String clientCheck = " AND AD_Client_ID=" + m_AD_Client_ID; + + // **** Prepare **** + + // Delete Old Imported + if (m_deleteOldImported) + { + sql = new StringBuffer ("DELETE I_ElementValue " + + "WHERE I_IsImported='Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Delete Old Impored =" + no); + } + + // Set Client, Org, IsActive, Created/Updated + sql = new StringBuffer ("UPDATE I_ElementValue " + + "SET AD_Client_ID = COALESCE (AD_Client_ID, ").append(m_AD_Client_ID).append(")," + + " AD_Org_ID = COALESCE (AD_Org_ID, 0)," + + " IsActive = COALESCE (IsActive, 'Y')," + + " Created = COALESCE (Created, SysDate)," + + " CreatedBy = COALESCE (CreatedBy, 0)," + + " Updated = COALESCE (Updated, SysDate)," + + " UpdatedBy = COALESCE (UpdatedBy, 0)," + + " I_ErrorMsg = NULL," + + " I_IsImported = 'N' " + + "WHERE I_IsImported<>'Y' OR I_IsImported IS NULL"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Reset=" + no); + + // **** Prepare **** + + // Set Element + if (m_C_Element_ID != 0) + { + sql = new StringBuffer ("UPDATE I_ElementValue " + + "SET ElementName=(SELECT Name FROM C_Element WHERE C_Element_ID=").append(m_C_Element_ID).append(") " + + "WHERE ElementName IS NULL AND C_Element_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Element Default=" + no); + } + // + sql = new StringBuffer ("UPDATE I_ElementValue i " + + "SET C_Element_ID = (SELECT C_Element_ID FROM C_Element e" + + " WHERE i.ElementName=e.Name AND i.AD_Client_ID=e.AD_Client_ID)" + + "WHERE C_Element_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Element=" + no); + // + sql = new StringBuffer ("UPDATE I_ElementValue " + + "SET I_IsImported='E', I_ErrorMsg='ERR=Invalid Element, ' " + + "WHERE C_Element_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Invalid Element=" + no); + + // Set Column + sql = new StringBuffer ("UPDATE I_ElementValue i " + + "SET AD_Column_ID = (SELECT AD_Column_ID FROM AD_Column c" + + " WHERE UPPER(i.Default_Account)=UPPER(c.ColumnName)" + + " AND c.AD_Table_ID IN (315,266) AND AD_Reference_ID=25) " + + "WHERE Default_Account IS NOT NULL AND AD_Column_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Column=" + no); + // + sql = new StringBuffer ("UPDATE I_ElementValue " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Column, ' " + + "WHERE AD_Column_ID IS NULL AND Default_Account IS NOT NULL" + + " AND UPPER(Default_Account)<>'DEFAULT_ACCT'" // ignore default account + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Invalid Column=" + no); + + // Set Post* Defaults (ignore errors) + String[] yColumns = new String[] {"PostActual", "PostBudget", "PostStatistical", "PostEncumbrance"}; + for (int i = 0; i < yColumns.length; i++) + { + sql = new StringBuffer ("UPDATE I_ElementValue SET ") + .append(yColumns[i]).append("='Y' WHERE ") + .append(yColumns[i]).append(" IS NULL OR ") + .append(yColumns[i]).append(" NOT IN ('Y','N')" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set " + yColumns[i] + " Default=" + no); + } + // Summary + sql = new StringBuffer ("UPDATE I_ElementValue " + + "SET IsSummary='N' " + + "WHERE IsSummary IS NULL OR IsSummary NOT IN ('Y','N')" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set IsSummary Default=" + no); + + // Doc Controlled + sql = new StringBuffer ("UPDATE I_ElementValue " + + "SET IsDocControlled = CASE WHEN AD_Column_ID IS NOT NULL THEN 'Y' ELSE 'N' END " + + "WHERE IsDocControlled IS NULL OR IsDocControlled NOT IN ('Y','N')" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set IsDocumentControlled Default=" + no); + + // Check Account Type A (E) L M O R + sql = new StringBuffer ("UPDATE I_ElementValue " + + "SET AccountType='E' " + + "WHERE AccountType IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set AccountType Default=" + no); + // + sql = new StringBuffer ("UPDATE I_ElementValue " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid AccountType, ' " + + "WHERE AccountType NOT IN ('A','E','L','M','O','R')" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Invalid AccountType=" + no); + + // Check Account Sign (N) C B + sql = new StringBuffer ("UPDATE I_ElementValue " + + "SET AccountSign='N' " + + "WHERE AccountSign IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set AccountSign Default=" + no); + // + sql = new StringBuffer ("UPDATE I_ElementValue " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid AccountSign, ' " + + "WHERE AccountSign NOT IN ('N','C','D')" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Invalid AccountSign=" + no); + + // No Value + sql = new StringBuffer ("UPDATE I_ElementValue " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No Key, ' " + + "WHERE (Value IS NULL OR Value='')" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Invalid Key=" + no); + + // **** Update ElementValue from existing + sql = new StringBuffer ("UPDATE I_ElementValue i " + + "SET C_ElementValue_ID=(SELECT C_ElementValue_ID FROM C_ElementValue ev" + + " INNER JOIN C_Element e ON (ev.C_Element_ID=e.C_Element_ID)" + + " WHERE i.C_Element_ID=e.C_Element_ID AND i.AD_Client_ID=e.AD_Client_ID" + + " AND i.Value=ev.Value) " + + "WHERE C_ElementValue_ID IS NULL" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Found ElementValue=" + no); + + commit(); + + // ------------------------------------------------------------------- + int noInsert = 0; + int noUpdate = 0; + + // Go through Records + sql = new StringBuffer ("SELECT * " + + "FROM I_ElementValue " + + "WHERE I_IsImported='N'").append(clientCheck) + .append(" ORDER BY I_ElementValue_ID"); + try + { + PreparedStatement pstmt = DB.prepareStatement(sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + X_I_ElementValue impEV = new X_I_ElementValue(getCtx(), rs, get_TrxName()); + int C_ElementValue_ID = impEV.getC_ElementValue_ID(); + int I_ElementValue_ID = impEV.getI_ElementValue_ID(); + + // **** Create/Update ElementValue + if (C_ElementValue_ID == 0) // New + { + MElementValue ev = new MElementValue(impEV); + if (ev.save()) + { + noInsert++; + impEV.setC_ElementValue_ID(ev.getC_ElementValue_ID()); + impEV.setI_IsImported(true); + impEV.save(); + } + else + { + sql = new StringBuffer ("UPDATE I_ElementValue i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||").append(DB.TO_STRING("Insert ElementValue ")) + .append("WHERE I_ElementValue_ID=").append(I_ElementValue_ID); + DB.executeUpdate(sql.toString(), get_TrxName()); + } + } + else // Update existing + { + MElementValue ev = new MElementValue (getCtx(), C_ElementValue_ID, null); + if (ev.get_ID() != C_ElementValue_ID) + { + + } + ev.set(impEV); + if (ev.save()) + { + noUpdate++; + impEV.setI_IsImported(true); + impEV.save(); + } + else + { + sql = new StringBuffer ("UPDATE I_ElementValue i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||").append(DB.TO_STRING("Update ElementValue")) + .append("WHERE I_ElementValue_ID=").append(I_ElementValue_ID); + DB.executeUpdate(sql.toString(), get_TrxName()); + } + } + } // for all I_Product + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + throw new Exception ("create", e); + } + + // Set Error to indicator to not imported + sql = new StringBuffer ("UPDATE I_ElementValue " + + "SET I_IsImported='N', Updated=SysDate " + + "WHERE I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog (0, null, new BigDecimal (no), "@Errors@"); + addLog (0, null, new BigDecimal (noInsert), "@C_ElementValue_ID@: @Inserted@"); + addLog (0, null, new BigDecimal (noUpdate), "@C_ElementValue_ID@: @Updated@"); + + commit(); + + // ***** Set Parent + sql = new StringBuffer ("UPDATE I_ElementValue i " + + "SET ParentElementValue_ID=(SELECT C_ElementValue_ID" + + " FROM C_ElementValue ev WHERE i.C_Element_ID=ev.C_Element_ID" + + " AND i.ParentValue=ev.Value AND i.AD_Client_ID=ev.AD_Client_ID) " + + "WHERE ParentElementValue_ID IS NULL" + + " AND I_IsImported='Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Found Parent ElementValue=" + no); + // + sql = new StringBuffer ("UPDATE I_ElementValue " + + "SET I_ErrorMsg=I_ErrorMsg||'Info=ParentNotFound, ' " + + "WHERE ParentElementValue_ID IS NULL AND ParentValue IS NOT NULL" + + " AND I_IsImported='Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Not Found Patent ElementValue=" + no); + // + sql = new StringBuffer ("SELECT i.ParentElementValue_ID, i.I_ElementValue_ID," + + " e.AD_Tree_ID, i.C_ElementValue_ID, i.Value||'-'||i.Name AS Info " + + "FROM I_ElementValue i" + + " INNER JOIN C_Element e ON (i.C_Element_ID=e.C_Element_ID) " + + "WHERE i.C_ElementValue_ID IS NOT NULL AND e.AD_Tree_ID IS NOT NULL" + + " AND i.ParentElementValue_ID IS NOT NULL" + + " AND i.I_IsImported='Y' AND i.AD_Client_ID=").append(m_AD_Client_ID); + int noParentUpdate = 0; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + // + String updateSQL = "UPDATE AD_TreeNode SET Parent_ID=?, SeqNo=? " + + "WHERE AD_Tree_ID=? AND Node_ID=?"; + //begin e-evolution vpj-cd 15 nov 2005 PostgreSQL + //PreparedStatement updateStmt = DB.prepareStatement(updateSQL, get_TrxName()); + PreparedStatement updateStmt = DB.prepareStatement(updateSQL, ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); + //end + // + while (rs.next()) + { + updateStmt.setInt(1, rs.getInt(1)); // Parent + updateStmt.setInt(2, rs.getInt(2)); // SeqNo (assume sequenec in import is the same) + updateStmt.setInt(3, rs.getInt(3)); // Tree + updateStmt.setInt(4, rs.getInt(4)); // Node + try + { + no = updateStmt.executeUpdate(); + noParentUpdate += no; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, "(ParentUpdate)", ex); + no = 0; + } + if (no == 0) + log.info("Parent not found for " + rs.getString(5)); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "(ParentUpdateLoop) " + sql.toString(), e); + } + addLog (0, null, new BigDecimal (noParentUpdate), "@ParentElementValue_ID@: @Updated@"); + + // Reset Processing Flag + sql = new StringBuffer ("UPDATE I_ElementValue " + + "SET Processing='-'" + + "WHERE I_IsImported='Y' AND Processed='Y' AND Processing='Y'" + + " AND C_ElementValue_ID IS NOT NULL") + .append(clientCheck); + if (m_updateDefaultAccounts) + sql.append(" AND AD_Column_ID IS NULL"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Reset Processing Flag=" + no); + + if (m_updateDefaultAccounts) + updateDefaults(clientCheck); + + // Update Description + sql = new StringBuffer("SELECT * FROM C_ValidCombination vc " + + "WHERE EXISTS (SELECT * FROM I_ElementValue i " + + "WHERE vc.Account_ID=i.C_ElementValue_ID)"); + + + return ""; + } // doIt + + + /************************************************************************** + * Update Default Accounts + * @param clientCheck client where cluase + */ + private void updateDefaults (String clientCheck) + { + log.config("CreateNewCombination=" + m_createNewCombination); + + // **** Update Defaults + StringBuffer sql = new StringBuffer ("SELECT C_AcctSchema_ID FROM C_AcctSchema_Element " + + "WHERE C_Element_ID=?").append(clientCheck); + try + { + PreparedStatement pstmt = DB.prepareStatement(sql.toString(), get_TrxName()); + pstmt.setInt(1, m_C_Element_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + updateDefaultAccounts (rs.getInt(1)); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + + // Default Account DEFAULT_ACCT + sql = new StringBuffer ("UPDATE C_AcctSchema_Element e " + + "SET C_ElementValue_ID=(SELECT C_ElementValue_ID FROM I_ElementValue i" + + " WHERE e.C_Element_ID=i.C_Element_ID AND i.C_ElementValue_ID IS NOT NULL" + + " AND UPPER(i.Default_Account)='DEFAULT_ACCT') " + + "WHERE EXISTS (SELECT * FROM I_ElementValue i" + + " WHERE e.C_Element_ID=i.C_Element_ID AND i.C_ElementValue_ID IS NOT NULL" + + " AND UPPER(i.Default_Account)='DEFAULT_ACCT' " + + " AND i.I_IsImported='Y')") + .append(clientCheck); + int no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog (0, null, new BigDecimal (no), "@C_AcctSchema_Element_ID@: @Updated@"); + } // updateDefaults + + /** + * Update Default Accounts. + * _Default.xxxx = C_ValidCombination_ID => Account_ID=C_ElementValue_ID + * @param C_AcctSchema_ID Accounting Schema + */ + private void updateDefaultAccounts (int C_AcctSchema_ID) + { + log.config("C_AcctSchema_ID=" + C_AcctSchema_ID); + + MAcctSchema as = new MAcctSchema (getCtx(), C_AcctSchema_ID, null); + if (as.getAcctSchemaElement("AC").getC_Element_ID() != m_C_Element_ID) + { + log.log(Level.SEVERE, "C_Element_ID=" + m_C_Element_ID + " not in AcctSchema=" + as); + return; + } + + int[] counts = new int[] {0, 0, 0}; + + String sql = "SELECT i.C_ElementValue_ID, t.TableName, c.ColumnName, i.I_ElementValue_ID " + + "FROM I_ElementValue i" + + " INNER JOIN AD_Column c ON (i.AD_Column_ID=c.AD_Column_ID)" + + " INNER JOIN AD_Table t ON (c.AD_Table_ID=t.AD_Table_ID) " + + "WHERE i.I_IsImported='Y' AND i.Processed='Y' AND Processing='Y'" + + " AND i.C_ElementValue_ID IS NOT NULL AND C_Element_ID=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, m_C_Element_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + int C_ElementValue_ID = rs.getInt(1); + String TableName = rs.getString(2); + String ColumnName = rs.getString(3); + int I_ElementValue_ID = rs.getInt(4); + // Update it + int u = updateDefaultAccount(TableName, ColumnName, C_AcctSchema_ID, C_ElementValue_ID); + counts[u]++; + if (u != UPDATE_ERROR) + { + sql = "UPDATE I_ElementValue SET Processing='N' " + + "WHERE I_ElementValue_ID=" + I_ElementValue_ID; + int no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 1) + log.log(Level.SEVERE, "Updated=" + no); + } + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "", e); + } + addLog (0, null, new BigDecimal (counts[UPDATE_ERROR]), as.toString() + ": @Errors@"); + addLog (0, null, new BigDecimal (counts[UPDATE_YES]), as.toString() + ": @Updated@"); + addLog (0, null, new BigDecimal (counts[UPDATE_SAME]), as.toString() + ": OK"); + + } // createDefaultAccounts + + + private static final int UPDATE_ERROR = 0; + private static final int UPDATE_YES = 1; + private static final int UPDATE_SAME = 2; + + /** + * Update Default Account. + * This is the sql to delete unused accounts - with the import still in the table(!): + DELETE C_ElementValue e + WHERE NOT EXISTS (SELECT * FROM Fact_Acct f WHERE f.Account_ID=e.C_ElementValue_ID) + AND NOT EXISTS (SELECT * FROM C_ValidCombination vc WHERE vc.Account_ID=e.C_ElementValue_ID) + AND NOT EXISTS (SELECT * FROM I_ElementValue i WHERE i.C_ElementValue_ID=e.C_ElementValue_ID); + * @param TableName Table Name + * @param ColumnName Column Name + * @param C_AcctSchema_ID Account Schema + * @param C_ElementValue_ID new Account + * @return UPDATE_* status + */ + private int updateDefaultAccount (String TableName, String ColumnName, int C_AcctSchema_ID, int C_ElementValue_ID) + { + log.fine(TableName + "." + ColumnName + " - " + C_ElementValue_ID); + int retValue = UPDATE_ERROR; + StringBuffer sql = new StringBuffer ("SELECT x.") + .append(ColumnName).append(",Account_ID FROM ") + .append(TableName).append(" x INNER JOIN C_ValidCombination vc ON (x.") + .append(ColumnName).append("=vc.C_ValidCombination_ID) ") + .append("WHERE x.C_AcctSchema_ID=").append(C_AcctSchema_ID); + try + { + PreparedStatement pstmt = DB.prepareStatement(sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + int C_ValidCombination_ID = rs.getInt(1); + int Account_ID = rs.getInt(2); + // The current account value is the same + if (Account_ID == C_ElementValue_ID) + { + retValue = UPDATE_SAME; + log.fine("Account_ID same as new value"); + } + // We need to update the Account Value + else + { + if (m_createNewCombination) + { + MAccount acct = MAccount.get(getCtx(), C_ValidCombination_ID); + acct.setAccount_ID(C_ElementValue_ID); + if (acct.save()) + { + int newC_ValidCombination_ID = acct.getC_ValidCombination_ID(); + if (C_ValidCombination_ID != newC_ValidCombination_ID) + { + sql = new StringBuffer ("UPDATE ").append(TableName) + .append(" SET ").append(ColumnName).append("=").append(newC_ValidCombination_ID) + .append(" WHERE C_AcctSchema_ID=").append(C_AcctSchema_ID); + int no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("ImportAccount.updateDefaultAccount - #" + no + " - " + + TableName + "." + ColumnName + " - " + C_ElementValue_ID + + " -- " + C_ValidCombination_ID + " -> " + newC_ValidCombination_ID); + if (no == 1) + retValue = UPDATE_YES; + } + } + else + log.log(Level.SEVERE, "Account not saved - " + acct); + } + else // Replace Combination + { + // Only Acct Combination directly + sql = new StringBuffer ("UPDATE C_ValidCombination SET Account_ID=") + .append(C_ElementValue_ID).append(" WHERE C_ValidCombination_ID=").append(C_ValidCombination_ID); + int no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("ImportAccount.updateDefaultAccount - Replace #" + no + " - " + + "C_ValidCombination_ID=" + C_ValidCombination_ID + ", New Account_ID=" + C_ElementValue_ID); + if (no == 1) + { + retValue = UPDATE_YES; + // Where Acct was used + sql = new StringBuffer ("UPDATE C_ValidCombination SET Account_ID=") + .append(C_ElementValue_ID).append(" WHERE Account_ID=").append(Account_ID); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("ImportAccount.updateDefaultAccount - Replace VC #" + no + " - " + + "Account_ID=" + Account_ID + ", New Account_ID=" + C_ElementValue_ID); + sql = new StringBuffer ("UPDATE Fact_Acct SET Account_ID=") + .append(C_ElementValue_ID).append(" WHERE Account_ID=").append(Account_ID); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("ImportAccount.updateDefaultAccount - Replace Fact #" + no + " - " + + "Account_ID=" + Account_ID + ", New Account_ID=" + C_ElementValue_ID); + } + } // replace combination + } // need to update + } // for all default accounts + else + log.log(Level.SEVERE, "Account not found " + sql); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + + return retValue; + } // updateDefaultAccount + +} // ImportAccount diff --git a/base/src/org/compiere/process/ImportBPartner.java b/base/src/org/compiere/process/ImportBPartner.java new file mode 100644 index 0000000000..904cbc1e12 --- /dev/null +++ b/base/src/org/compiere/process/ImportBPartner.java @@ -0,0 +1,527 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + * Contributor: Carlos Ruiz - globalqss * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Import BPartners from I_BPartner + * + * @author Jorg Janke + * @version $Id: ImportBPartner.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class ImportBPartner extends SvrProcess +{ + /** Client to be imported to */ + private int m_AD_Client_ID = 0; + /** Delete old Imported */ + private boolean m_deleteOldImported = false; + + /** Organization to be imported to */ + private int m_AD_Org_ID = 0; + /** Effective */ + private Timestamp m_DateValue = null; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (name.equals("AD_Client_ID")) + m_AD_Client_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("DeleteOldImported")) + m_deleteOldImported = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + if (m_DateValue == null) + m_DateValue = new Timestamp (System.currentTimeMillis()); + } // prepare + + + /** + * Perrform process. + * @return Message + * @throws Exception + */ + protected String doIt() throws java.lang.Exception + { + StringBuffer sql = null; + int no = 0; + String clientCheck = " AND AD_Client_ID=" + m_AD_Client_ID; + + // **** Prepare **** + + // Delete Old Imported + if (m_deleteOldImported) + { + sql = new StringBuffer ("DELETE I_BPartner " + + "WHERE I_IsImported='Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Delete Old Impored =" + no); + } + + // Set Client, Org, IsActive, Created/Updated + sql = new StringBuffer ("UPDATE I_BPartner " + + "SET AD_Client_ID = COALESCE (AD_Client_ID, ").append(m_AD_Client_ID).append(")," + + " AD_Org_ID = COALESCE (AD_Org_ID, 0)," + + " IsActive = COALESCE (IsActive, 'Y')," + + " Created = COALESCE (Created, SysDate)," + + " CreatedBy = COALESCE (CreatedBy, 0)," + + " Updated = COALESCE (Updated, SysDate)," + + " UpdatedBy = COALESCE (UpdatedBy, 0)," + + " I_ErrorMsg = NULL," + + " I_IsImported = 'N' " + + "WHERE I_IsImported<>'Y' OR I_IsImported IS NULL"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Reset=" + no); + + // Set BP_Group + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET GroupValue=(SELECT Value FROM C_BP_Group g WHERE g.IsDefault='Y'" + + " AND g.AD_Client_ID=i.AD_Client_ID AND ROWNUM=1) " + + "WHERE GroupValue IS NULL AND C_BP_Group_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Group Default=" + no); + // + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET C_BP_Group_ID=(SELECT C_BP_Group_ID FROM C_BP_Group g" + + " WHERE i.GroupValue=g.Value AND g.AD_Client_ID=i.AD_Client_ID) " + + "WHERE C_BP_Group_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Group=" + no); + // + sql = new StringBuffer ("UPDATE I_BPartner " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Group, ' " + + "WHERE C_BP_Group_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Invalid Group=" + no); + + // Set Country + /** + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET CountryCode=(SELECT CountryCode FROM C_Country c WHERE c.IsDefault='Y'" + + " AND c.AD_Client_ID IN (0, i.AD_Client_ID) AND ROWNUM=1) " + + "WHERE CountryCode IS NULL AND C_Country_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Country Default=" + no); + **/ + // + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET C_Country_ID=(SELECT C_Country_ID FROM C_Country c" + + " WHERE i.CountryCode=c.CountryCode AND c.AD_Client_ID IN (0, i.AD_Client_ID)) " + + "WHERE C_Country_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Country=" + no); + // + sql = new StringBuffer ("UPDATE I_BPartner " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Country, ' " + + "WHERE C_Country_ID IS NULL AND (City IS NOT NULL OR Address1 IS NOT NULL)" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Invalid Country=" + no); + + // Set Region + sql = new StringBuffer ("UPDATE I_BPartner i " + + "Set RegionName=(SELECT Name FROM C_Region r" + + " WHERE r.IsDefault='Y' AND r.C_Country_ID=i.C_Country_ID" + + " AND r.AD_Client_ID IN (0, i.AD_Client_ID) AND ROWNUM=1) " + + "WHERE RegionName IS NULL AND C_Region_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Region Default=" + no); + // + sql = new StringBuffer ("UPDATE I_BPartner i " + + "Set C_Region_ID=(SELECT C_Region_ID FROM C_Region r" + + " WHERE r.Name=i.RegionName AND r.C_Country_ID=i.C_Country_ID" + + " AND r.AD_Client_ID IN (0, i.AD_Client_ID)) " + + "WHERE C_Region_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Region=" + no); + // + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Region, ' " + + "WHERE C_Region_ID IS NULL " + + " AND EXISTS (SELECT * FROM C_Country c" + + " WHERE c.C_Country_ID=i.C_Country_ID AND c.HasRegion='Y')" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Invalid Region=" + no); + + // Set Greeting + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET C_Greeting_ID=(SELECT C_Greeting_ID FROM C_Greeting g" + + " WHERE i.BPContactGreeting=g.Name AND g.AD_Client_ID IN (0, i.AD_Client_ID)) " + + "WHERE C_Greeting_ID IS NULL AND BPContactGreeting IS NOT NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Greeting=" + no); + // + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Greeting, ' " + + "WHERE C_Greeting_ID IS NULL AND BPContactGreeting IS NOT NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Invalid Greeting=" + no); + + // Existing User ? + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET (C_BPartner_ID,AD_User_ID)=" + + "(SELECT C_BPartner_ID,AD_User_ID FROM AD_User u " + + "WHERE i.EMail=u.EMail AND u.AD_Client_ID=i.AD_Client_ID) " + + "WHERE i.EMail IS NOT NULL AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Found EMail User=" + no); + + // Existing BPartner ? Match Value + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET C_BPartner_ID=(SELECT C_BPartner_ID FROM C_BPartner p" + + " WHERE i.Value=p.Value AND p.AD_Client_ID=i.AD_Client_ID) " + + "WHERE C_BPartner_ID IS NULL AND Value IS NOT NULL" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Found BPartner=" + no); + + // Existing Contact ? Match Name + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET AD_User_ID=(SELECT AD_User_ID FROM AD_User c" + + " WHERE i.ContactName=c.Name AND i.C_BPartner_ID=c.C_BPartner_ID AND c.AD_Client_ID=i.AD_Client_ID) " + + "WHERE C_BPartner_ID IS NOT NULL AND AD_User_ID IS NULL AND ContactName IS NOT NULL" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Found Contact=" + no); + + // Existing Location ? Exact Match + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET C_BPartner_Location_ID=(SELECT C_BPartner_Location_ID" + + " FROM C_BPartner_Location bpl INNER JOIN C_Location l ON (bpl.C_Location_ID=l.C_Location_ID)" + + " WHERE i.C_BPartner_ID=bpl.C_BPartner_ID AND bpl.AD_Client_ID=i.AD_Client_ID" + + " AND DUMP(i.Address1)=DUMP(l.Address1) AND DUMP(i.Address2)=DUMP(l.Address2)" + + " AND DUMP(i.City)=DUMP(l.City) AND DUMP(i.Postal)=DUMP(l.Postal) AND DUMP(i.Postal_Add)=DUMP(l.Postal_Add)" + + " AND DUMP(i.C_Region_ID)=DUMP(l.C_Region_ID) AND DUMP(i.C_Country_ID)=DUMP(l.C_Country_ID)) " + + "WHERE C_BPartner_ID IS NOT NULL AND C_BPartner_Location_ID IS NULL" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Found Location=" + no); + + // Interest Area + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET R_InterestArea_ID=(SELECT R_InterestArea_ID FROM R_InterestArea ia " + + "WHERE i.InterestAreaName=ia.Name AND ia.AD_Client_ID=i.AD_Client_ID) " + + "WHERE R_InterestArea_ID IS NULL AND InterestAreaName IS NOT NULL" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Interest Area=" + no); + + + commit(); + // ------------------------------------------------------------------- + int noInsert = 0; + int noUpdate = 0; + + // Go through Records + sql = new StringBuffer ("SELECT * FROM I_BPartner " + + "WHERE I_IsImported='N'").append(clientCheck); + try + { + PreparedStatement pstmt = DB.prepareStatement(sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + X_I_BPartner impBP = new X_I_BPartner (getCtx(), rs, get_TrxName()); + log.fine("I_BPartner_ID=" + impBP.getI_BPartner_ID() + + ", C_BPartner_ID=" + impBP.getC_BPartner_ID() + + ", C_BPartner_Location_ID=" + impBP.getC_BPartner_Location_ID() + + ", AD_User_ID=" + impBP.getAD_User_ID()); + + + // **** Create/Update BPartner **** + MBPartner bp = null; + if (impBP.getC_BPartner_ID() == 0) // Insert new BPartner + { + bp = new MBPartner(impBP); + if (bp.save()) + { + impBP.setC_BPartner_ID(bp.getC_BPartner_ID()); + log.finest("Insert BPartner - " + bp.getC_BPartner_ID()); + noInsert++; + } + else + { + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||") + .append("'Cannot Insert BPartner, ' ") + .append("WHERE I_BPartner_ID=").append(impBP.getI_BPartner_ID()); + DB.executeUpdate(sql.toString(), get_TrxName()); + continue; + } + } + else // Update existing BPartner + { + bp = new MBPartner(getCtx(), impBP.getC_BPartner_ID(), get_TrxName()); + // if (impBP.getValue() != null) // not to overwite + // bp.setValue(impBP.getValue()); + if (impBP.getName() != null) + { + bp.setName(impBP.getName()); + bp.setName2(impBP.getName2()); + } + if (impBP.getDUNS() != null) + bp.setDUNS(impBP.getDUNS()); + if (impBP.getTaxID() != null) + bp.setTaxID(impBP.getTaxID()); + if (impBP.getNAICS() != null) + bp.setNAICS(impBP.getNAICS()); + if (impBP.getC_BP_Group_ID() != 0) + bp.setC_BP_Group_ID(impBP.getC_BP_Group_ID()); + // + if (bp.save()) + { + log.finest("Update BPartner - " + bp.getC_BPartner_ID()); + noUpdate++; + } + else + { + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||") + .append("'Cannot Update BPartner, ' ") + .append("WHERE I_BPartner_ID=").append(impBP.getI_BPartner_ID()); + DB.executeUpdate(sql.toString(), get_TrxName()); + continue; + } + } + + // **** Create/Update BPartner Location **** + MBPartnerLocation bpl = null; + if (impBP.getC_BPartner_Location_ID() != 0) // Update Location + { + bpl = new MBPartnerLocation(getCtx(), impBP.getC_BPartner_Location_ID(), get_TrxName()); + MLocation location = new MLocation(getCtx(), bpl.getC_Location_ID(), get_TrxName()); + location.setC_Country_ID(impBP.getC_Country_ID()); + location.setC_Region_ID(impBP.getC_Region_ID()); + location.setCity(impBP.getCity()); + location.setAddress1(impBP.getAddress1()); + location.setAddress2(impBP.getAddress2()); + location.setPostal(impBP.getPostal()); + location.setPostal_Add(impBP.getPostal_Add()); + if (!location.save()) + log.warning("Location not updated"); + else + bpl.setC_Location_ID(location.getC_Location_ID()); + if (impBP.getPhone() != null) + bpl.setPhone(impBP.getPhone()); + if (impBP.getPhone2() != null) + bpl.setPhone2(impBP.getPhone2()); + if (impBP.getFax() != null) + bpl.setFax(impBP.getFax()); + bpl.save(); + } + else // New Location + if (impBP.getC_Country_ID() != 0 + && impBP.getAddress1() != null + && impBP.getCity() != null) + { + MLocation location = new MLocation(getCtx(), impBP.getC_Country_ID(), + impBP.getC_Region_ID(), impBP.getCity(), get_TrxName()); + location.setAddress1(impBP.getAddress1()); + location.setAddress2(impBP.getAddress2()); + location.setPostal(impBP.getPostal()); + location.setPostal_Add(impBP.getPostal_Add()); + if (location.save()) + log.finest("Insert Location - " + location.getC_Location_ID()); + else + { + rollback(); + noInsert--; + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||") + .append("'Cannot Insert Location, ' ") + .append("WHERE I_BPartner_ID=").append(impBP.getI_BPartner_ID()); + DB.executeUpdate(sql.toString(), get_TrxName()); + continue; + } + // + bpl = new MBPartnerLocation (bp); + bpl.setC_Location_ID(location.getC_Location_ID()); + bpl.setPhone(impBP.getPhone()); + bpl.setPhone2(impBP.getPhone2()); + bpl.setFax(impBP.getFax()); + if (bpl.save()) + { + log.finest("Insert BP Location - " + bpl.getC_BPartner_Location_ID()); + impBP.setC_BPartner_Location_ID(bpl.getC_BPartner_Location_ID()); + } + else + { + rollback(); + noInsert--; + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||") + .append("'Cannot Insert BPLocation, ' ") + .append("WHERE I_BPartner_ID=").append(impBP.getI_BPartner_ID()); + DB.executeUpdate(sql.toString(), get_TrxName()); + continue; + } + } + + // **** Create/Update Contact **** + MUser user = null; + if (impBP.getAD_User_ID() != 0) + { + user = new MUser (getCtx(), impBP.getAD_User_ID(), get_TrxName()); + if (user.getC_BPartner_ID() == 0) + user.setC_BPartner_ID(bp.getC_BPartner_ID()); + else if (user.getC_BPartner_ID() != bp.getC_BPartner_ID()) + { + rollback(); + noInsert--; + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||") + .append("'BP of User <> BP, ' ") + .append("WHERE I_BPartner_ID=").append(impBP.getI_BPartner_ID()); + DB.executeUpdate(sql.toString(), get_TrxName()); + continue; + } + if (impBP.getC_Greeting_ID() != 0) + user.setC_Greeting_ID(impBP.getC_Greeting_ID()); + String name = impBP.getContactName(); + if (name == null || name.length() == 0) + name = impBP.getEMail(); + user.setName(name); + if (impBP.getTitle() != null) + user.setTitle(impBP.getTitle()); + if (impBP.getContactDescription() != null) + user.setDescription(impBP.getContactDescription()); + if (impBP.getComments() != null) + user.setComments(impBP.getComments()); + if (impBP.getPhone() != null) + user.setPhone(impBP.getPhone()); + if (impBP.getPhone2() != null) + user.setPhone(impBP.getPhone2()); + if (impBP.getFax() != null) + user.setFax(impBP.getFax()); + if (impBP.getEMail() != null) + user.setEMail(impBP.getEMail()); + if (impBP.getBirthday() != null) + user.setBirthday(impBP.getBirthday()); + if (bpl != null) + user.setC_BPartner_Location_ID(bpl.getC_BPartner_Location_ID()); + if (user.save()) + { + log.finest("Update BP Contact - " + user.getAD_User_ID()); + } + else + { + rollback(); + noInsert--; + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||") + .append("'Cannot Update BP Contact, ' ") + .append("WHERE I_BPartner_ID=").append(impBP.getI_BPartner_ID()); + DB.executeUpdate(sql.toString(), get_TrxName()); + continue; + } + } + else // New Contact + if (impBP.getContactName() != null || impBP.getEMail() != null) + { + user = new MUser (bp); + if (impBP.getC_Greeting_ID() != 0) + user.setC_Greeting_ID(impBP.getC_Greeting_ID()); + String name = impBP.getContactName(); + if (name == null || name.length() == 0) + name = impBP.getEMail(); + user.setName(name); + user.setTitle(impBP.getTitle()); + user.setDescription(impBP.getContactDescription()); + user.setComments(impBP.getComments()); + user.setPhone(impBP.getPhone()); + user.setPhone(impBP.getPhone2()); + user.setFax(impBP.getFax()); + user.setEMail(impBP.getEMail()); + user.setBirthday(impBP.getBirthday()); + if (bpl != null) + user.setC_BPartner_Location_ID(bpl.getC_BPartner_Location_ID()); + if (user.save()) + { + log.finest("Insert BP Contact - " + user.getAD_User_ID()); + impBP.setAD_User_ID(user.getAD_User_ID()); + } + else + { + rollback(); + noInsert--; + sql = new StringBuffer ("UPDATE I_BPartner i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||") + .append("'Cannot Insert BPContact, ' ") + .append("WHERE I_BPartner_ID=").append(impBP.getI_BPartner_ID()); + DB.executeUpdate(sql.toString(), get_TrxName()); + continue; + } + } + + // Interest Area + if (impBP.getR_InterestArea_ID() != 0 && user != null) + { + MContactInterest ci = MContactInterest.get(getCtx(), + impBP.getR_InterestArea_ID(), user.getAD_User_ID(), + true, get_TrxName()); + ci.save(); // don't subscribe or re-activate + } + // + impBP.setI_IsImported(true); + impBP.setProcessed(true); + impBP.setProcessing(false); + impBP.save(); + commit(); + } // for all I_Product + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "", e); + rollback(); + } + + // Set Error to indicator to not imported + sql = new StringBuffer ("UPDATE I_BPartner " + + "SET I_IsImported='N', Updated=SysDate " + + "WHERE I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog (0, null, new BigDecimal (no), "@Errors@"); + addLog (0, null, new BigDecimal (noInsert), "@C_BPartner_ID@: @Inserted@"); + addLog (0, null, new BigDecimal (noUpdate), "@C_BPartner_ID@: @Updated@"); + return ""; + } // doIt + +} // ImportBPartner diff --git a/base/src/org/compiere/process/ImportBankStatement.java b/base/src/org/compiere/process/ImportBankStatement.java new file mode 100644 index 0000000000..568f93b790 --- /dev/null +++ b/base/src/org/compiere/process/ImportBankStatement.java @@ -0,0 +1,524 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.math.*; +import java.util.*; + +//import org.compiere.process.*; +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Import Bank Statement from I_BankStatement + * + * author Eldir Tomassen + * @version $Id: ImportBankStatement.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ImportBankStatement extends SvrProcess +{ + /** Client to be imported to */ + private int p_AD_Client_ID = 0; + /** Organization to be imported to */ + private int p_AD_Org_ID = 0; + /** Default Bank Account */ + private int p_C_BankAccount_ID = 0; + /** Delete old Imported */ + private boolean p_deleteOldImported = false; + + /** Properties */ + private Properties m_ctx; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Client_ID")) + p_AD_Client_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("AD_Org_ID")) + p_AD_Org_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_BankAccount_ID")) + p_C_BankAccount_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("DeleteOldImported")) + p_deleteOldImported = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + m_ctx = Env.getCtx(); + } // prepare + + + /** + * Perform process. + * @return Message + * @throws Exception + */ + protected String doIt() throws java.lang.Exception + { + log.info("AD_Org_ID=" + p_AD_Org_ID + ", C_BankAccount_ID" + p_C_BankAccount_ID); + StringBuffer sql = null; + int no = 0; + String clientCheck = " AND AD_Client_ID=" + p_AD_Client_ID; + + // **** Prepare **** + + // Delete Old Imported + if (p_deleteOldImported) + { + sql = new StringBuffer ("DELETE I_BankStatement " + + "WHERE I_IsImported='Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Delete Old Impored =" + no); + } + + // Set Client, Org, IsActive, Created/Updated + sql = new StringBuffer ("UPDATE I_BankStatement " + + "SET AD_Client_ID = COALESCE (AD_Client_ID,").append (p_AD_Client_ID).append (")," + + " AD_Org_ID = COALESCE (AD_Org_ID,").append (p_AD_Org_ID).append ("),"); + sql.append(" IsActive = COALESCE (IsActive, 'Y')," + + " Created = COALESCE (Created, SysDate)," + + " CreatedBy = COALESCE (CreatedBy, 0)," + + " Updated = COALESCE (Updated, SysDate)," + + " UpdatedBy = COALESCE (UpdatedBy, 0)," + + " I_ErrorMsg = NULL," + + " I_IsImported = 'N' " + + "WHERE I_IsImported<>'Y' OR I_IsImported IS NULL OR AD_Client_ID IS NULL OR AD_Org_ID IS NULL OR AD_Client_ID=0 OR AD_Org_ID=0"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info ("Reset=" + no); + + sql = new StringBuffer ("UPDATE I_BankStatement o " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Org, '" + + "WHERE (AD_Org_ID IS NULL OR AD_Org_ID=0" + + " OR EXISTS (SELECT * FROM AD_Org oo WHERE o.AD_Org_ID=oo.AD_Org_ID AND (oo.IsSummary='Y' OR oo.IsActive='N')))" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Org=" + no); + + // Set Bank Account + sql = new StringBuffer("UPDATE I_BankStatement i " + + "SET C_BankAccount_ID=" + + "( " + + " SELECT C_BankAccount_ID " + + " FROM C_BankAccount a, C_Bank b " + + " WHERE b.IsOwnBank='Y' " + + " AND a.AD_Client_ID=i.AD_Client_ID " + + " AND a.C_Bank_ID=b.C_Bank_ID " + + " AND a.AccountNo=i.BankAccountNo " + + " AND b.RoutingNo=i.RoutingNo " + + " OR b.SwiftCode=i.RoutingNo " + + ") " + + "WHERE i.C_BankAccount_ID IS NULL " + + "AND i.I_IsImported<>'Y' " + + "OR i.I_IsImported IS NULL").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Bank Account (With Routing No)=" + no); + // + sql = new StringBuffer("UPDATE I_BankStatement i " + + "SET C_BankAccount_ID=" + + "( " + + " SELECT C_BankAccount_ID " + + " FROM C_BankAccount a, C_Bank b " + + " WHERE b.IsOwnBank='Y' " + + " AND a.C_Bank_ID=b.C_Bank_ID " + + " AND a.AccountNo=i.BankAccountNo " + + " AND a.AD_Client_ID=i.AD_Client_ID " + + ") " + + "WHERE i.C_BankAccount_ID IS NULL " + + "AND i.I_isImported<>'Y' " + + "OR i.I_isImported IS NULL").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Bank Account (Without Routing No)=" + no); + // + sql = new StringBuffer("UPDATE I_BankStatement i " + + "SET C_BankAccount_ID=(SELECT C_BankAccount_ID FROM C_BankAccount a WHERE a.C_BankAccount_ID=").append(p_C_BankAccount_ID); + sql.append(" and a.AD_Client_ID=i.AD_Client_ID) " + + "WHERE i.C_BankAccount_ID IS NULL " + + "AND i.BankAccountNo IS NULL " + + "AND i.I_isImported<>'Y' " + + "OR i.I_isImported IS NULL").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Bank Account=" + no); + // + sql = new StringBuffer("UPDATE I_BankStatement " + + "SET I_isImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Bank Account, ' " + + "WHERE C_BankAccount_ID IS NULL " + + "AND I_isImported<>'Y' " + + "OR I_isImported IS NULL").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning("Invalid Bank Account=" + no); + + // Set Currency + sql = new StringBuffer ("UPDATE I_BankStatement i " + + "SET C_Currency_ID=(SELECT C_Currency_ID FROM C_Currency c" + + " WHERE i.ISO_Code=c.ISO_Code AND c.AD_Client_ID IN (0,i.AD_Client_ID)) " + + "WHERE C_Currency_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Set Currency=" + no); + // + sql = new StringBuffer("UPDATE I_BankStatement i " + + "SET i.C_Currency_ID=(SELECT C_Currency_ID FROM C_BankAccount WHERE C_BankAccount_ID=i.C_BankAccount_ID) " + + "WHERE i.C_Currency_ID IS NULL " + + "AND i.ISO_Code IS NULL").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Set Currency=" + no); + // + sql = new StringBuffer ("UPDATE I_BankStatement " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Currency,' " + + "WHERE C_Currency_ID IS NULL " + + "AND I_IsImported<>'E' " + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning("Invalid Currency=" + no); + + + // Set Amount + sql = new StringBuffer("UPDATE I_BankStatement " + + "SET ChargeAmt=0 " + + "WHERE ChargeAmt IS NULL " + + "AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Charge Amount=" + no); + // + sql = new StringBuffer("UPDATE I_BankStatement " + + "SET InterestAmt=0 " + + "WHERE InterestAmt IS NULL " + + "AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Interest Amount=" + no); + // + sql = new StringBuffer("UPDATE I_BankStatement " + + "SET TrxAmt=StmtAmt - InterestAmt - ChargeAmt " + + "WHERE TrxAmt IS NULL " + + "AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Transaction Amount=" + no); + // + sql = new StringBuffer("UPDATE I_BankStatement " + + "SET I_isImported='E', I_ErrorMsg=I_ErrorMsg||'Err=Invalid Amount, ' " + + "WHERE TrxAmt + ChargeAmt + InterestAmt <> StmtAmt " + + "AND I_isImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Invaid Amount=" + no); + + // Set Valuta Date + sql = new StringBuffer("UPDATE I_BankStatement " + + "SET ValutaDate=StatementLineDate " + + "WHERE ValutaDate IS NULL " + + "AND I_isImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Valuta Date=" + no); + + // Check Payment<->Invoice combination + sql = new StringBuffer("UPDATE I_BankStatement " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'Err=Invalid Payment<->Invoice, ' " + + "WHERE I_BankStatement_ID IN " + + "(SELECT I_BankStatement_ID " + + "FROM I_BankStatement i" + + " INNER JOIN C_Payment p ON (i.C_Payment_ID=p.C_Payment_ID) " + + "WHERE i.C_Invoice_ID IS NOT NULL " + + " AND p.C_Invoice_ID IS NOT NULL " + + " AND p.C_Invoice_ID<>i.C_Invoice_ID) ") + .append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Payment<->Invoice Mismatch=" + no); + + // Check Payment<->BPartner combination + sql = new StringBuffer("UPDATE I_BankStatement " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'Err=Invalid Payment<->BPartner, ' " + + "WHERE I_BankStatement_ID IN " + + "(SELECT I_BankStatement_ID " + + "FROM I_BankStatement i" + + " INNER JOIN C_Payment p ON (i.C_Payment_ID=p.C_Payment_ID) " + + "WHERE i.C_BPartner_ID IS NOT NULL " + + " AND p.C_BPartner_ID IS NOT NULL " + + " AND p.C_BPartner_ID<>i.C_BPartner_ID) ") + .append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Payment<->BPartner Mismatch=" + no); + + // Check Invoice<->BPartner combination + sql = new StringBuffer("UPDATE I_BankStatement " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'Err=Invalid Invoice<->BPartner, ' " + + "WHERE I_BankStatement_ID IN " + + "(SELECT I_BankStatement_ID " + + "FROM I_BankStatement i" + + " INNER JOIN C_Invoice v ON (i.C_Invoice_ID=v.C_Invoice_ID) " + + "WHERE i.C_BPartner_ID IS NOT NULL " + + " AND v.C_BPartner_ID IS NOT NULL " + + " AND v.C_BPartner_ID<>i.C_BPartner_ID) ") + .append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Invoice<->BPartner Mismatch=" + no); + + // Check Invoice.BPartner<->Payment.BPartner combination + sql = new StringBuffer("UPDATE I_BankStatement " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'Err=Invalid Invoice.BPartner<->Payment.BPartner, ' " + + "WHERE I_BankStatement_ID IN " + + "(SELECT I_BankStatement_ID " + + "FROM I_BankStatement i" + + " INNER JOIN C_Invoice v ON (i.C_Invoice_ID=v.C_Invoice_ID)" + + " INNER JOIN C_Payment p ON (i.C_Payment_ID=p.C_Payment_ID) " + + "WHERE p.C_Invoice_ID<>v.C_Invoice_ID" + + " AND v.C_BPartner_ID<>p.C_BPartner_ID) ") + .append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Invoice.BPartner<->Payment.BPartner Mismatch=" + no); + + // Detect Duplicates + sql = new StringBuffer("SELECT i.I_BankStatement_ID, l.C_BankStatementLine_ID, i.EftTrxID " + + "FROM I_BankStatement i, C_BankStatement s, C_BankStatementLine l " + + "WHERE i.I_isImported='N' " + + "AND s.C_BankStatement_ID=l.C_BankStatement_ID " + + "AND i.EftTrxID IS NOT NULL AND " + // Concatinate EFT Info + + "(l.EftTrxID||l.EftAmt||l.EftStatementLineDate||l.EftValutaDate||l.EftTrxType||l.EftCurrency||l.EftReference||s.EftStatementReference " + + "||l.EftCheckNo||l.EftMemo||l.EftPayee||l.EftPayeeAccount) " + + "= " + + "(i.EftTrxID||i.EftAmt||i.EftStatementLineDate||i.EftValutaDate||i.EftTrxType||i.EftCurrency||i.EftReference||i.EftStatementReference " + + "||i.EftCheckNo||i.EftMemo||i.EftPayee||i.EftPayeeAccount) "); + + StringBuffer updateSql = new StringBuffer("UPDATE I_Bankstatement " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'Err=Duplicate['||?||']' " + + "WHERE I_BankStatement_ID=?").append(clientCheck); + PreparedStatement pupdt = DB.prepareStatement(updateSql.toString(), get_TrxName()); + + PreparedStatement pstmtDuplicates = null; + no = 0; + try + { + pstmtDuplicates = DB.prepareStatement(sql.toString(), get_TrxName()); + ResultSet rs = pstmtDuplicates.executeQuery(); + while (rs.next()) + { + String info = "Line_ID=" + rs.getInt(2) // l.C_BankStatementLine_ID + + ",EDTTrxID=" + rs.getString(3); // i.EftTrxID + pupdt.setString(1, info); + pupdt.setInt(2, rs.getInt(1)); // i.I_BankStatement_ID + pupdt.executeUpdate(); + no++; + } + rs.close(); + pstmtDuplicates.close(); + pupdt.close(); + + rs = null; + pstmtDuplicates = null; + pupdt = null; + } + catch(Exception e) + { + log.log(Level.SEVERE, "DetectDuplicates " + e.getMessage()); + } + if (no != 0) + log.info("Duplicates=" + no); + + commit(); + + //Import Bank Statement + sql = new StringBuffer("SELECT * FROM I_BankStatement" + + " WHERE I_IsImported='N'" + + " ORDER BY C_BankAccount_ID, Name, EftStatementDate, EftStatementReference"); + + MBankStatement statement = null; + MBankAccount account = null; + PreparedStatement pstmt = null; + int lineNo = 10; + int noInsert = 0; + int noInsertLine = 0; + try + { + pstmt = DB.prepareStatement(sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + + while (rs.next()) + { + X_I_BankStatement imp = new X_I_BankStatement(m_ctx, rs, get_TrxName()); + // Get the bank account for the first statement + if (account == null) + { + account = MBankAccount.get (m_ctx, imp.getC_BankAccount_ID()); + statement = null; + log.info("New Statement, Account=" + account.getAccountNo()); + } + // Create a new Bank Statement for every account + else if (account.getC_BankAccount_ID() != imp.getC_BankAccount_ID()) + { + account = MBankAccount.get (m_ctx, imp.getC_BankAccount_ID()); + statement = null; + log.info("New Statement, Account=" + account.getAccountNo()); + } + // Create a new Bank Statement for every statement name + else if ((statement.getName() != null) && (imp.getName() != null)) + { + if (!statement.getName().equals(imp.getName())) + { + statement = null; + log.info("New Statement, Statement Name=" + imp.getName()); + } + } + // Create a new Bank Statement for every statement reference + else if ((statement.getEftStatementReference() != null) && (imp.getEftStatementReference() != null)) + { + if (!statement.getEftStatementReference().equals(imp.getEftStatementReference())) + { + statement = null; + log.info("New Statement, Statement Reference=" + imp.getEftStatementReference()); + } + } + // Create a new Bank Statement for every statement date + else if ((statement.getStatementDate() != null) && (imp.getStatementDate() != null)) + { + if (!statement.getStatementDate().equals(imp.getStatementDate())) + { + statement = null; + log.info("New Statement, Statement Date=" + imp.getStatementDate()); + } + } + + // New Statement + if (statement == null) + { + statement = new MBankStatement(account); + statement.setEndingBalance(Env.ZERO); + + // Copy statement data + if (imp.getName() != null) + { + statement.setName(imp.getName()); + } + if (imp.getStatementDate() != null) + { + statement.setStatementDate(imp.getStatementDate()); + } + statement.setDescription(imp.getDescription()); + statement.setEftStatementReference(imp.getEftStatementReference()); + statement.setEftStatementDate(imp.getEftStatementDate()); + if (statement.save()) + { + noInsert++; + } + lineNo = 10; + } + + // New StatementLine + MBankStatementLine line = new MBankStatementLine(statement, lineNo); + + // Copy statement line data + //line.setC_BPartner_ID(imp.getC_BPartner_ID()); + //line.setC_Invoice_ID(imp.getC_Invoice_ID()); + line.setReferenceNo(imp.getReferenceNo()); + line.setDescription(imp.getLineDescription()); + line.setStatementLineDate(imp.getStatementLineDate()); + line.setDateAcct(imp.getStatementLineDate()); + line.setValutaDate(imp.getValutaDate()); + line.setIsReversal(imp.isReversal()); + line.setC_Currency_ID(imp.getC_Currency_ID()); + line.setTrxAmt(imp.getTrxAmt()); + line.setStmtAmt(imp.getStmtAmt()); + if (imp.getC_Charge_ID() != 0) + { + line.setC_Charge_ID(imp.getC_Charge_ID()); + } + line.setInterestAmt(imp.getInterestAmt()); + line.setChargeAmt(imp.getChargeAmt()); + line.setMemo(imp.getMemo()); + if (imp.getC_Payment_ID() != 0) + { + line.setC_Payment_ID(imp.getC_Payment_ID()); + } + + // Copy statement line reference data + line.setEftTrxID(imp.getEftTrxID()); + line.setEftTrxType(imp.getEftTrxType()); + line.setEftCheckNo(imp.getEftCheckNo()); + line.setEftReference(imp.getEftReference()); + line.setEftMemo(imp.getEftMemo()); + line.setEftPayee(imp.getEftPayee()); + line.setEftPayeeAccount(imp.getEftPayeeAccount()); + line.setEftStatementLineDate(imp.getEftStatementLineDate()); + line.setEftValutaDate(imp.getEftValutaDate()); + line.setEftCurrency(imp.getEftCurrency()); + line.setEftAmt(imp.getEftAmt()); + + // Save statement line + if (line.save()) + { + imp.setC_BankStatement_ID(statement.getC_BankStatement_ID()); + imp.setC_BankStatementLine_ID(line.getC_BankStatementLine_ID()); + imp.setI_IsImported(true); + imp.setProcessed(true); + imp.save(); + noInsertLine++; + lineNo += 10; + } + line = null; + + } + + // Close database connection + rs.close(); + pstmt.close(); + rs = null; + pstmt = null; + + } + catch(Exception e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + + // Set Error to indicator to not imported + sql = new StringBuffer ("UPDATE I_BankStatement " + + "SET I_IsImported='N', Updated=SysDate " + + "WHERE I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog (0, null, new BigDecimal (no), "@Errors@"); + // + addLog (0, null, new BigDecimal (noInsert), "@C_BankStatement_ID@: @Inserted@"); + addLog (0, null, new BigDecimal (noInsertLine), "@C_BankStatementLine_ID@: @Inserted@"); + return ""; + + } // doIt + +} // ImportBankStatement diff --git a/base/src/org/compiere/process/ImportConversionRate.java b/base/src/org/compiere/process/ImportConversionRate.java new file mode 100644 index 0000000000..9f83d35212 --- /dev/null +++ b/base/src/org/compiere/process/ImportConversionRate.java @@ -0,0 +1,299 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Import Currency Conversion Rates + * + * @author Jorg Janke + * @version $Id: ImportConversionRate.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ImportConversionRate extends SvrProcess +{ + + /** Client to be imported to */ + private int p_AD_Client_ID = 0; + /** Organization to be imported to */ + private int p_AD_Org_ID = 0; + /** Conversion Type to be imported to */ + private int p_C_ConversionType_ID = 0; + /** Default Date */ + private Timestamp p_ValidFrom = null; + /** Default Reciprocal */ + private boolean p_CreateReciprocalRate = false; + /** Delete old Imported */ + private boolean p_DeleteOldImported = false; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Client_ID")) + p_AD_Client_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("AD_Org_ID")) + p_AD_Org_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_ConversionType_ID")) + p_C_ConversionType_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("ValidFrom")) + p_ValidFrom = (Timestamp)para[i].getParameter(); + else if (name.equals("CreateReciprocalRate")) + p_CreateReciprocalRate = "Y".equals(para[i].getParameter()); + else if (name.equals("DeleteOldImported")) + p_DeleteOldImported = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + + /** + * Perrform process. + * @return Message + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info("doIt - AD_Client_ID=" + p_AD_Client_ID + + ",AD_Org_ID=" + p_AD_Org_ID + + ",C_ConversionType_ID=" + p_C_ConversionType_ID + + ",ValidFrom=" + p_ValidFrom + + ",CreateReciprocalRate=" + p_CreateReciprocalRate); + // + StringBuffer sql = null; + int no = 0; + String clientCheck = " AND AD_Client_ID=" + p_AD_Client_ID; + // **** Prepare **** + + // Delete Old Imported + if (p_DeleteOldImported) + { + sql = new StringBuffer ("DELETE I_Conversion_Rate " + + "WHERE I_IsImported='Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Delete Old Impored =" + no); + } + + // Set Client, Org, Location, IsActive, Created/Updated + sql = new StringBuffer ("UPDATE I_Conversion_Rate " + + "SET AD_Client_ID = COALESCE (AD_Client_ID,").append (p_AD_Client_ID).append (")," + + " AD_Org_ID = COALESCE (AD_Org_ID,").append (p_AD_Org_ID).append ("),"); + if (p_C_ConversionType_ID != 0) + sql.append(" C_ConversionType_ID = COALESCE (C_ConversionType_ID,").append (p_C_ConversionType_ID).append ("),"); + if (p_ValidFrom != null) + sql.append(" ValidFrom = COALESCE (ValidFrom,").append (DB.TO_DATE(p_ValidFrom)).append ("),"); + else + sql.append(" ValidFrom = COALESCE (ValidFrom,SysDate),"); + sql.append(" CreateReciprocalRate = COALESCE (CreateReciprocalRate,'").append (p_CreateReciprocalRate ? "Y" : "N").append ("')," + + " IsActive = COALESCE (IsActive, 'Y')," + + " Created = COALESCE (Created, SysDate)," + + " CreatedBy = COALESCE (CreatedBy, 0)," + + " Updated = COALESCE (Updated, SysDate)," + + " UpdatedBy = ").append(getAD_User_ID()).append("," + + " I_ErrorMsg = NULL," + + " Processed = 'N'," + + " I_IsImported = 'N' " + + "WHERE I_IsImported<>'Y' OR I_IsImported IS NULL"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info ("Reset =" + no); + + // Org + sql = new StringBuffer ("UPDATE I_Conversion_Rate o " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Org, '" + + "WHERE (AD_Org_ID IS NULL" + + " OR EXISTS (SELECT * FROM AD_Org oo WHERE o.AD_Org_ID=oo.AD_Org_ID AND (oo.IsSummary='Y' OR oo.IsActive='N')))" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Org =" + no); + + // Conversion Type + sql = new StringBuffer ("UPDATE I_Conversion_Rate i " + + "SET C_ConversionType_ID = (SELECT C_ConversionType_ID FROM C_ConversionType c" + + " WHERE c.Value=i.ConversionTypeValue AND c.AD_Client_ID IN (0,i.AD_Client_ID) AND c.IsActive='Y') " + + "WHERE C_ConversionType_ID IS NULL AND ConversionTypeValue IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no > 0) + log.fine("Set ConversionType =" + no); + sql = new StringBuffer ("UPDATE I_Conversion_Rate i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid ConversionType, ' " + + "WHERE (C_ConversionType_ID IS NULL" + + " OR NOT EXISTS (SELECT * FROM C_ConversionType c " + + "WHERE i.C_ConversionType_ID=c.C_ConversionType_ID AND c.IsActive='Y'" + + " AND c.AD_Client_ID IN (0,i.AD_Client_ID)))" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid ConversionType =" + no); + + // Currency + sql = new StringBuffer ("UPDATE I_Conversion_Rate i " + + "SET C_Currency_ID = (SELECT C_Currency_ID FROM C_Currency c" + + " WHERE c.ISO_Code=i.ISO_Code AND c.AD_Client_ID IN (0,i.AD_Client_ID) AND c.IsActive='Y') " + + "WHERE C_Currency_ID IS NULL AND ISO_Code IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no > 0) + log.fine("Set Currency =" + no); + sql = new StringBuffer ("UPDATE I_Conversion_Rate i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Currency, ' " + + "WHERE (C_Currency_ID IS NULL" + + " OR NOT EXISTS (SELECT * FROM C_Currency c " + + "WHERE i.C_Currency_ID=c.C_Currency_ID AND c.IsActive='Y'" + + " AND c.AD_Client_ID IN (0,i.AD_Client_ID)))" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Currency =" + no); + + // Currency To + sql = new StringBuffer ("UPDATE I_Conversion_Rate i " + + "SET C_Currency_ID_To = (SELECT C_Currency_ID FROM C_Currency c" + + " WHERE c.ISO_Code=i.ISO_Code_To AND c.AD_Client_ID IN (0,i.AD_Client_ID) AND c.IsActive='Y') " + + "WHERE C_Currency_ID_To IS NULL AND ISO_Code_To IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no > 0) + log.fine("Set Currency To =" + no); + sql = new StringBuffer ("UPDATE I_Conversion_Rate i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Currency To, ' " + + "WHERE (C_Currency_ID_To IS NULL" + + " OR NOT EXISTS (SELECT * FROM C_Currency c " + + "WHERE i.C_Currency_ID_To=c.C_Currency_ID AND c.IsActive='Y'" + + " AND c.AD_Client_ID IN (0,i.AD_Client_ID)))" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Currency To =" + no); + + // Rates + sql = new StringBuffer ("UPDATE I_Conversion_Rate i " + + "SET MultiplyRate = 1 / DivideRate " + + "WHERE (MultiplyRate IS NULL OR MultiplyRate = 0) AND DivideRate IS NOT NULL AND DivideRate<>0" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no > 0) + log.fine("Set MultiplyRate =" + no); + sql = new StringBuffer ("UPDATE I_Conversion_Rate i " + + "SET DivideRate = 1 / MultiplyRate " + + "WHERE (DivideRate IS NULL OR DivideRate = 0) AND MultiplyRate IS NOT NULL AND MultiplyRate<>0" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no > 0) + log.fine("Set DivideRate =" + no); + sql = new StringBuffer ("UPDATE I_Conversion_Rate i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Rates, ' " + + "WHERE (MultiplyRate IS NULL OR MultiplyRate = 0 OR DivideRate IS NULL OR DivideRate = 0)" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Rates =" + no); + // sql = new StringBuffer ("UPDATE I_Conversion_Rate i " // Rate diff > 10% + // + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Inconsistent Rates='||(MultiplyRate - (1/DivideRate)) " + // + "WHERE ((MultiplyRate - (1/DivideRate)) > (MultiplyRate * .1))" + // + " AND I_IsImported<>'Y'").append (clientCheck); + // no = DB.executeUpdate(sql.toString(), get_TrxName()); + // if (no != 0) + // log.warn ("Inconsistent Rates =" + no); + + commit(); + /*********************************************************************/ + + int noInsert = 0; + sql = new StringBuffer ("SELECT * FROM I_Conversion_Rate " + + "WHERE I_IsImported='N'").append (clientCheck) + .append(" ORDER BY C_Currency_ID, C_Currency_ID_To, ValidFrom"); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + X_I_Conversion_Rate imp = new X_I_Conversion_Rate (getCtx(), rs, get_TrxName()); + MConversionRate rate = new MConversionRate (imp, + imp.getC_ConversionType_ID(), + imp.getC_Currency_ID(), imp.getC_Currency_ID_To(), + imp.getMultiplyRate(), imp.getValidFrom()); + if (imp.getValidTo() != null) + rate.setValidTo(imp.getValidTo()); + if (rate.save()) + { + imp.setC_Conversion_Rate_ID(rate.getC_Conversion_Rate_ID()); + imp.setI_IsImported(true); + imp.setProcessed(true); + imp.save(); + noInsert++; + // + if (imp.isCreateReciprocalRate()) + { + rate = new MConversionRate (imp, + imp.getC_ConversionType_ID(), + imp.getC_Currency_ID_To(), imp.getC_Currency_ID(), + imp.getDivideRate(), imp.getValidFrom()); + if (imp.getValidTo() != null) + rate.setValidTo(imp.getValidTo()); + if (rate.save()) + noInsert++; + } + } + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + // Set Error to indicator to not imported + sql = new StringBuffer ("UPDATE I_Conversion_Rate " + + "SET I_IsImported='N', Updated=SysDate " + + "WHERE I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog (0, null, new BigDecimal (no), "@Errors@"); + // + addLog (0, null, new BigDecimal (noInsert), "@C_Conversion_Rate_ID@: @Inserted@"); + return ""; + } // doIt + +} // ImportConversionRate diff --git a/base/src/org/compiere/process/ImportDelete.java b/base/src/org/compiere/process/ImportDelete.java new file mode 100644 index 0000000000..239e8fb40e --- /dev/null +++ b/base/src/org/compiere/process/ImportDelete.java @@ -0,0 +1,76 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Delete Data in Import Table + * + * @author Jorg Janke + * @version $Id: ImportDelete.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ImportDelete extends SvrProcess +{ + /** Table be deleted */ + private int p_AD_Table_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (name.equals("AD_Table_ID")) + p_AD_Table_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + + /** + * Perrform process. + * @return clear Message + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info("AD_Table_ID=" + p_AD_Table_ID); + // get Table Info + MTable table = new MTable (getCtx(), p_AD_Table_ID, get_TrxName()); + if (table.get_ID() == 0) + throw new IllegalArgumentException ("No AD_Table_ID=" + p_AD_Table_ID); + String tableName = table.getTableName(); + if (!tableName.startsWith("I")) + throw new IllegalArgumentException ("Not an import table = " + tableName); + + // Delete + String sql = "DELETE FROM " + tableName + " WHERE AD_Client_ID=" + getAD_Client_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + String msg = Msg.translate(getCtx(), tableName + "_ID") + " #" + no; + return msg; + } // ImportDelete + +} // ImportDelete diff --git a/base/src/org/compiere/process/ImportGLJournal.java b/base/src/org/compiere/process/ImportGLJournal.java new file mode 100644 index 0000000000..4ed7f64a79 --- /dev/null +++ b/base/src/org/compiere/process/ImportGLJournal.java @@ -0,0 +1,778 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + * Contributor: Carlos Ruiz - globalqss * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Import GL Journal Batch/JournalLine from I_Journal + * + * @author Jorg Janke + * @version $Id: ImportGLJournal.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class ImportGLJournal extends SvrProcess +{ + /** Client to be imported to */ + private int m_AD_Client_ID = 0; + /** Organization to be imported to */ + private int m_AD_Org_ID = 0; + /** Acct Schema to be imported to */ + private int m_C_AcctSchema_ID = 0; + /** Default Date */ + private Timestamp m_DateAcct = null; + /** Delete old Imported */ + private boolean m_DeleteOldImported = false; + /** Don't import */ + private boolean m_IsValidateOnly = false; + /** Import if no Errors */ + private boolean m_IsImportOnlyNoErrors = true; + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Client_ID")) + m_AD_Client_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("AD_Org_ID")) + m_AD_Org_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_AcctSchema_ID")) + m_C_AcctSchema_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("DateAcct")) + m_DateAcct = (Timestamp)para[i].getParameter(); + else if (name.equals("IsValidateOnly")) + m_IsValidateOnly = "Y".equals(para[i].getParameter()); + else if (name.equals("IsImportOnlyNoErrors")) + m_IsImportOnlyNoErrors = "Y".equals(para[i].getParameter()); + else if (name.equals("DeleteOldImported")) + m_DeleteOldImported = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + + /** + * Perrform process. + * @return Message + * @throws Exception + */ + protected String doIt() throws java.lang.Exception + { + log.info("IsValidateOnly=" + m_IsValidateOnly + ", IsImportOnlyNoErrors=" + m_IsImportOnlyNoErrors); + StringBuffer sql = null; + int no = 0; + String clientCheck = " AND AD_Client_ID=" + m_AD_Client_ID; + + // **** Prepare **** + + // Delete Old Imported + if (m_DeleteOldImported) + { + sql = new StringBuffer ("DELETE I_GLJournal " + + "WHERE I_IsImported='Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Delete Old Impored =" + no); + } + + // Set IsActive, Created/Updated + sql = new StringBuffer ("UPDATE I_GLJournal " + + "SET IsActive = COALESCE (IsActive, 'Y')," + + " Created = COALESCE (Created, SysDate)," + + " CreatedBy = COALESCE (CreatedBy, 0)," + + " Updated = COALESCE (Updated, SysDate)," + + " UpdatedBy = COALESCE (UpdatedBy, 0)," + + " I_ErrorMsg = NULL," + + " I_IsImported = 'N' " + + "WHERE I_IsImported<>'Y' OR I_IsImported IS NULL"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info ("Reset=" + no); + + // Set Client from Name + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET AD_Client_ID=(SELECT c.AD_Client_ID FROM AD_Client c WHERE c.Value=i.ClientValue) " + + "WHERE (AD_Client_ID IS NULL OR AD_Client_ID=0) AND ClientValue IS NOT NULL" + + " AND I_IsImported<>'Y'"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Client from Value=" + no); + + // Set Default Client, Doc Org, AcctSchema, DatAcct + sql = new StringBuffer ("UPDATE I_GLJournal " + + "SET AD_Client_ID = COALESCE (AD_Client_ID,").append (m_AD_Client_ID).append (")," + + " AD_OrgDoc_ID = COALESCE (AD_OrgDoc_ID,").append (m_AD_Org_ID).append ("),"); + if (m_C_AcctSchema_ID != 0) + sql.append(" C_AcctSchema_ID = COALESCE (C_AcctSchema_ID,").append (m_C_AcctSchema_ID).append ("),"); + if (m_DateAcct != null) + sql.append(" DateAcct = COALESCE (DateAcct,").append (DB.TO_DATE(m_DateAcct)).append ("),"); + sql.append(" Updated = COALESCE (Updated, SysDate) " + + "WHERE I_IsImported<>'Y' OR I_IsImported IS NULL"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Client/DocOrg/Default=" + no); + + // Error Doc Org + sql = new StringBuffer ("UPDATE I_GLJournal o " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Doc Org, '" + + "WHERE (AD_OrgDoc_ID IS NULL OR AD_OrgDoc_ID=0" + + " OR EXISTS (SELECT * FROM AD_Org oo WHERE o.AD_Org_ID=oo.AD_Org_ID AND (oo.IsSummary='Y' OR oo.IsActive='N')))" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Doc Org=" + no); + + // Set AcctSchema + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET C_AcctSchema_ID=(SELECT a.C_AcctSchema_ID FROM C_AcctSchema a" + + " WHERE i.AcctSchemaName=a.Name AND i.AD_Client_ID=a.AD_Client_ID) " + + "WHERE C_AcctSchema_ID IS NULL AND AcctSchemaName IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set AcctSchema from Name=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET C_AcctSchema_ID=(SELECT c.C_AcctSchema1_ID FROM AD_ClientInfo c WHERE c.AD_Client_ID=i.AD_Client_ID) " + + "WHERE C_AcctSchema_ID IS NULL AND AcctSchemaName IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set AcctSchema from Client=" + no); + // Error AcctSchema + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid AcctSchema, '" + + "WHERE (C_AcctSchema_ID IS NULL OR C_AcctSchema_ID=0" + + " OR NOT EXISTS (SELECT * FROM C_AcctSchema a WHERE i.AD_Client_ID=a.AD_Client_ID))" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid AcctSchema=" + no); + + // Set DateAcct (mandatory) + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET DateAcct=SysDate " + + "WHERE DateAcct IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set DateAcct=" + no); + + // Document Type + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET C_DocType_ID=(SELECT d.C_DocType_ID FROM C_DocType d" + + " WHERE d.Name=i.DocTypeName AND d.DocBaseType='GLJ' AND i.AD_Client_ID=d.AD_Client_ID) " + + "WHERE C_DocType_ID IS NULL AND DocTypeName IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set DocType=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid DocType, '" + + "WHERE (C_DocType_ID IS NULL OR C_DocType_ID=0" + + " OR NOT EXISTS (SELECT * FROM C_DocType d WHERE i.AD_Client_ID=d.AD_Client_ID AND d.DocBaseType='GLJ'))" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid DocType=" + no); + + // GL Category + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET GL_Category_ID=(SELECT c.GL_Category_ID FROM GL_Category c" + + " WHERE c.Name=i.CategoryName AND i.AD_Client_ID=c.AD_Client_ID) " + + "WHERE GL_Category_ID IS NULL AND CategoryName IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set DocType=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Category, '" + + "WHERE (GL_Category_ID IS NULL OR GL_Category_ID=0)" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Category=" + no); + + // Set Currency + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET C_Currency_ID=(SELECT c.C_Currency_ID FROM C_Currency c" + + " WHERE c.ISO_Code=i.ISO_Code AND c.AD_Client_ID IN (0,i.AD_Client_ID)) " + + "WHERE C_Currency_ID IS NULL AND ISO_Code IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Currency from ISO=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET C_Currency_ID=(SELECT a.C_Currency_ID FROM C_AcctSchema a" + + " WHERE a.C_AcctSchema_ID=i.C_AcctSchema_ID AND a.AD_Client_ID=i.AD_Client_ID)" + + "WHERE C_Currency_ID IS NULL AND ISO_Code IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Default Currency=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Currency, '" + + "WHERE (C_Currency_ID IS NULL OR C_Currency_ID=0)" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Currency=" + no); + + // Set Conversion Type + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET ConversionTypeValue='S' " + + "WHERE C_ConversionType_ID IS NULL AND ConversionTypeValue IS NULL" + + " AND I_IsImported='N'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set CurrencyType Value to Spot =" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET C_ConversionType_ID=(SELECT c.C_ConversionType_ID FROM C_ConversionType c" + + " WHERE c.Value=i.ConversionTypeValue AND c.AD_Client_ID IN (0,i.AD_Client_ID)) " + + "WHERE C_ConversionType_ID IS NULL AND ConversionTypeValue IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set CurrencyType from Value=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid CurrencyType, '" + + "WHERE (C_ConversionType_ID IS NULL OR C_ConversionType_ID=0) AND ConversionTypeValue IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid CurrencyTypeValue=" + no); + + + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No ConversionType, '" + + "WHERE (C_ConversionType_ID IS NULL OR C_ConversionType_ID=0)" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("No CourrencyType=" + no); + + // Set/Overwrite Home Currency Rate + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET CurrencyRate=1" + + "WHERE EXISTS (SELECT * FROM C_AcctSchema a" + + " WHERE a.C_AcctSchema_ID=i.C_AcctSchema_ID AND a.C_Currency_ID=i.C_Currency_ID)" + + " AND C_Currency_ID IS NOT NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Home CurrencyRate=" + no); + // Set Currency Rate + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET CurrencyRate=(SELECT r.MultiplyRate FROM C_Conversion_Rate r, C_AcctSchema s" + + " WHERE s.C_AcctSchema_ID=i.C_AcctSchema_ID AND s.AD_Client_ID=i.AD_Client_ID" + + " AND r.C_Currency_ID=i.C_Currency_ID AND r.C_Currency_ID_TO=s.C_Currency_ID" + + " AND r.AD_Client_ID=i.AD_Client_ID AND r.AD_Org_ID=i.AD_OrgDoc_ID" + + " AND r.C_ConversionType_ID=i.C_ConversionType_ID" + + " AND i.DateAcct BETWEEN r.ValidFrom AND r.ValidTo AND ROWNUM=1" + // ORDER BY ValidFrom DESC + + ") WHERE CurrencyRate IS NULL OR CurrencyRate=0 AND C_Currency_ID>0" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Org Rate=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET CurrencyRate=(SELECT r.MultiplyRate FROM C_Conversion_Rate r, C_AcctSchema s" + + " WHERE s.C_AcctSchema_ID=i.C_AcctSchema_ID AND s.AD_Client_ID=i.AD_Client_ID" + + " AND r.C_Currency_ID=i.C_Currency_ID AND r.C_Currency_ID_TO=s.C_Currency_ID" + + " AND r.AD_Client_ID=i.AD_Client_ID" + + " AND r.C_ConversionType_ID=i.C_ConversionType_ID" + + " AND i.DateAcct BETWEEN r.ValidFrom AND r.ValidTo AND ROWNUM=1" + // ORDER BY ValidFrom DESC + + ") WHERE CurrencyRate IS NULL OR CurrencyRate=0 AND C_Currency_ID>0" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Client Rate=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No Rate, '" + + "WHERE CurrencyRate IS NULL OR CurrencyRate=0" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("No Rate=" + no); + + // Set Period + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET C_Period_ID=(SELECT p.C_Period_ID FROM C_Period p" + + " INNER JOIN C_Year y ON (y.C_Year_ID=p.C_Year_ID)" + + " INNER JOIN AD_ClientInfo c ON (c.C_Calendar_ID=y.C_Calendar_ID)" + + " WHERE c.AD_Client_ID=i.AD_Client_ID" + // globalqss - cruiz - Bug [ 1577712 ] Financial Period Bug + + " AND i.DateAcct BETWEEN p.StartDate AND p.EndDate AND p.IsActive='Y' AND p.PeriodType='S' AND ROWNUM=1) " + + "WHERE C_Period_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Period=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Period, '" + + "WHERE C_Period_ID IS NULL OR C_Period_ID<>" + + "(SELECT C_Period_ID FROM C_Period p" + + " INNER JOIN C_Year y ON (y.C_Year_ID=p.C_Year_ID)" + + " INNER JOIN AD_ClientInfo c ON (c.C_Calendar_ID=y.C_Calendar_ID) " + + " WHERE c.AD_Client_ID=i.AD_Client_ID" + // globalqss - cruiz - Bug [ 1577712 ] Financial Period Bug + + " AND i.DateAcct BETWEEN p.StartDate AND p.EndDate AND p.IsActive='Y' AND p.PeriodType='S' AND ROWNUM=1)" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Period=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_ErrorMsg=I_ErrorMsg||'WARN=Period Closed, ' " + + "WHERE C_Period_ID IS NOT NULL AND NOT EXISTS" + + " (SELECT * FROM C_PeriodControl pc WHERE pc.C_Period_ID=i.C_Period_ID AND DocBaseType='GLJ' AND PeriodStatus='O') " + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Period Closed=" + no); + + // Posting Type + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET PostingType='A' " + + "WHERE PostingType IS NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Actual PostingType=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid PostingType, ' " + + "WHERE PostingType IS NULL OR NOT EXISTS" + + " (SELECT * FROM AD_Ref_List r WHERE r.AD_Reference_ID=125 AND i.PostingType=r.Value)" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid PostingTypee=" + no); + + + // ** Account Elements (optional) ** + // (C_ValidCombination_ID IS NULL OR C_ValidCombination_ID=0) + + // Set Org from Name (* is overwritten and default) + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET AD_Org_ID=(SELECT o.AD_Org_ID FROM AD_Org o" + + " WHERE o.Value=i.OrgValue AND o.IsSummary='N' AND i.AD_Client_ID=o.AD_Client_ID) " + + "WHERE (AD_Org_ID IS NULL OR AD_Org_ID=0) AND OrgValue IS NOT NULL" + + " AND (C_ValidCombination_ID IS NULL OR C_ValidCombination_ID=0) AND I_IsImported<>'Y'"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Org from Value=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET AD_Org_ID=AD_OrgDoc_ID " + + "WHERE (AD_Org_ID IS NULL OR AD_Org_ID=0) AND OrgValue IS NULL AND AD_OrgDoc_ID IS NOT NULL AND AD_OrgDoc_ID<>0" + + " AND (C_ValidCombination_ID IS NULL OR C_ValidCombination_ID=0) AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Org from Doc Org=" + no); + // Error Org + sql = new StringBuffer ("UPDATE I_GLJournal o " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Org, '" + + "WHERE (AD_Org_ID IS NULL OR AD_Org_ID=0" + + " OR EXISTS (SELECT * FROM AD_Org oo WHERE o.AD_Org_ID=oo.AD_Org_ID AND (oo.IsSummary='Y' OR oo.IsActive='N')))" + + " AND (C_ValidCombination_ID IS NULL OR C_ValidCombination_ID=0) AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Org=" + no); + + // Set Account + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET Account_ID=(SELECT ev.C_ElementValue_ID FROM C_ElementValue ev" + + " INNER JOIN C_Element e ON (e.C_Element_ID=ev.C_Element_ID)" + + " INNER JOIN C_AcctSchema_Element ase ON (e.C_Element_ID=ase.C_Element_ID AND ase.ElementType='AC')" + + " WHERE ev.Value=i.AccountValue AND ev.IsSummary='N'" + + " AND i.C_AcctSchema_ID=ase.C_AcctSchema_ID AND i.AD_Client_ID=ev.AD_Client_ID AND ROWNUM=1) " + + "WHERE Account_ID IS NULL AND AccountValue IS NOT NULL" + + " AND (C_ValidCombination_ID IS NULL OR C_ValidCombination_ID=0) AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Account from Value=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Account, '" + + "WHERE (Account_ID IS NULL OR Account_ID=0)" + + " AND (C_ValidCombination_ID IS NULL OR C_ValidCombination_ID=0) AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Account=" + no); + + // Set BPartner + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET C_BPartner_ID=(SELECT bp.C_BPartner_ID FROM C_BPartner bp" + + " WHERE bp.Value=i.BPartnerValue AND bp.IsSummary='N' AND i.AD_Client_ID=bp.AD_Client_ID) " + + "WHERE C_BPartner_ID IS NULL AND BPartnerValue IS NOT NULL" + + " AND (C_ValidCombination_ID IS NULL OR C_ValidCombination_ID=0) AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set BPartner from Value=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid BPartner, '" + + "WHERE C_BPartner_ID IS NULL AND BPartnerValue IS NOT NULL" + + " AND (C_ValidCombination_ID IS NULL OR C_ValidCombination_ID=0) AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid BPartner=" + no); + + // Set Product + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET M_Product_ID=(SELECT p.M_Product_ID FROM M_Product p" + + " WHERE (p.Value=i.ProductValue OR p.UPC=i.UPC OR p.SKU=i.SKU)" + + " AND p.IsSummary='N' AND i.AD_Client_ID=p.AD_Client_ID AND ROWNUM=1) " + + "WHERE M_Product_ID IS NULL AND (ProductValue IS NOT NULL OR UPC IS NOT NULL OR SKU IS NOT NULL)" + + " AND (C_ValidCombination_ID IS NULL OR C_ValidCombination_ID=0) AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Product from Value=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Product, '" + + "WHERE M_Product_ID IS NULL AND (ProductValue IS NOT NULL OR UPC IS NOT NULL OR SKU IS NOT NULL)" + + " AND (C_ValidCombination_ID IS NULL OR C_ValidCombination_ID=0) AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Product=" + no); + + // Set Project + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET C_Project_ID=(SELECT p.C_Project_ID FROM C_Project p" + + " WHERE p.Value=i.ProjectValue AND p.IsSummary='N' AND i.AD_Client_ID=p.AD_Client_ID) " + + "WHERE C_Project_ID IS NULL AND ProjectValue IS NOT NULL" + + " AND (C_ValidCombination_ID IS NULL OR C_ValidCombination_ID=0) AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Project from Value=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Project, '" + + "WHERE C_Project_ID IS NULL AND ProjectValue IS NOT NULL" + + " AND (C_ValidCombination_ID IS NULL OR C_ValidCombination_ID=0) AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Project=" + no); + + // Set TrxOrg + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET AD_OrgTrx_ID=(SELECT o.AD_Org_ID FROM AD_Org o" + + " WHERE o.Value=i.OrgValue AND o.IsSummary='N' AND i.AD_Client_ID=o.AD_Client_ID) " + + "WHERE AD_OrgTrx_ID IS NULL AND OrgTrxValue IS NOT NULL" + + " AND (C_ValidCombination_ID IS NULL OR C_ValidCombination_ID=0) AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set OrgTrx from Value=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid OrgTrx, '" + + "WHERE AD_OrgTrx_ID IS NULL AND OrgTrxValue IS NOT NULL" + + " AND (C_ValidCombination_ID IS NULL OR C_ValidCombination_ID=0) AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid OrgTrx=" + no); + + + // Source Amounts + sql = new StringBuffer ("UPDATE I_GLJournal " + + "SET AmtSourceDr = 0 " + + "WHERE AmtSourceDr IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set 0 Source Dr=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal " + + "SET AmtSourceCr = 0 " + + "WHERE AmtSourceCr IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set 0 Source Cr=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_ErrorMsg=I_ErrorMsg||'WARN=Zero Source Balance, ' " + + "WHERE (AmtSourceDr-AmtSourceCr)=0" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Zero Source Balance=" + no); + + // Accounted Amounts (Only if No Error) + sql = new StringBuffer ("UPDATE I_GLJournal " + + "SET AmtAcctDr = ROUND(AmtSourceDr * CurrencyRate, 2) " // HARDCODED rounding + + "WHERE AmtAcctDr IS NULL OR AmtAcctDr=0" + + " AND I_IsImported='N'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Calculate Acct Dr=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal " + + "SET AmtAcctCr = ROUND(AmtSourceCr * CurrencyRate, 2) " + + "WHERE AmtAcctCr IS NULL OR AmtAcctCr=0" + + " AND I_IsImported='N'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Calculate Acct Cr=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_ErrorMsg=I_ErrorMsg||'WARN=Zero Acct Balance, ' " + + "WHERE (AmtSourceDr-AmtSourceCr)<>0 AND (AmtAcctDr-AmtAcctCr)=0" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Zero Acct Balance=" + no); + sql = new StringBuffer ("UPDATE I_GLJournal i " + + "SET I_ErrorMsg=I_ErrorMsg||'WARN=Check Acct Balance, ' " + + "WHERE ABS(AmtAcctDr-AmtAcctCr)>100000000" // 100 mio + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Chack Acct Balance=" + no); + + + /*********************************************************************/ + + // Get Balance + sql = new StringBuffer ("SELECT SUM(AmtSourceDr)-SUM(AmtSourceCr), SUM(AmtAcctDr)-SUM(AmtAcctCr) " + + "FROM I_GLJournal " + + "WHERE I_IsImported='N'").append (clientCheck); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + { + BigDecimal source = rs.getBigDecimal(1); + BigDecimal acct = rs.getBigDecimal(2); + if (source != null && source.signum() == 0 + && acct != null && acct.signum() == 0) + log.info ("Import Balance = 0"); + else + log.warning("Balance Source=" + source + ", Acct=" + acct); + if (source != null) + addLog (0, null, source, "@AmtSourceDr@ - @AmtSourceCr@"); + if (acct != null) + addLog (0, null, acct, "@AmtAcctDr@ - @AmtAcctCr@"); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql.toString(), ex); + } + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + + // Count Errors + int errors = DB.getSQLValue(get_TrxName(), + "SELECT COUNT(*) FROM I_GLJournal WHERE I_IsImported NOT IN ('Y','N')" + clientCheck); + + if (errors != 0) + { + if (m_IsValidateOnly || m_IsImportOnlyNoErrors) + throw new Exception ("@Errors@=" + errors); + } + else if (m_IsValidateOnly) + return "@Errors@=" + errors; + + log.info("Validation Errors=" + errors); + commit(); + + /*********************************************************************/ + + int noInsert = 0; + int noInsertJournal = 0; + int noInsertLine = 0; + + MJournalBatch batch = null; // Change Batch per Batch DocumentNo + String BatchDocumentNo = ""; + MJournal journal = null; + String JournalDocumentNo = ""; + Timestamp DateAcct = null; + + // Go through Journal Records + sql = new StringBuffer ("SELECT * FROM I_GLJournal " + + "WHERE I_IsImported='N'").append (clientCheck) + .append(" ORDER BY COALESCE(BatchDocumentNo, TO_NCHAR(I_GLJournal_ID)), COALESCE(JournalDocumentNo, TO_NCHAR(I_GLJournal_ID)), C_AcctSchema_ID, PostingType, C_DocType_ID, GL_Category_ID, C_Currency_ID, TRUNC(DateAcct), Line, I_GLJournal_ID"); + try + { + pstmt = DB.prepareStatement (sql.toString (), get_TrxName()); + ResultSet rs = pstmt.executeQuery (); + // + while (rs.next()) + { + X_I_GLJournal imp = new X_I_GLJournal (getCtx (), rs, get_TrxName()); + + // New Batch if Batch Document No changes + String impBatchDocumentNo = imp.getBatchDocumentNo(); + if (impBatchDocumentNo == null) + impBatchDocumentNo = ""; + if (batch == null + || imp.isCreateNewBatch() + || journal.getC_AcctSchema_ID() != imp.getC_AcctSchema_ID() + || !BatchDocumentNo.equals(impBatchDocumentNo)) + { + BatchDocumentNo = impBatchDocumentNo; // cannot compare real DocumentNo + batch = new MJournalBatch (getCtx(), 0, null); + batch.setClientOrg(imp.getAD_Client_ID(), imp.getAD_OrgDoc_ID()); + if (imp.getBatchDocumentNo() != null + && imp.getBatchDocumentNo().length() > 0) + batch.setDocumentNo (imp.getBatchDocumentNo()); + batch.setC_DocType_ID(imp.getC_DocType_ID()); + batch.setPostingType(imp.getPostingType()); + String description = imp.getBatchDescription(); + if (description == null || description.length() == 0) + description = "*Import-"; + else + description += " *Import-"; + description += new Timestamp(System.currentTimeMillis()); + batch.setDescription(description); + if (!batch.save()) + { + log.log(Level.SEVERE, "Batch not saved"); + Exception ex = CLogger.retrieveException(); + if (ex != null) + { + addLog (0, null, null, ex.getLocalizedMessage()); + throw ex; + } + break; + } + noInsert++; + journal = null; + } + // Journal + String impJournalDocumentNo = imp.getJournalDocumentNo(); + if (impJournalDocumentNo == null) + impJournalDocumentNo = ""; + Timestamp impDateAcct = TimeUtil.getDay(imp.getDateAcct()); + if (journal == null + || imp.isCreateNewJournal() + || !JournalDocumentNo.equals(impJournalDocumentNo) + || journal.getC_DocType_ID() != imp.getC_DocType_ID() + || journal.getGL_Category_ID() != imp.getGL_Category_ID() + || !journal.getPostingType().equals(imp.getPostingType()) + || journal.getC_Currency_ID() != imp.getC_Currency_ID() + || !impDateAcct.equals(DateAcct) + ) + { + JournalDocumentNo = impJournalDocumentNo; // cannot compare real DocumentNo + DateAcct = impDateAcct; + journal = new MJournal (getCtx(), 0, get_TrxName()); + journal.setGL_JournalBatch_ID(batch.getGL_JournalBatch_ID()); + journal.setClientOrg(imp.getAD_Client_ID(), imp.getAD_OrgDoc_ID()); + // + String description = imp.getBatchDescription(); + if (description == null || description.length() == 0) + description = "(Import)"; + journal.setDescription (description); + if (imp.getJournalDocumentNo() != null && imp.getJournalDocumentNo().length() > 0) + journal.setDocumentNo (imp.getJournalDocumentNo()); + // + journal.setC_AcctSchema_ID (imp.getC_AcctSchema_ID()); + journal.setC_DocType_ID (imp.getC_DocType_ID()); + journal.setGL_Category_ID (imp.getGL_Category_ID()); + journal.setPostingType (imp.getPostingType()); + journal.setGL_Budget_ID(imp.getGL_Budget_ID()); + // + journal.setCurrency (imp.getC_Currency_ID(), imp.getC_ConversionType_ID(), imp.getCurrencyRate()); + // + journal.setC_Period_ID(imp.getC_Period_ID()); + journal.setDateAcct(imp.getDateAcct()); // sets Period if not defined + journal.setDateDoc (imp.getDateAcct()); + // + if (!journal.save()) + { + log.log(Level.SEVERE, "Journal not saved"); + Exception ex = CLogger.retrieveException(); + if (ex != null) + { + addLog (0, null, null, ex.getLocalizedMessage()); + throw ex; + } + break; + } + noInsertJournal++; + } + + // Lines + MJournalLine line = new MJournalLine (journal); + // + line.setDescription(imp.getDescription()); + line.setCurrency (imp.getC_Currency_ID(), imp.getC_ConversionType_ID(), imp.getCurrencyRate()); + // Set/Get Account Combination + if (imp.getC_ValidCombination_ID() == 0) + { + MAccount acct = MAccount.get(getCtx(), imp.getAD_Client_ID(), imp.getAD_Org_ID(), + imp.getC_AcctSchema_ID(), imp.getAccount_ID(), 0, + imp.getM_Product_ID(), imp.getC_BPartner_ID(), imp.getAD_OrgTrx_ID(), + imp.getC_LocFrom_ID(), imp.getC_LocTo_ID(), imp.getC_SalesRegion_ID(), + imp.getC_Project_ID(), imp.getC_Campaign_ID(), imp.getC_Activity_ID(), + imp.getUser1_ID(), imp.getUser2_ID(), 0, 0); + if (acct != null && acct.get_ID() == 0) + acct.save(); + if (acct == null || acct.get_ID() == 0) + { + imp.setI_ErrorMsg("ERROR creating Account"); + imp.setI_IsImported(false); + imp.save(); + continue; + } + else + { + line.setC_ValidCombination_ID(acct.get_ID()); + imp.setC_ValidCombination_ID(acct.get_ID()); + } + } + else + line.setC_ValidCombination_ID (imp.getC_ValidCombination_ID()); + // + line.setLine (imp.getLine()); + line.setAmtSourceCr (imp.getAmtSourceCr()); + line.setAmtSourceDr (imp.getAmtSourceDr()); + line.setAmtAcct (imp.getAmtAcctDr(), imp.getAmtAcctCr()); // only if not 0 + line.setDateAcct (imp.getDateAcct()); + // + line.setC_UOM_ID(imp.getC_UOM_ID()); + line.setQty(imp.getQty()); + // + if (line.save()) + { + imp.setGL_JournalBatch_ID(batch.getGL_JournalBatch_ID()); + imp.setGL_Journal_ID(journal.getGL_Journal_ID()); + imp.setGL_JournalLine_ID(line.getGL_JournalLine_ID()); + imp.setI_IsImported(true); + imp.setProcessed(true); + if (imp.save()) + noInsertLine++; + } + } // while records + rs.close(); + pstmt.close(); + } + catch (Exception e) + { + log.log(Level.SEVERE, "", e); + } + // clean up + try + { + if (pstmt != null) + pstmt.close (); + } + catch (SQLException ex1) + { + } + pstmt = null; + + // Set Error to indicator to not imported + sql = new StringBuffer ("UPDATE I_GLJournal " + + "SET I_IsImported='N', Updated=SysDate " + + "WHERE I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog (0, null, new BigDecimal (no), "@Errors@"); + // + addLog (0, null, new BigDecimal (noInsert), "@GL_JournalBatch_ID@: @Inserted@"); + addLog (0, null, new BigDecimal (noInsertJournal), "@GL_Journal_ID@: @Inserted@"); + addLog (0, null, new BigDecimal (noInsertLine), "@GL_JournalLine_ID@: @Inserted@"); + return ""; + } // doIt + +} // ImportGLJournal diff --git a/base/src/org/compiere/process/ImportInOutConfirm.java b/base/src/org/compiere/process/ImportInOutConfirm.java new file mode 100644 index 0000000000..9719b87504 --- /dev/null +++ b/base/src/org/compiere/process/ImportInOutConfirm.java @@ -0,0 +1,198 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Import Confirmations + * + * @author Jorg Janke + * @version $Id: ImportInOutConfirm.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class ImportInOutConfirm extends SvrProcess +{ + /** Client to be imported to */ + private int p_AD_Client_ID = 0; + /** Delete old Imported */ + private boolean p_DeleteOldImported = false; + /** Import */ + private int p_I_InOutLineConfirm_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Client_ID")) + p_AD_Client_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("DeleteOldImported")) + p_DeleteOldImported = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_I_InOutLineConfirm_ID = getRecord_ID(); + } // prepare + + /** + * doIt + * @return info + */ + protected String doIt () throws Exception + { + log.info(""); + StringBuffer sql = null; + int no = 0; + String clientCheck = " AND AD_Client_ID=" + p_AD_Client_ID; + + // Delete Old Imported + if (p_DeleteOldImported) + { + sql = new StringBuffer ("DELETE I_InOutLineConfirm " + + "WHERE I_IsImported='Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Delete Old Impored =" + no); + } + + // Set IsActive, Created/Updated + sql = new StringBuffer ("UPDATE I_InOutLineConfirm " + + "SET IsActive = COALESCE (IsActive, 'Y')," + + " Created = COALESCE (Created, SysDate)," + + " CreatedBy = COALESCE (CreatedBy, 0)," + + " Updated = COALESCE (Updated, SysDate)," + + " UpdatedBy = COALESCE (UpdatedBy, 0)," + + " I_ErrorMsg = NULL," + + " I_IsImported = 'N' " + + "WHERE I_IsImported<>'Y' OR I_IsImported IS NULL"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info ("Reset=" + no); + + // Set Client from Name + sql = new StringBuffer ("UPDATE I_InOutLineConfirm i " + + "SET AD_Client_ID=COALESCE (AD_Client_ID,").append (p_AD_Client_ID).append (") " + + "WHERE (AD_Client_ID IS NULL OR AD_Client_ID=0)" + + " AND I_IsImported<>'Y'"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Client from Value=" + no); + + // Error Confirmation Line + sql = new StringBuffer ("UPDATE I_InOutLineConfirm i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Confirmation Line, '" + + "WHERE (M_InOutLineConfirm_ID IS NULL OR M_InOutLineConfirm_ID=0" + + " OR NOT EXISTS (SELECT * FROM M_InOutLineConfirm c WHERE i.M_InOutLineConfirm_ID=c.M_InOutLineConfirm_ID))" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid InOutLineConfirm=" + no); + + // Error Confirmation No + sql = new StringBuffer ("UPDATE I_InOutLineConfirm i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Missing Confirmation No, '" + + "WHERE (ConfirmationNo IS NULL OR ConfirmationNo='')" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid ConfirmationNo=" + no); + + // Qty + sql = new StringBuffer ("UPDATE I_InOutLineConfirm i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Target<>(Confirmed+Difference+Scrapped), ' " + + "WHERE EXISTS (SELECT * FROM M_InOutLineConfirm c " + + "WHERE i.M_InOutLineConfirm_ID=c.M_InOutLineConfirm_ID" + + " AND c.TargetQty<>(i.ConfirmedQty+i.ScrappedQty+i.DifferenceQty))" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Qty=" + no); + + commit(); + + /*********************************************************************/ + + PreparedStatement pstmt = null; + sql = new StringBuffer ("SELECT * FROM I_InOutLineConfirm " + + "WHERE I_IsImported='N'").append (clientCheck) + .append(" ORDER BY I_InOutLineConfirm_ID"); + no = 0; + try + { + pstmt = DB.prepareStatement (sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + X_I_InOutLineConfirm importLine = new X_I_InOutLineConfirm (getCtx(), rs, get_TrxName()); + MInOutLineConfirm confirmLine = new MInOutLineConfirm (getCtx(), + importLine.getM_InOutLineConfirm_ID(), get_TrxName()); + if (confirmLine.get_ID() == 0 + || confirmLine.get_ID() != importLine.getM_InOutLineConfirm_ID()) + { + importLine.setI_IsImported(false); + importLine.setI_ErrorMsg("ID Not Found"); + importLine.save(); + } + else + { + confirmLine.setConfirmationNo(importLine.getConfirmationNo()); + confirmLine.setConfirmedQty(importLine.getConfirmedQty()); + confirmLine.setDifferenceQty(importLine.getDifferenceQty()); + confirmLine.setScrappedQty(importLine.getScrappedQty()); + confirmLine.setDescription(importLine.getDescription()); + if (confirmLine.save()) + { + // Import + importLine.setI_IsImported(true); + importLine.setProcessed(true); + if (importLine.save()) + no++; + } + } + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + return "@Updated@ #" + no; + } // doIt + +} // ImportInOutConfirm diff --git a/base/src/org/compiere/process/ImportInventory.java b/base/src/org/compiere/process/ImportInventory.java new file mode 100644 index 0000000000..318dbfd0d3 --- /dev/null +++ b/base/src/org/compiere/process/ImportInventory.java @@ -0,0 +1,300 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Import Physical Inventory fom I_Inventory + * + * @author Jorg Janke + * @version $Id: ImportInventory.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ImportInventory extends SvrProcess +{ + /** Client to be imported to */ + private int p_AD_Client_ID = 0; + /** Organization to be imported to */ + private int p_AD_Org_ID = 0; + /** Location to be imported to */ + private int p_M_Locator_ID = 0; + /** Default Date */ + private Timestamp p_MovementDate = null; + /** Delete old Imported */ + private boolean p_DeleteOldImported = false; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Client_ID")) + p_AD_Client_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("AD_Org_ID")) + p_AD_Org_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("M_Locator_ID")) + p_M_Locator_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("MovementDate")) + p_MovementDate = (Timestamp)para[i].getParameter(); + else if (name.equals("DeleteOldImported")) + p_DeleteOldImported = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + + /** + * Perrform process. + * @return Message + * @throws Exception + */ + protected String doIt() throws java.lang.Exception + { + log.info("M_Locator_ID=" + p_M_Locator_ID + ",MovementDate=" + p_MovementDate); + // + StringBuffer sql = null; + int no = 0; + String clientCheck = " AND AD_Client_ID=" + p_AD_Client_ID; + + // **** Prepare **** + + // Delete Old Imported + if (p_DeleteOldImported) + { + sql = new StringBuffer ("DELETE I_Inventory " + + "WHERE I_IsImported='Y'").append (clientCheck); + no = DB.executeUpdate (sql.toString (), get_TrxName()); + log.fine("Delete Old Impored =" + no); + } + + // Set Client, Org, Location, IsActive, Created/Updated + sql = new StringBuffer ("UPDATE I_Inventory " + + "SET AD_Client_ID = COALESCE (AD_Client_ID,").append (p_AD_Client_ID).append (")," + + " AD_Org_ID = COALESCE (AD_Org_ID,").append (p_AD_Org_ID).append ("),"); + if (p_MovementDate != null) + sql.append(" MovementDate = COALESCE (MovementDate,").append (DB.TO_DATE(p_MovementDate)).append ("),"); + sql.append(" IsActive = COALESCE (IsActive, 'Y')," + + " Created = COALESCE (Created, SysDate)," + + " CreatedBy = COALESCE (CreatedBy, 0)," + + " Updated = COALESCE (Updated, SysDate)," + + " UpdatedBy = COALESCE (UpdatedBy, 0)," + + " I_ErrorMsg = NULL," + + " M_Warehouse_ID = NULL," // reset + + " I_IsImported = 'N' " + + "WHERE I_IsImported<>'Y' OR I_IsImported IS NULL"); + no = DB.executeUpdate (sql.toString (), get_TrxName()); + log.info ("Reset=" + no); + + sql = new StringBuffer ("UPDATE I_Inventory o " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Org, '" + + "WHERE (AD_Org_ID IS NULL OR AD_Org_ID=0" + + " OR EXISTS (SELECT * FROM AD_Org oo WHERE o.AD_Org_ID=oo.AD_Org_ID AND (oo.IsSummary='Y' OR oo.IsActive='N')))" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate (sql.toString (), get_TrxName()); + if (no != 0) + log.warning ("Invalid Org=" + no); + + + // Location + sql = new StringBuffer ("UPDATE I_Inventory i " + + "SET M_Locator_ID=(SELECT M_Locator_ID FROM M_Locator l" + + " WHERE i.LocatorValue=l.Value AND i.AD_Client_ID=l.AD_Client_ID AND ROWNUM=1) " + + "WHERE M_Locator_ID IS NULL AND LocatorValue IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate (sql.toString (), get_TrxName()); + log.fine("Set Locator from Value =" + no); + sql = new StringBuffer ("UPDATE I_Inventory i " + + "SET M_Locator_ID=(SELECT M_Locator_ID FROM M_Locator l" + + " WHERE i.X=l.X AND i.Y=l.Y AND i.Z=l.Z AND i.AD_Client_ID=l.AD_Client_ID AND ROWNUM=1) " + + "WHERE M_Locator_ID IS NULL AND X IS NOT NULL AND Y IS NOT NULL AND Z IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate (sql.toString (), get_TrxName()); + log.fine("Set Locator from X,Y,Z =" + no); + if (p_M_Locator_ID != 0) + { + sql = new StringBuffer ("UPDATE I_Inventory " + + "SET M_Locator_ID = ").append (p_M_Locator_ID).append ( + " WHERE M_Locator_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate (sql.toString (), get_TrxName()); + log.fine("Set Locator from Parameter=" + no); + } + sql = new StringBuffer ("UPDATE I_Inventory " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No Location, ' " + + "WHERE M_Locator_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate (sql.toString (), get_TrxName()); + if (no != 0) + log.warning ("No Location=" + no); + + + // Set M_Warehouse_ID + sql = new StringBuffer ("UPDATE I_Inventory i " + + "SET M_Warehouse_ID=(SELECT M_Warehouse_ID FROM M_Locator l WHERE i.M_Locator_ID=l.M_Locator_ID) " + + "WHERE M_Locator_ID IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate (sql.toString (), get_TrxName()); + log.fine("Set Warehouse from Locator =" + no); + sql = new StringBuffer ("UPDATE I_Inventory " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No Warehouse, ' " + + "WHERE M_Warehouse_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate (sql.toString (), get_TrxName()); + if (no != 0) + log.warning ("No Warehouse=" + no); + + + // Product + sql = new StringBuffer ("UPDATE I_Inventory i " + + "SET M_Product_ID=(SELECT M_Product_ID FROM M_Product p" + + " WHERE i.Value=p.Value AND i.AD_Client_ID=p.AD_Client_ID AND ROWNUM=1) " + + "WHERE M_Product_ID IS NULL AND Value IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate (sql.toString (), get_TrxName()); + log.fine("Set Product from Value=" + no); + sql = new StringBuffer ("UPDATE I_Inventory i " + + "SET M_Product_ID=(SELECT M_Product_ID FROM M_Product p" + + " WHERE i.UPC=p.UPC AND i.AD_Client_ID=p.AD_Client_ID AND ROWNUM=1) " + + "WHERE M_Product_ID IS NULL AND UPC IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate (sql.toString (), get_TrxName()); + log.fine("Set Product from UPC=" + no); + sql = new StringBuffer ("UPDATE I_Inventory " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No Product, ' " + + "WHERE M_Product_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate (sql.toString (), get_TrxName()); + if (no != 0) + log.warning ("No Product=" + no); + + // No QtyCount + sql = new StringBuffer ("UPDATE I_Inventory " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No Qty Count, ' " + + "WHERE QtyCount IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate (sql.toString (), get_TrxName()); + if (no != 0) + log.warning ("No QtyCount=" + no); + + commit(); + + /*********************************************************************/ + + MInventory inventory = null; + + int noInsert = 0; + int noInsertLine = 0; + + // Go through Inventory Records + sql = new StringBuffer ("SELECT * FROM I_Inventory " + + "WHERE I_IsImported='N'").append (clientCheck) + .append(" ORDER BY M_Warehouse_ID, TRUNC(MovementDate), I_Inventory_ID"); + try + { + PreparedStatement pstmt = DB.prepareStatement (sql.toString (), get_TrxName()); + ResultSet rs = pstmt.executeQuery (); + // + int x_M_Warehouse_ID = -1; + Timestamp x_MovementDate = null; + while (rs.next()) + { + X_I_Inventory imp = new X_I_Inventory (getCtx (), rs, get_TrxName()); + Timestamp MovementDate = TimeUtil.getDay(imp.getMovementDate()); + + if (inventory == null + || imp.getM_Warehouse_ID() != x_M_Warehouse_ID + || !MovementDate.equals(x_MovementDate)) + { + inventory = new MInventory (getCtx(), 0, get_TrxName()); + inventory.setClientOrg(imp.getAD_Client_ID(), imp.getAD_Org_ID()); + inventory.setDescription("I " + imp.getM_Warehouse_ID() + " " + MovementDate); + inventory.setM_Warehouse_ID(imp.getM_Warehouse_ID()); + inventory.setMovementDate(MovementDate); + // + if (!inventory.save()) + { + log.log(Level.SEVERE, "Inventory not saved"); + break; + } + x_M_Warehouse_ID = imp.getM_Warehouse_ID(); + x_MovementDate = MovementDate; + noInsert++; + } + + // Line + int M_AttributeSetInstance_ID = 0; + if (imp.getLot() != null || imp.getSerNo() != null) + { + MProduct product = MProduct.get(getCtx(), imp.getM_Product_ID()); + if (product.isInstanceAttribute()) + { + MAttributeSet mas = product.getAttributeSet(); + MAttributeSetInstance masi = new MAttributeSetInstance(getCtx(), 0, mas.getM_AttributeSet_ID(), get_TrxName()); + if (mas.isLot() && imp.getLot() != null) + masi.setLot(imp.getLot(), imp.getM_Product_ID()); + if (mas.isSerNo() && imp.getSerNo() != null) + masi.setSerNo(imp.getSerNo()); + masi.setDescription(); + masi.save(); + M_AttributeSetInstance_ID = masi.getM_AttributeSetInstance_ID(); + } + } + MInventoryLine line = new MInventoryLine (inventory, + imp.getM_Locator_ID(), imp.getM_Product_ID(), M_AttributeSetInstance_ID, + imp.getQtyBook(), imp.getQtyCount()); + if (line.save()) + { + imp.setI_IsImported(true); + imp.setM_Inventory_ID(line.getM_Inventory_ID()); + imp.setM_InventoryLine_ID(line.getM_InventoryLine_ID()); + imp.setProcessed(true); + if (imp.save()) + noInsertLine++; + } + } + rs.close(); + pstmt.close(); + } + catch (Exception e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + + // Set Error to indicator to not imported + sql = new StringBuffer ("UPDATE I_Inventory " + + "SET I_IsImported='N', Updated=SysDate " + + "WHERE I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog (0, null, new BigDecimal (no), "@Errors@"); + // + addLog (0, null, new BigDecimal (noInsert), "@M_Inventory_ID@: @Inserted@"); + addLog (0, null, new BigDecimal (noInsertLine), "@M_InventoryLine_ID@: @Inserted@"); + return ""; + } // doIt + +} // ImportInventory diff --git a/base/src/org/compiere/process/ImportInvoice.java b/base/src/org/compiere/process/ImportInvoice.java new file mode 100644 index 0000000000..edb50fc023 --- /dev/null +++ b/base/src/org/compiere/process/ImportInvoice.java @@ -0,0 +1,689 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Import Invoice from I_Invoice + * + * @author Jorg Janke + * @version $Id: ImportInvoice.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ImportInvoice extends SvrProcess +{ + /** Client to be imported to */ + private int m_AD_Client_ID = 0; + /** Organization to be imported to */ + private int m_AD_Org_ID = 0; + /** Delete old Imported */ + private boolean m_deleteOldImported = false; + /** Document Action */ + private String m_docAction = MInvoice.DOCACTION_Prepare; + + + /** Effective */ + private Timestamp m_DateValue = null; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (name.equals("AD_Client_ID")) + m_AD_Client_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("AD_Org_ID")) + m_AD_Org_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("DeleteOldImported")) + m_deleteOldImported = "Y".equals(para[i].getParameter()); + else if (name.equals("DocAction")) + m_docAction = (String)para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + if (m_DateValue == null) + m_DateValue = new Timestamp (System.currentTimeMillis()); + } // prepare + + + /** + * Perrform process. + * @return clear Message + * @throws Exception + */ + protected String doIt() throws java.lang.Exception + { + StringBuffer sql = null; + int no = 0; + String clientCheck = " AND AD_Client_ID=" + m_AD_Client_ID; + + // **** Prepare **** + + // Delete Old Imported + if (m_deleteOldImported) + { + sql = new StringBuffer ("DELETE I_Invoice " + + "WHERE I_IsImported='Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Delete Old Impored =" + no); + } + + // Set Client, Org, IsActive, Created/Updated + sql = new StringBuffer ("UPDATE I_Invoice " + + "SET AD_Client_ID = COALESCE (AD_Client_ID,").append (m_AD_Client_ID).append (")," + + " AD_Org_ID = COALESCE (AD_Org_ID,").append (m_AD_Org_ID).append (")," + + " IsActive = COALESCE (IsActive, 'Y')," + + " Created = COALESCE (Created, SysDate)," + + " CreatedBy = COALESCE (CreatedBy, 0)," + + " Updated = COALESCE (Updated, SysDate)," + + " UpdatedBy = COALESCE (UpdatedBy, 0)," + + " I_ErrorMsg = NULL," + + " I_IsImported = 'N' " + + "WHERE I_IsImported<>'Y' OR I_IsImported IS NULL"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info ("Reset=" + no); + + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Org, '" + + "WHERE (AD_Org_ID IS NULL OR AD_Org_ID=0" + + " OR EXISTS (SELECT * FROM AD_Org oo WHERE o.AD_Org_ID=oo.AD_Org_ID AND (oo.IsSummary='Y' OR oo.IsActive='N')))" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Org=" + no); + + // Document Type - PO - SO + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET C_DocType_ID=(SELECT C_DocType_ID FROM C_DocType d WHERE d.Name=o.DocTypeName" + + " AND d.DocBaseType IN ('API','APC') AND o.AD_Client_ID=d.AD_Client_ID) " + + "WHERE C_DocType_ID IS NULL AND IsSOTrx='N' AND DocTypeName IS NOT NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.fine("Set PO DocType=" + no); + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET C_DocType_ID=(SELECT C_DocType_ID FROM C_DocType d WHERE d.Name=o.DocTypeName" + + " AND d.DocBaseType IN ('ARI','ARC') AND o.AD_Client_ID=d.AD_Client_ID) " + + "WHERE C_DocType_ID IS NULL AND IsSOTrx='Y' AND DocTypeName IS NOT NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.fine("Set SO DocType=" + no); + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET C_DocType_ID=(SELECT C_DocType_ID FROM C_DocType d WHERE d.Name=o.DocTypeName" + + " AND d.DocBaseType IN ('API','ARI','APC','ARC') AND o.AD_Client_ID=d.AD_Client_ID) " + //+ "WHERE C_DocType_ID IS NULL AND IsSOTrx IS NULL AND DocTypeName IS NOT NULL AND I_IsImported<>'Y'").append (clientCheck); + + "WHERE C_DocType_ID IS NULL AND DocTypeName IS NOT NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.fine("Set DocType=" + no); + sql = new StringBuffer ("UPDATE I_Invoice " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid DocTypeName, ' " + + "WHERE C_DocType_ID IS NULL AND DocTypeName IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid DocTypeName=" + no); + // DocType Default + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET C_DocType_ID=(SELECT C_DocType_ID FROM C_DocType d WHERE d.IsDefault='Y'" + + " AND d.DocBaseType='API' AND ROWNUM=1 AND o.AD_Client_ID=d.AD_Client_ID) " + + "WHERE C_DocType_ID IS NULL AND IsSOTrx='N' AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.fine("Set PO Default DocType=" + no); + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET C_DocType_ID=(SELECT C_DocType_ID FROM C_DocType d WHERE d.IsDefault='Y'" + + " AND d.DocBaseType='ARI' AND ROWNUM=1 AND o.AD_Client_ID=d.AD_Client_ID) " + + "WHERE C_DocType_ID IS NULL AND IsSOTrx='Y' AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.fine("Set SO Default DocType=" + no); + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET C_DocType_ID=(SELECT C_DocType_ID FROM C_DocType d WHERE d.IsDefault='Y'" + + " AND d.DocBaseType IN('ARI','API') AND ROWNUM=1 AND o.AD_Client_ID=d.AD_Client_ID) " + + "WHERE C_DocType_ID IS NULL AND IsSOTrx IS NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.fine("Set Default DocType=" + no); + sql = new StringBuffer ("UPDATE I_Invoice " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No DocType, ' " + + "WHERE C_DocType_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("No DocType=" + no); + + // Set IsSOTrx + sql = new StringBuffer ("UPDATE I_Invoice o SET IsSOTrx='Y' " + + "WHERE EXISTS (SELECT * FROM C_DocType d WHERE o.C_DocType_ID=d.C_DocType_ID AND d.DocBaseType='ARI' AND o.AD_Client_ID=d.AD_Client_ID)" + + " AND C_DocType_ID IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set IsSOTrx=Y=" + no); + sql = new StringBuffer ("UPDATE I_Invoice o SET IsSOTrx='N' " + + "WHERE EXISTS (SELECT * FROM C_DocType d WHERE o.C_DocType_ID=d.C_DocType_ID AND d.DocBaseType='API' AND o.AD_Client_ID=d.AD_Client_ID)" + + " AND C_DocType_ID IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set IsSOTrx=N=" + no); + + // Price List + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET M_PriceList_ID=(SELECT M_PriceList_ID FROM M_PriceList p WHERE p.IsDefault='Y'" + + " AND p.C_Currency_ID=o.C_Currency_ID AND p.IsSOPriceList=o.IsSOTrx AND ROWNUM=1 AND o.AD_Client_ID=p.AD_Client_ID) " + + "WHERE M_PriceList_ID IS NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Default Currency PriceList=" + no); + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET M_PriceList_ID=(SELECT M_PriceList_ID FROM M_PriceList p WHERE p.IsDefault='Y'" + + " AND p.IsSOPriceList=o.IsSOTrx AND ROWNUM=1 AND o.AD_Client_ID=p.AD_Client_ID) " + + "WHERE M_PriceList_ID IS NULL AND C_Currency_ID IS NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Default PriceList=" + no); + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET M_PriceList_ID=(SELECT M_PriceList_ID FROM M_PriceList p " + + " WHERE p.C_Currency_ID=o.C_Currency_ID AND p.IsSOPriceList=o.IsSOTrx AND ROWNUM=1 AND o.AD_Client_ID=p.AD_Client_ID) " + + "WHERE M_PriceList_ID IS NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Currency PriceList=" + no); + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET M_PriceList_ID=(SELECT M_PriceList_ID FROM M_PriceList p " + + " WHERE p.IsSOPriceList=o.IsSOTrx AND ROWNUM=1 AND o.AD_Client_ID=p.AD_Client_ID) " + + "WHERE M_PriceList_ID IS NULL AND C_Currency_ID IS NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set PriceList=" + no); + // + sql = new StringBuffer ("UPDATE I_Invoice " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No PriceList, ' " + + "WHERE M_PriceList_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning("No PriceList=" + no); + + // Payment Term + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET C_PaymentTerm_ID=(SELECT C_PaymentTerm_ID FROM C_PaymentTerm p" + + " WHERE o.PaymentTermValue=p.Value AND o.AD_Client_ID=p.AD_Client_ID) " + + "WHERE C_PaymentTerm_ID IS NULL AND PaymentTermValue IS NOT NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set PaymentTerm=" + no); + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET C_PaymentTerm_ID=(SELECT C_PaymentTerm_ID FROM C_PaymentTerm p" + + " WHERE p.IsDefault='Y' AND ROWNUM=1 AND o.AD_Client_ID=p.AD_Client_ID) " + + "WHERE C_PaymentTerm_ID IS NULL AND o.PaymentTermValue IS NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Default PaymentTerm=" + no); + // + sql = new StringBuffer ("UPDATE I_Invoice " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No PaymentTerm, ' " + + "WHERE C_PaymentTerm_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("No PaymentTerm=" + no); + + // BP from EMail + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET (C_BPartner_ID,AD_User_ID)=(SELECT C_BPartner_ID,AD_User_ID FROM AD_User u" + + " WHERE o.EMail=u.EMail AND o.AD_Client_ID=u.AD_Client_ID AND u.C_BPartner_ID IS NOT NULL) " + + "WHERE C_BPartner_ID IS NULL AND EMail IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set BP from EMail=" + no); + // BP from ContactName + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET (C_BPartner_ID,AD_User_ID)=(SELECT C_BPartner_ID,AD_User_ID FROM AD_User u" + + " WHERE o.ContactName=u.Name AND o.AD_Client_ID=u.AD_Client_ID AND u.C_BPartner_ID IS NOT NULL) " + + "WHERE C_BPartner_ID IS NULL AND ContactName IS NOT NULL" + + " AND EXISTS (SELECT Name FROM AD_User u WHERE o.ContactName=u.Name AND o.AD_Client_ID=u.AD_Client_ID AND u.C_BPartner_ID IS NOT NULL GROUP BY Name HAVING COUNT(*)=1)" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set BP from ContactName=" + no); + // BP from Value + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET C_BPartner_ID=(SELECT C_BPartner_ID FROM C_BPartner bp" + + " WHERE o.BPartnerValue=bp.Value AND o.AD_Client_ID=bp.AD_Client_ID AND ROWNUM=1) " + + "WHERE C_BPartner_ID IS NULL AND BPartnerValue IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set BP from Value=" + no); + // Default BP + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET C_BPartner_ID=(SELECT C_BPartnerCashTrx_ID FROM AD_ClientInfo c" + + " WHERE o.AD_Client_ID=c.AD_Client_ID) " + + "WHERE C_BPartner_ID IS NULL AND BPartnerValue IS NULL AND Name IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Default BP=" + no); + + // Existing Location ? Exact Match + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET C_BPartner_Location_ID=(SELECT C_BPartner_Location_ID" + + " FROM C_BPartner_Location bpl INNER JOIN C_Location l ON (bpl.C_Location_ID=l.C_Location_ID)" + + " WHERE o.C_BPartner_ID=bpl.C_BPartner_ID AND bpl.AD_Client_ID=o.AD_Client_ID" + + " AND DUMP(o.Address1)=DUMP(l.Address1) AND DUMP(o.Address2)=DUMP(l.Address2)" + + " AND DUMP(o.City)=DUMP(l.City) AND DUMP(o.Postal)=DUMP(l.Postal)" + + " AND DUMP(o.C_Region_ID)=DUMP(l.C_Region_ID) AND DUMP(o.C_Country_ID)=DUMP(l.C_Country_ID)) " + + "WHERE C_BPartner_ID IS NOT NULL AND C_BPartner_Location_ID IS NULL" + + " AND I_IsImported='N'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Found Location=" + no); + // Set Location from BPartner + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET C_BPartner_Location_ID=(SELECT C_BPartner_Location_ID FROM C_BPartner_Location l" + + " WHERE l.C_BPartner_ID=o.C_BPartner_ID AND o.AD_Client_ID=l.AD_Client_ID" + + " AND ((l.IsBillTo='Y' AND o.IsSOTrx='Y') OR o.IsSOTrx='N')" + + " AND ROWNUM=1) " + + "WHERE C_BPartner_ID IS NOT NULL AND C_BPartner_Location_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set BP Location from BP=" + no); + // + sql = new StringBuffer ("UPDATE I_Invoice " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No BP Location, ' " + + "WHERE C_BPartner_ID IS NOT NULL AND C_BPartner_Location_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("No BP Location=" + no); + + // Set Country + /** + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET CountryCode=(SELECT CountryCode FROM C_Country c WHERE c.IsDefault='Y'" + + " AND c.AD_Client_ID IN (0, o.AD_Client_ID) AND ROWNUM=1) " + + "WHERE C_BPartner_ID IS NULL AND CountryCode IS NULL AND C_Country_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Country Default=" + no); + **/ + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET C_Country_ID=(SELECT C_Country_ID FROM C_Country c" + + " WHERE o.CountryCode=c.CountryCode AND c.AD_Client_ID IN (0, o.AD_Client_ID)) " + + "WHERE C_BPartner_ID IS NULL AND C_Country_ID IS NULL AND CountryCode IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Country=" + no); + // + sql = new StringBuffer ("UPDATE I_Invoice " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Country, ' " + + "WHERE C_BPartner_ID IS NULL AND C_Country_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Country=" + no); + + // Set Region + sql = new StringBuffer ("UPDATE I_Invoice o " + + "Set RegionName=(SELECT Name FROM C_Region r" + + " WHERE r.IsDefault='Y' AND r.C_Country_ID=o.C_Country_ID" + + " AND r.AD_Client_ID IN (0, o.AD_Client_ID) AND ROWNUM=1) " + + "WHERE C_BPartner_ID IS NULL AND C_Region_ID IS NULL AND RegionName IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Region Default=" + no); + // + sql = new StringBuffer ("UPDATE I_Invoice o " + + "Set C_Region_ID=(SELECT C_Region_ID FROM C_Region r" + + " WHERE r.Name=o.RegionName AND r.C_Country_ID=o.C_Country_ID" + + " AND r.AD_Client_ID IN (0, o.AD_Client_ID)) " + + "WHERE C_BPartner_ID IS NULL AND C_Region_ID IS NULL AND RegionName IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Region=" + no); + // + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Region, ' " + + "WHERE C_BPartner_ID IS NULL AND C_Region_ID IS NULL " + + " AND EXISTS (SELECT * FROM C_Country c" + + " WHERE c.C_Country_ID=o.C_Country_ID AND c.HasRegion='Y')" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Region=" + no); + + // Product + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET M_Product_ID=(SELECT M_Product_ID FROM M_Product p" + + " WHERE o.ProductValue=p.Value AND o.AD_Client_ID=p.AD_Client_ID AND ROWNUM=1) " + + "WHERE M_Product_ID IS NULL AND ProductValue IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Product from Value=" + no); + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET M_Product_ID=(SELECT M_Product_ID FROM M_Product p" + + " WHERE o.UPC=p.UPC AND o.AD_Client_ID=p.AD_Client_ID AND ROWNUM=1) " + + "WHERE M_Product_ID IS NULL AND UPC IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Product from UPC=" + no); + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET M_Product_ID=(SELECT M_Product_ID FROM M_Product p" + + " WHERE o.SKU=p.SKU AND o.AD_Client_ID=p.AD_Client_ID AND ROWNUM=1) " + + "WHERE M_Product_ID IS NULL AND SKU IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Product fom SKU=" + no); + sql = new StringBuffer ("UPDATE I_Invoice " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Product, ' " + + "WHERE M_Product_ID IS NULL AND (ProductValue IS NOT NULL OR UPC IS NOT NULL OR SKU IS NOT NULL)" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Product=" + no); + + // Tax + sql = new StringBuffer ("UPDATE I_Invoice o " + + "SET C_Tax_ID=(SELECT C_Tax_ID FROM C_Tax t" + + " WHERE o.TaxIndicator=t.TaxIndicator AND o.AD_Client_ID=t.AD_Client_ID AND ROWNUM=1) " + + "WHERE C_Tax_ID IS NULL AND TaxIndicator IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Tax=" + no); + sql = new StringBuffer ("UPDATE I_Invoice " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Tax, ' " + + "WHERE C_Tax_ID IS NULL AND TaxIndicator IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Tax=" + no); + + commit(); + + // -- New BPartner --------------------------------------------------- + + // Go through Invoice Records w/o C_BPartner_ID + sql = new StringBuffer ("SELECT * FROM I_Invoice " + + "WHERE I_IsImported='N' AND C_BPartner_ID IS NULL").append (clientCheck); + try + { + PreparedStatement pstmt = DB.prepareStatement (sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + X_I_Invoice imp = new X_I_Invoice (getCtx(), rs, get_TrxName()); + if (imp.getBPartnerValue () == null) + { + if (imp.getEMail () != null) + imp.setBPartnerValue (imp.getEMail ()); + else if (imp.getName () != null) + imp.setBPartnerValue (imp.getName ()); + else + continue; + } + if (imp.getName () == null) + { + if (imp.getContactName () != null) + imp.setName (imp.getContactName ()); + else + imp.setName (imp.getBPartnerValue ()); + } + // BPartner + MBPartner bp = MBPartner.get (getCtx(), imp.getBPartnerValue()); + if (bp == null) + { + bp = new MBPartner (getCtx (), -1, get_TrxName()); + bp.setClientOrg (imp.getAD_Client_ID (), imp.getAD_Org_ID ()); + bp.setValue (imp.getBPartnerValue ()); + bp.setName (imp.getName ()); + if (!bp.save ()) + continue; + } + imp.setC_BPartner_ID (bp.getC_BPartner_ID ()); + + // BP Location + MBPartnerLocation bpl = null; + MBPartnerLocation[] bpls = bp.getLocations(true); + for (int i = 0; bpl == null && i < bpls.length; i++) + { + if (imp.getC_BPartner_Location_ID() == bpls[i].getC_BPartner_Location_ID()) + bpl = bpls[i]; + // Same Location ID + else if (imp.getC_Location_ID() == bpls[i].getC_Location_ID()) + bpl = bpls[i]; + // Same Location Info + else if (imp.getC_Location_ID() == 0) + { + MLocation loc = bpl.getLocation(false); + if (loc.equals(imp.getC_Country_ID(), imp.getC_Region_ID(), + imp.getPostal(), "", imp.getCity(), + imp.getAddress1(), imp.getAddress2())) + bpl = bpls[i]; + } + } + if (bpl == null) + { + // New Location + MLocation loc = new MLocation (getCtx (), 0, get_TrxName()); + loc.setAddress1 (imp.getAddress1 ()); + loc.setAddress2 (imp.getAddress2 ()); + loc.setCity (imp.getCity ()); + loc.setPostal (imp.getPostal ()); + if (imp.getC_Region_ID () != 0) + loc.setC_Region_ID (imp.getC_Region_ID ()); + loc.setC_Country_ID (imp.getC_Country_ID ()); + if (!loc.save ()) + continue; + // + bpl = new MBPartnerLocation (bp); + bpl.setC_Location_ID (imp.getC_Location_ID ()); + if (!bpl.save ()) + continue; + } + imp.setC_Location_ID (bpl.getC_Location_ID ()); + imp.setC_BPartner_Location_ID (bpl.getC_BPartner_Location_ID ()); + + // User/Contact + if (imp.getContactName () != null + || imp.getEMail () != null + || imp.getPhone () != null) + { + MUser[] users = bp.getContacts(true); + MUser user = null; + for (int i = 0; user == null && i < users.length; i++) + { + String name = users[i].getName(); + if (name.equals(imp.getContactName()) + || name.equals(imp.getName())) + { + user = users[i]; + imp.setAD_User_ID (user.getAD_User_ID ()); + } + } + if (user == null) + { + user = new MUser (bp); + if (imp.getContactName () == null) + user.setName (imp.getName ()); + else + user.setName (imp.getContactName ()); + user.setEMail (imp.getEMail ()); + user.setPhone (imp.getPhone ()); + if (user.save ()) + imp.setAD_User_ID (user.getAD_User_ID ()); + } + } + imp.save (); + } // for all new BPartners + rs.close (); + pstmt.close (); + // + } + catch (SQLException e) + { + log.log(Level.SEVERE, "CreateBP", e); + } + sql = new StringBuffer ("UPDATE I_Invoice " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No BPartner, ' " + + "WHERE C_BPartner_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("No BPartner=" + no); + + commit(); + + // -- New Invoices ----------------------------------------------------- + + int noInsert = 0; + int noInsertLine = 0; + + // Go through Invoice Records w/o + sql = new StringBuffer ("SELECT * FROM I_Invoice " + + "WHERE I_IsImported='N'").append (clientCheck) + .append(" ORDER BY C_BPartner_ID, C_BPartner_Location_ID, I_Invoice_ID"); + try + { + PreparedStatement pstmt = DB.prepareStatement (sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery (); + // Group Change + int oldC_BPartner_ID = 0; + int oldC_BPartner_Location_ID = 0; + String oldDocumentNo = ""; + // + MInvoice invoice = null; + int lineNo = 0; + while (rs.next ()) + { + X_I_Invoice imp = new X_I_Invoice (getCtx (), rs, null); + String cmpDocumentNo = imp.getDocumentNo(); + if (cmpDocumentNo == null) + cmpDocumentNo = ""; + // New Invoice + if (oldC_BPartner_ID != imp.getC_BPartner_ID() + || oldC_BPartner_Location_ID != imp.getC_BPartner_Location_ID() + || !oldDocumentNo.equals(cmpDocumentNo) ) + { + if (invoice != null) + { + invoice.processIt(m_docAction); + invoice.save(); + } + // Group Change + oldC_BPartner_ID = imp.getC_BPartner_ID(); + oldC_BPartner_Location_ID = imp.getC_BPartner_Location_ID(); + oldDocumentNo = imp.getDocumentNo(); + if (oldDocumentNo == null) + oldDocumentNo = ""; + // + invoice = new MInvoice (getCtx(), 0, null); + invoice.setClientOrg (imp.getAD_Client_ID(), imp.getAD_Org_ID()); + invoice.setC_DocTypeTarget_ID(imp.getC_DocType_ID()); + invoice.setIsSOTrx(imp.isSOTrx()); + if (imp.getDocumentNo() != null) + invoice.setDocumentNo(imp.getDocumentNo()); + // + invoice.setC_BPartner_ID(imp.getC_BPartner_ID()); + invoice.setC_BPartner_Location_ID(imp.getC_BPartner_Location_ID()); + if (imp.getAD_User_ID() != 0) + invoice.setAD_User_ID(imp.getAD_User_ID()); + // + if (imp.getDescription() != null) + invoice.setDescription(imp.getDescription()); + invoice.setC_PaymentTerm_ID(imp.getC_PaymentTerm_ID()); + invoice.setM_PriceList_ID(imp.getM_PriceList_ID()); + // SalesRep from Import or the person running the import + if (imp.getSalesRep_ID() != 0) + invoice.setSalesRep_ID(imp.getSalesRep_ID()); + if (invoice.getSalesRep_ID() == 0) + invoice.setSalesRep_ID(getAD_User_ID()); + // + if (imp.getAD_OrgTrx_ID() != 0) + invoice.setAD_OrgTrx_ID(imp.getAD_OrgTrx_ID()); + if (imp.getC_Activity_ID() != 0) + invoice.setC_Activity_ID(imp.getC_Activity_ID()); + if (imp.getC_Campaign_ID() != 0) + invoice.setC_Campaign_ID(imp.getC_Campaign_ID()); + if (imp.getC_Project_ID() != 0) + invoice.setC_Project_ID(imp.getC_Project_ID()); + // + if (imp.getDateInvoiced() != null) + invoice.setDateInvoiced(imp.getDateInvoiced()); + if (imp.getDateAcct() != null) + invoice.setDateAcct(imp.getDateAcct()); + // + invoice.save(); + noInsert++; + lineNo = 10; + } + imp.setC_Invoice_ID (invoice.getC_Invoice_ID()); + // New InvoiceLine + MInvoiceLine line = new MInvoiceLine (invoice); + if (imp.getLineDescription() != null) + line.setDescription(imp.getLineDescription()); + line.setLine(lineNo); + lineNo += 10; + if (imp.getM_Product_ID() != 0) + line.setM_Product_ID(imp.getM_Product_ID(), true); + line.setQty(imp.getQtyOrdered()); + line.setPrice(); + BigDecimal price = imp.getPriceActual(); + if (price != null && Env.ZERO.compareTo(price) != 0) + line.setPrice(price); + if (imp.getC_Tax_ID() != 0) + line.setC_Tax_ID(imp.getC_Tax_ID()); + else + { + line.setTax(); + imp.setC_Tax_ID(line.getC_Tax_ID()); + } + BigDecimal taxAmt = imp.getTaxAmt(); + if (taxAmt != null && Env.ZERO.compareTo(taxAmt) != 0) + line.setTaxAmt(taxAmt); + line.save(); + // + imp.setC_InvoiceLine_ID(line.getC_InvoiceLine_ID()); + imp.setI_IsImported(true); + imp.setProcessed(true); + // + if (imp.save()) + noInsertLine++; + } + if (invoice != null) + { + invoice.processIt (m_docAction); + invoice.save(); + } + rs.close(); + pstmt.close(); + } + catch (Exception e) + { + log.log(Level.SEVERE, "CreateInvoice", e); + } + + // Set Error to indicator to not imported + sql = new StringBuffer ("UPDATE I_Invoice " + + "SET I_IsImported='N', Updated=SysDate " + + "WHERE I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog (0, null, new BigDecimal (no), "@Errors@"); + // + addLog (0, null, new BigDecimal (noInsert), "@C_Invoice_ID@: @Inserted@"); + addLog (0, null, new BigDecimal (noInsertLine), "@C_InvoiceLine_ID@: @Inserted@"); + return ""; + } // doIt + +} // ImportInvoice diff --git a/base/src/org/compiere/process/ImportOrder.java b/base/src/org/compiere/process/ImportOrder.java new file mode 100644 index 0000000000..7b5b661c0c --- /dev/null +++ b/base/src/org/compiere/process/ImportOrder.java @@ -0,0 +1,733 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Import Order from I_Order + * + * @author Jorg Janke + * @version $Id: ImportOrder.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class ImportOrder extends SvrProcess +{ + /** Client to be imported to */ + private int m_AD_Client_ID = 0; + /** Organization to be imported to */ + private int m_AD_Org_ID = 0; + /** Delete old Imported */ + private boolean m_deleteOldImported = false; + /** Document Action */ + private String m_docAction = MOrder.DOCACTION_Prepare; + + + /** Effective */ + private Timestamp m_DateValue = null; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (name.equals("AD_Client_ID")) + m_AD_Client_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("AD_Org_ID")) + m_AD_Org_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("DeleteOldImported")) + m_deleteOldImported = "Y".equals(para[i].getParameter()); + else if (name.equals("DocAction")) + m_docAction = (String)para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + if (m_DateValue == null) + m_DateValue = new Timestamp (System.currentTimeMillis()); + } // prepare + + + /** + * Perrform process. + * @return Message + * @throws Exception + */ + protected String doIt() throws java.lang.Exception + { + StringBuffer sql = null; + int no = 0; + String clientCheck = " AND AD_Client_ID=" + m_AD_Client_ID; + + // **** Prepare **** + + // Delete Old Imported + if (m_deleteOldImported) + { + sql = new StringBuffer ("DELETE I_Order " + + "WHERE I_IsImported='Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Delete Old Impored =" + no); + } + + // Set Client, Org, IsActive, Created/Updated + sql = new StringBuffer ("UPDATE I_Order " + + "SET AD_Client_ID = COALESCE (AD_Client_ID,").append (m_AD_Client_ID).append (")," + + " AD_Org_ID = COALESCE (AD_Org_ID,").append (m_AD_Org_ID).append (")," + + " IsActive = COALESCE (IsActive, 'Y')," + + " Created = COALESCE (Created, SysDate)," + + " CreatedBy = COALESCE (CreatedBy, 0)," + + " Updated = COALESCE (Updated, SysDate)," + + " UpdatedBy = COALESCE (UpdatedBy, 0)," + + " I_ErrorMsg = NULL," + + " I_IsImported = 'N' " + + "WHERE I_IsImported<>'Y' OR I_IsImported IS NULL"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info ("Reset=" + no); + + sql = new StringBuffer ("UPDATE I_Order o " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Org, '" + + "WHERE (AD_Org_ID IS NULL OR AD_Org_ID=0" + + " OR EXISTS (SELECT * FROM AD_Org oo WHERE o.AD_Org_ID=oo.AD_Org_ID AND (oo.IsSummary='Y' OR oo.IsActive='N')))" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Org=" + no); + + // Document Type - PO - SO + sql = new StringBuffer ("UPDATE I_Order o " // PO Document Type Name + + "SET C_DocType_ID=(SELECT C_DocType_ID FROM C_DocType d WHERE d.Name=o.DocTypeName" + + " AND d.DocBaseType='POO' AND o.AD_Client_ID=d.AD_Client_ID) " + + "WHERE C_DocType_ID IS NULL AND IsSOTrx='N' AND DocTypeName IS NOT NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set PO DocType=" + no); + sql = new StringBuffer ("UPDATE I_Order o " // SO Document Type Name + + "SET C_DocType_ID=(SELECT C_DocType_ID FROM C_DocType d WHERE d.Name=o.DocTypeName" + + " AND d.DocBaseType='SOO' AND o.AD_Client_ID=d.AD_Client_ID) " + + "WHERE C_DocType_ID IS NULL AND IsSOTrx='Y' AND DocTypeName IS NOT NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set SO DocType=" + no); + sql = new StringBuffer ("UPDATE I_Order o " + + "SET C_DocType_ID=(SELECT C_DocType_ID FROM C_DocType d WHERE d.Name=o.DocTypeName" + + " AND d.DocBaseType IN ('SOO','POO') AND o.AD_Client_ID=d.AD_Client_ID) " + //+ "WHERE C_DocType_ID IS NULL AND IsSOTrx IS NULL AND DocTypeName IS NOT NULL AND I_IsImported<>'Y'").append (clientCheck); + + "WHERE C_DocType_ID IS NULL AND DocTypeName IS NOT NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set DocType=" + no); + sql = new StringBuffer ("UPDATE I_Order " // Error Invalid Doc Type Name + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid DocTypeName, ' " + + "WHERE C_DocType_ID IS NULL AND DocTypeName IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid DocTypeName=" + no); + // DocType Default + sql = new StringBuffer ("UPDATE I_Order o " // Default PO + + "SET C_DocType_ID=(SELECT C_DocType_ID FROM C_DocType d WHERE d.IsDefault='Y'" + + " AND d.DocBaseType='POO' AND ROWNUM=1 AND o.AD_Client_ID=d.AD_Client_ID) " + + "WHERE C_DocType_ID IS NULL AND IsSOTrx='N' AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set PO Default DocType=" + no); + sql = new StringBuffer ("UPDATE I_Order o " // Default SO + + "SET C_DocType_ID=(SELECT C_DocType_ID FROM C_DocType d WHERE d.IsDefault='Y'" + + " AND d.DocBaseType='SOO' AND ROWNUM=1 AND o.AD_Client_ID=d.AD_Client_ID) " + + "WHERE C_DocType_ID IS NULL AND IsSOTrx='Y' AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set SO Default DocType=" + no); + sql = new StringBuffer ("UPDATE I_Order o " + + "SET C_DocType_ID=(SELECT C_DocType_ID FROM C_DocType d WHERE d.IsDefault='Y'" + + " AND d.DocBaseType IN('SOO','POO') AND ROWNUM=1 AND o.AD_Client_ID=d.AD_Client_ID) " + + "WHERE C_DocType_ID IS NULL AND IsSOTrx IS NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Default DocType=" + no); + sql = new StringBuffer ("UPDATE I_Order " // No DocType + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No DocType, ' " + + "WHERE C_DocType_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("No DocType=" + no); + + // Set IsSOTrx + sql = new StringBuffer ("UPDATE I_Order o SET IsSOTrx='Y' " + + "WHERE EXISTS (SELECT * FROM C_DocType d WHERE o.C_DocType_ID=d.C_DocType_ID AND d.DocBaseType='SOO' AND o.AD_Client_ID=d.AD_Client_ID)" + + " AND C_DocType_ID IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set IsSOTrx=Y=" + no); + sql = new StringBuffer ("UPDATE I_Order o SET IsSOTrx='N' " + + "WHERE EXISTS (SELECT * FROM C_DocType d WHERE o.C_DocType_ID=d.C_DocType_ID AND d.DocBaseType='POO' AND o.AD_Client_ID=d.AD_Client_ID)" + + " AND C_DocType_ID IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set IsSOTrx=N=" + no); + + // Price List + sql = new StringBuffer ("UPDATE I_Order o " + + "SET M_PriceList_ID=(SELECT M_PriceList_ID FROM M_PriceList p WHERE p.IsDefault='Y'" + + " AND p.C_Currency_ID=o.C_Currency_ID AND p.IsSOPriceList=o.IsSOTrx AND ROWNUM=1 AND o.AD_Client_ID=p.AD_Client_ID) " + + "WHERE M_PriceList_ID IS NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Default Currency PriceList=" + no); + sql = new StringBuffer ("UPDATE I_Order o " + + "SET M_PriceList_ID=(SELECT M_PriceList_ID FROM M_PriceList p WHERE p.IsDefault='Y'" + + " AND p.IsSOPriceList=o.IsSOTrx AND ROWNUM=1 AND o.AD_Client_ID=p.AD_Client_ID) " + + "WHERE M_PriceList_ID IS NULL AND C_Currency_ID IS NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Default PriceList=" + no); + sql = new StringBuffer ("UPDATE I_Order o " + + "SET M_PriceList_ID=(SELECT M_PriceList_ID FROM M_PriceList p " + + " WHERE p.C_Currency_ID=o.C_Currency_ID AND p.IsSOPriceList=o.IsSOTrx AND ROWNUM=1 AND o.AD_Client_ID=p.AD_Client_ID) " + + "WHERE M_PriceList_ID IS NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Currency PriceList=" + no); + sql = new StringBuffer ("UPDATE I_Order o " + + "SET M_PriceList_ID=(SELECT M_PriceList_ID FROM M_PriceList p " + + " WHERE p.IsSOPriceList=o.IsSOTrx AND ROWNUM=1 AND o.AD_Client_ID=p.AD_Client_ID) " + + "WHERE M_PriceList_ID IS NULL AND C_Currency_ID IS NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set PriceList=" + no); + // + sql = new StringBuffer ("UPDATE I_Order " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No PriceList, ' " + + "WHERE M_PriceList_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning("No PriceList=" + no); + + // Payment Term + sql = new StringBuffer ("UPDATE I_Order o " + + "SET C_PaymentTerm_ID=(SELECT C_PaymentTerm_ID FROM C_PaymentTerm p" + + " WHERE o.PaymentTermValue=p.Value AND o.AD_Client_ID=p.AD_Client_ID) " + + "WHERE C_PaymentTerm_ID IS NULL AND PaymentTermValue IS NOT NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set PaymentTerm=" + no); + sql = new StringBuffer ("UPDATE I_Order o " + + "SET C_PaymentTerm_ID=(SELECT C_PaymentTerm_ID FROM C_PaymentTerm p" + + " WHERE p.IsDefault='Y' AND ROWNUM=1 AND o.AD_Client_ID=p.AD_Client_ID) " + + "WHERE C_PaymentTerm_ID IS NULL AND o.PaymentTermValue IS NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Default PaymentTerm=" + no); + // + sql = new StringBuffer ("UPDATE I_Order " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No PaymentTerm, ' " + + "WHERE C_PaymentTerm_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("No PaymentTerm=" + no); + + // Warehouse + sql = new StringBuffer ("UPDATE I_Order o " + + "SET M_Warehouse_ID=(SELECT M_Warehouse_ID FROM M_Warehouse w" + + " WHERE ROWNUM=1 AND o.AD_Client_ID=w.AD_Client_ID AND o.AD_Org_ID=w.AD_Org_ID) " + + "WHERE M_Warehouse_ID IS NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); // Warehouse for Org + if (no != 0) + log.fine("Set Warehouse=" + no); + sql = new StringBuffer ("UPDATE I_Order o " + + "SET M_Warehouse_ID=(SELECT M_Warehouse_ID FROM M_Warehouse w" + + " WHERE o.AD_Client_ID=w.AD_Client_ID) " + + "WHERE M_Warehouse_ID IS NULL" + + " AND EXISTS (SELECT AD_Client_ID FROM M_Warehouse w WHERE w.AD_Client_ID=o.AD_Client_ID GROUP BY AD_Client_ID HAVING COUNT(*)=1)" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.fine("Set Only Client Warehouse=" + no); + // + sql = new StringBuffer ("UPDATE I_Order " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No Warehouse, ' " + + "WHERE M_Warehouse_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("No Warehouse=" + no); + + // BP from EMail + sql = new StringBuffer ("UPDATE I_Order o " + + "SET (C_BPartner_ID,AD_User_ID)=(SELECT C_BPartner_ID,AD_User_ID FROM AD_User u" + + " WHERE o.EMail=u.EMail AND o.AD_Client_ID=u.AD_Client_ID AND u.C_BPartner_ID IS NOT NULL) " + + "WHERE C_BPartner_ID IS NULL AND EMail IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set BP from EMail=" + no); + // BP from ContactName + sql = new StringBuffer ("UPDATE I_Order o " + + "SET (C_BPartner_ID,AD_User_ID)=(SELECT C_BPartner_ID,AD_User_ID FROM AD_User u" + + " WHERE o.ContactName=u.Name AND o.AD_Client_ID=u.AD_Client_ID AND u.C_BPartner_ID IS NOT NULL) " + + "WHERE C_BPartner_ID IS NULL AND ContactName IS NOT NULL" + + " AND EXISTS (SELECT Name FROM AD_User u WHERE o.ContactName=u.Name AND o.AD_Client_ID=u.AD_Client_ID AND u.C_BPartner_ID IS NOT NULL GROUP BY Name HAVING COUNT(*)=1)" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set BP from ContactName=" + no); + // BP from Value + sql = new StringBuffer ("UPDATE I_Order o " + + "SET C_BPartner_ID=(SELECT C_BPartner_ID FROM C_BPartner bp" + + " WHERE o.BPartnerValue=bp.Value AND o.AD_Client_ID=bp.AD_Client_ID AND ROWNUM=1) " + + "WHERE C_BPartner_ID IS NULL AND BPartnerValue IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set BP from Value=" + no); + // Default BP + sql = new StringBuffer ("UPDATE I_Order o " + + "SET C_BPartner_ID=(SELECT C_BPartnerCashTrx_ID FROM AD_ClientInfo c" + + " WHERE o.AD_Client_ID=c.AD_Client_ID) " + + "WHERE C_BPartner_ID IS NULL AND BPartnerValue IS NULL AND Name IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Default BP=" + no); + + // Existing Location ? Exact Match + sql = new StringBuffer ("UPDATE I_Order o " + + "SET (BillTo_ID,C_BPartner_Location_ID)=(SELECT C_BPartner_Location_ID,C_BPartner_Location_ID" + + " FROM C_BPartner_Location bpl INNER JOIN C_Location l ON (bpl.C_Location_ID=l.C_Location_ID)" + + " WHERE o.C_BPartner_ID=bpl.C_BPartner_ID AND bpl.AD_Client_ID=o.AD_Client_ID" + + " AND DUMP(o.Address1)=DUMP(l.Address1) AND DUMP(o.Address2)=DUMP(l.Address2)" + + " AND DUMP(o.City)=DUMP(l.City) AND DUMP(o.Postal)=DUMP(l.Postal)" + + " AND DUMP(o.C_Region_ID)=DUMP(l.C_Region_ID) AND DUMP(o.C_Country_ID)=DUMP(l.C_Country_ID)) " + + "WHERE C_BPartner_ID IS NOT NULL AND C_BPartner_Location_ID IS NULL" + + " AND I_IsImported='N'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Found Location=" + no); + // Set Bill Location from BPartner + sql = new StringBuffer ("UPDATE I_Order o " + + "SET BillTo_ID=(SELECT C_BPartner_Location_ID FROM C_BPartner_Location l" + + " WHERE l.C_BPartner_ID=o.C_BPartner_ID AND o.AD_Client_ID=l.AD_Client_ID" + + " AND ((l.IsBillTo='Y' AND o.IsSOTrx='Y') OR (l.IsPayFrom='Y' AND o.IsSOTrx='N'))" + + " AND ROWNUM=1) " + + "WHERE C_BPartner_ID IS NOT NULL AND BillTo_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set BP BillTo from BP=" + no); + // Set Location from BPartner + sql = new StringBuffer ("UPDATE I_Order o " + + "SET C_BPartner_Location_ID=(SELECT C_BPartner_Location_ID FROM C_BPartner_Location l" + + " WHERE l.C_BPartner_ID=o.C_BPartner_ID AND o.AD_Client_ID=l.AD_Client_ID" + + " AND ((l.IsShipTo='Y' AND o.IsSOTrx='Y') OR o.IsSOTrx='N')" + + " AND ROWNUM=1) " + + "WHERE C_BPartner_ID IS NOT NULL AND C_BPartner_Location_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set BP Location from BP=" + no); + // + sql = new StringBuffer ("UPDATE I_Order " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No BP Location, ' " + + "WHERE C_BPartner_ID IS NOT NULL AND (BillTo_ID IS NULL OR C_BPartner_Location_ID IS NULL)" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("No BP Location=" + no); + + // Set Country + /** + sql = new StringBuffer ("UPDATE I_Order o " + + "SET CountryCode=(SELECT CountryCode FROM C_Country c WHERE c.IsDefault='Y'" + + " AND c.AD_Client_ID IN (0, o.AD_Client_ID) AND ROWNUM=1) " + + "WHERE C_BPartner_ID IS NULL AND CountryCode IS NULL AND C_Country_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Country Default=" + no); + **/ + sql = new StringBuffer ("UPDATE I_Order o " + + "SET C_Country_ID=(SELECT C_Country_ID FROM C_Country c" + + " WHERE o.CountryCode=c.CountryCode AND c.AD_Client_ID IN (0, o.AD_Client_ID)) " + + "WHERE C_BPartner_ID IS NULL AND C_Country_ID IS NULL AND CountryCode IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Country=" + no); + // + sql = new StringBuffer ("UPDATE I_Order " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Country, ' " + + "WHERE C_BPartner_ID IS NULL AND C_Country_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Country=" + no); + + // Set Region + sql = new StringBuffer ("UPDATE I_Order o " + + "Set RegionName=(SELECT Name FROM C_Region r" + + " WHERE r.IsDefault='Y' AND r.C_Country_ID=o.C_Country_ID" + + " AND r.AD_Client_ID IN (0, o.AD_Client_ID) AND ROWNUM=1) " + + "WHERE C_BPartner_ID IS NULL AND C_Region_ID IS NULL AND RegionName IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Region Default=" + no); + // + sql = new StringBuffer ("UPDATE I_Order o " + + "Set C_Region_ID=(SELECT C_Region_ID FROM C_Region r" + + " WHERE r.Name=o.RegionName AND r.C_Country_ID=o.C_Country_ID" + + " AND r.AD_Client_ID IN (0, o.AD_Client_ID)) " + + "WHERE C_BPartner_ID IS NULL AND C_Region_ID IS NULL AND RegionName IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Region=" + no); + // + sql = new StringBuffer ("UPDATE I_Order o " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Region, ' " + + "WHERE C_BPartner_ID IS NULL AND C_Region_ID IS NULL " + + " AND EXISTS (SELECT * FROM C_Country c" + + " WHERE c.C_Country_ID=o.C_Country_ID AND c.HasRegion='Y')" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Region=" + no); + + // Product + sql = new StringBuffer ("UPDATE I_Order o " + + "SET M_Product_ID=(SELECT M_Product_ID FROM M_Product p" + + " WHERE o.ProductValue=p.Value AND o.AD_Client_ID=p.AD_Client_ID AND ROWNUM=1) " + + "WHERE M_Product_ID IS NULL AND ProductValue IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Product from Value=" + no); + sql = new StringBuffer ("UPDATE I_Order o " + + "SET M_Product_ID=(SELECT M_Product_ID FROM M_Product p" + + " WHERE o.UPC=p.UPC AND o.AD_Client_ID=p.AD_Client_ID AND ROWNUM=1) " + + "WHERE M_Product_ID IS NULL AND UPC IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Product from UPC=" + no); + sql = new StringBuffer ("UPDATE I_Order o " + + "SET M_Product_ID=(SELECT M_Product_ID FROM M_Product p" + + " WHERE o.SKU=p.SKU AND o.AD_Client_ID=p.AD_Client_ID AND ROWNUM=1) " + + "WHERE M_Product_ID IS NULL AND SKU IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Product fom SKU=" + no); + sql = new StringBuffer ("UPDATE I_Order " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Product, ' " + + "WHERE M_Product_ID IS NULL AND (ProductValue IS NOT NULL OR UPC IS NOT NULL OR SKU IS NOT NULL)" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Product=" + no); + + // Tax + sql = new StringBuffer ("UPDATE I_Order o " + + "SET C_Tax_ID=(SELECT C_Tax_ID FROM C_Tax t" + + " WHERE o.TaxIndicator=t.TaxIndicator AND o.AD_Client_ID=t.AD_Client_ID AND ROWNUM=1) " + + "WHERE C_Tax_ID IS NULL AND TaxIndicator IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Tax=" + no); + sql = new StringBuffer ("UPDATE I_Order " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Tax, ' " + + "WHERE C_Tax_ID IS NULL AND TaxIndicator IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Tax=" + no); + + commit(); + + // -- New BPartner --------------------------------------------------- + + // Go through Order Records w/o C_BPartner_ID + sql = new StringBuffer ("SELECT * FROM I_Order " + + "WHERE I_IsImported='N' AND C_BPartner_ID IS NULL").append (clientCheck); + try + { + PreparedStatement pstmt = DB.prepareStatement (sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + X_I_Order imp = new X_I_Order (getCtx (), rs, get_TrxName()); + if (imp.getBPartnerValue () == null) + { + if (imp.getEMail () != null) + imp.setBPartnerValue (imp.getEMail ()); + else if (imp.getName () != null) + imp.setBPartnerValue (imp.getName ()); + else + continue; + } + if (imp.getName () == null) + { + if (imp.getContactName () != null) + imp.setName (imp.getContactName ()); + else + imp.setName (imp.getBPartnerValue ()); + } + // BPartner + MBPartner bp = MBPartner.get (getCtx(), imp.getBPartnerValue()); + if (bp == null) + { + bp = new MBPartner (getCtx (), -1, get_TrxName()); + bp.setClientOrg (imp.getAD_Client_ID (), imp.getAD_Org_ID ()); + bp.setValue (imp.getBPartnerValue ()); + bp.setName (imp.getName ()); + if (!bp.save ()) + continue; + } + imp.setC_BPartner_ID (bp.getC_BPartner_ID ()); + + // BP Location + MBPartnerLocation bpl = null; + MBPartnerLocation[] bpls = bp.getLocations(true); + for (int i = 0; bpl == null && i < bpls.length; i++) + { + if (imp.getC_BPartner_Location_ID() == bpls[i].getC_BPartner_Location_ID()) + bpl = bpls[i]; + // Same Location ID + else if (imp.getC_Location_ID() == bpls[i].getC_Location_ID()) + bpl = bpls[i]; + // Same Location Info + else if (imp.getC_Location_ID() == 0) + { + MLocation loc = bpl.getLocation(false); + if (loc.equals(imp.getC_Country_ID(), imp.getC_Region_ID(), + imp.getPostal(), "", imp.getCity(), + imp.getAddress1(), imp.getAddress2())) + bpl = bpls[i]; + } + } + if (bpl == null) + { + // New Location + MLocation loc = new MLocation (getCtx (), 0, get_TrxName()); + loc.setAddress1 (imp.getAddress1 ()); + loc.setAddress2 (imp.getAddress2 ()); + loc.setCity (imp.getCity ()); + loc.setPostal (imp.getPostal ()); + if (imp.getC_Region_ID () != 0) + loc.setC_Region_ID (imp.getC_Region_ID ()); + loc.setC_Country_ID (imp.getC_Country_ID ()); + if (!loc.save ()) + continue; + // + bpl = new MBPartnerLocation (bp); + bpl.setC_Location_ID (imp.getC_Location_ID ()); + if (!bpl.save ()) + continue; + } + imp.setC_Location_ID (bpl.getC_Location_ID ()); + imp.setBillTo_ID (bpl.getC_BPartner_Location_ID ()); + imp.setC_BPartner_Location_ID (bpl.getC_BPartner_Location_ID ()); + + // User/Contact + if (imp.getContactName () != null + || imp.getEMail () != null + || imp.getPhone () != null) + { + MUser[] users = bp.getContacts(true); + MUser user = null; + for (int i = 0; user == null && i < users.length; i++) + { + String name = users[i].getName(); + if (name.equals(imp.getContactName()) + || name.equals(imp.getName())) + { + user = users[i]; + imp.setAD_User_ID (user.getAD_User_ID ()); + } + } + if (user == null) + { + user = new MUser (bp); + if (imp.getContactName () == null) + user.setName (imp.getName ()); + else + user.setName (imp.getContactName ()); + user.setEMail (imp.getEMail ()); + user.setPhone (imp.getPhone ()); + if (user.save ()) + imp.setAD_User_ID (user.getAD_User_ID ()); + } + } + imp.save (); + } // for all new BPartners + rs.close (); + pstmt.close (); + // + } + catch (SQLException e) + { + log.log(Level.SEVERE, "BP - " + sql.toString(), e); + } + sql = new StringBuffer ("UPDATE I_Order " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No BPartner, ' " + + "WHERE C_BPartner_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("No BPartner=" + no); + + commit(); + + // -- New Orders ----------------------------------------------------- + + int noInsert = 0; + int noInsertLine = 0; + + // Go through Order Records w/o + sql = new StringBuffer ("SELECT * FROM I_Order " + + "WHERE I_IsImported='N'").append (clientCheck) + .append(" ORDER BY C_BPartner_ID, BillTo_ID, C_BPartner_Location_ID, I_Order_ID"); + try + { + PreparedStatement pstmt = DB.prepareStatement (sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery (); + // + int oldC_BPartner_ID = 0; + int oldBillTo_ID = 0; + int oldC_BPartner_Location_ID = 0; + String oldDocumentNo = ""; + // + MOrder order = null; + int lineNo = 0; + while (rs.next ()) + { + X_I_Order imp = new X_I_Order (getCtx (), rs, get_TrxName()); + String cmpDocumentNo = imp.getDocumentNo(); + if (cmpDocumentNo == null) + cmpDocumentNo = ""; + // New Order + if (oldC_BPartner_ID != imp.getC_BPartner_ID() + || oldC_BPartner_Location_ID != imp.getC_BPartner_Location_ID() + || oldBillTo_ID != imp.getBillTo_ID() + || !oldDocumentNo.equals(cmpDocumentNo)) + { + if (order != null) + { + if (m_docAction != null && m_docAction.length() > 0) + { + order.setDocAction(m_docAction); + order.processIt (m_docAction); + } + order.save(); + } + oldC_BPartner_ID = imp.getC_BPartner_ID(); + oldC_BPartner_Location_ID = imp.getC_BPartner_Location_ID(); + oldBillTo_ID = imp.getBillTo_ID(); + oldDocumentNo = imp.getDocumentNo(); + if (oldDocumentNo == null) + oldDocumentNo = ""; + // + order = new MOrder (getCtx(), 0, get_TrxName()); + order.setClientOrg (imp.getAD_Client_ID(), imp.getAD_Org_ID()); + order.setC_DocTypeTarget_ID(imp.getC_DocType_ID()); + order.setIsSOTrx(imp.isSOTrx()); + if (imp.getDocumentNo() != null) + order.setDocumentNo(imp.getDocumentNo()); + // Ship Partner + order.setC_BPartner_ID(imp.getC_BPartner_ID()); + order.setC_BPartner_Location_ID(imp.getC_BPartner_Location_ID()); + if (imp.getAD_User_ID() != 0) + order.setAD_User_ID(imp.getAD_User_ID()); + // Bill Partner + order.setBill_BPartner_ID(imp.getC_BPartner_ID()); + order.setBill_Location_ID(imp.getBillTo_ID()); + // + if (imp.getDescription() != null) + order.setDescription(imp.getDescription()); + order.setC_PaymentTerm_ID(imp.getC_PaymentTerm_ID()); + order.setM_PriceList_ID(imp.getM_PriceList_ID()); + order.setM_Warehouse_ID(imp.getM_Warehouse_ID()); + if (imp.getM_Shipper_ID() != 0) + order.setM_Shipper_ID(imp.getM_Shipper_ID()); + // SalesRep from Import or the person running the import + if (imp.getSalesRep_ID() != 0) + order.setSalesRep_ID(imp.getSalesRep_ID()); + if (order.getSalesRep_ID() == 0) + order.setSalesRep_ID(getAD_User_ID()); + // + if (imp.getAD_OrgTrx_ID() != 0) + order.setAD_OrgTrx_ID(imp.getAD_OrgTrx_ID()); + if (imp.getC_Activity_ID() != 0) + order.setC_Activity_ID(imp.getC_Activity_ID()); + if (imp.getC_Campaign_ID() != 0) + order.setC_Campaign_ID(imp.getC_Campaign_ID()); + if (imp.getC_Project_ID() != 0) + order.setC_Project_ID(imp.getC_Project_ID()); + // + if (imp.getDateOrdered() != null) + order.setDateOrdered(imp.getDateOrdered()); + if (imp.getDateAcct() != null) + order.setDateAcct(imp.getDateAcct()); + // + order.save(); + noInsert++; + lineNo = 10; + } + imp.setC_Order_ID(order.getC_Order_ID()); + // New OrderLine + MOrderLine line = new MOrderLine (order); + line.setLine(lineNo); + lineNo += 10; + if (imp.getM_Product_ID() != 0) + line.setM_Product_ID(imp.getM_Product_ID(), true); + line.setQty(imp.getQtyOrdered()); + line.setPrice(); + if (imp.getPriceActual().compareTo(Env.ZERO) != 0) + line.setPrice(imp.getPriceActual()); + if (imp.getC_Tax_ID() != 0) + line.setC_Tax_ID(imp.getC_Tax_ID()); + else + { + line.setTax(); + imp.setC_Tax_ID(line.getC_Tax_ID()); + } + if (imp.getFreightAmt() != null) + line.setFreightAmt(imp.getFreightAmt()); + if (imp.getLineDescription() != null) + line.setDescription(imp.getLineDescription()); + line.save(); + imp.setC_OrderLine_ID(line.getC_OrderLine_ID()); + imp.setI_IsImported(true); + imp.setProcessed(true); + // + if (imp.save()) + noInsertLine++; + } + if (order != null) + { + if (m_docAction != null && m_docAction.length() > 0) + { + order.setDocAction(m_docAction); + order.processIt (m_docAction); + } + order.save(); + } + rs.close(); + pstmt.close(); + } + catch (Exception e) + { + log.log(Level.SEVERE, "Order - " + sql.toString(), e); + } + + // Set Error to indicator to not imported + sql = new StringBuffer ("UPDATE I_Order " + + "SET I_IsImported='N', Updated=SysDate " + + "WHERE I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog (0, null, new BigDecimal (no), "@Errors@"); + // + addLog (0, null, new BigDecimal (noInsert), "@C_Order_ID@: @Inserted@"); + addLog (0, null, new BigDecimal (noInsertLine), "@C_OrderLine_ID@: @Inserted@"); + return "#" + noInsert + "/" + noInsertLine; + } // doIt + +} // ImportOrder diff --git a/base/src/org/compiere/process/ImportPayment.java b/base/src/org/compiere/process/ImportPayment.java new file mode 100644 index 0000000000..e5e949afad --- /dev/null +++ b/base/src/org/compiere/process/ImportPayment.java @@ -0,0 +1,519 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Import Payments + * + * @author Jorg Janke + * @version $Id: ImportPayment.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ImportPayment extends SvrProcess +{ + /** Organization to be imported to */ + private int p_AD_Org_ID = 0; + /** Default Bank Account */ + private int p_C_BankAccount_ID = 0; + /** Delete old Imported */ + private boolean p_deleteOldImported = false; + + /** Properties */ + private Properties m_ctx; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (name.equals("AD_Org_ID")) + p_AD_Org_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_BankAccount_ID")) + p_C_BankAccount_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("DeleteOldImported")) + p_deleteOldImported = "Y".equals(para[i].getParameter()); + // else if (name.equals("DocAction")) + // m_docAction = (String)para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + m_ctx = Env.getCtx(); + } // prepare + + /** + * Proccess + * @return info + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info("C_BankAccount_ID" + p_C_BankAccount_ID); + MBankAccount ba = MBankAccount.get(getCtx(), p_C_BankAccount_ID); + if (p_C_BankAccount_ID == 0 || ba.get_ID() != p_C_BankAccount_ID) + throw new AdempiereUserError("@NotFound@ @C_BankAccount_ID@ - " + p_C_BankAccount_ID); + if (p_AD_Org_ID != ba.getAD_Org_ID() && ba.getAD_Org_ID() != 0) + p_AD_Org_ID = ba.getAD_Org_ID(); + log.info("AD_Org_ID=" + p_AD_Org_ID); + + StringBuffer sql = null; + int no = 0; + String clientCheck = " AND AD_Client_ID=" + ba.getAD_Client_ID(); + + // **** Prepare **** + + // Delete Old Imported + if (p_deleteOldImported) + { + sql = new StringBuffer ("DELETE I_Payment " + + "WHERE I_IsImported='Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Delete Old Impored =" + no); + } + + // Set Client, Org, IsActive, Created/Updated + sql = new StringBuffer ("UPDATE I_Payment " + + "SET AD_Client_ID = COALESCE (AD_Client_ID,").append (ba.getAD_Client_ID()).append (")," + + " AD_Org_ID = COALESCE (AD_Org_ID,").append (p_AD_Org_ID).append ("),"); + sql.append(" IsActive = COALESCE (IsActive, 'Y')," + + " Created = COALESCE (Created, SysDate)," + + " CreatedBy = COALESCE (CreatedBy, 0)," + + " Updated = COALESCE (Updated, SysDate)," + + " UpdatedBy = COALESCE (UpdatedBy, 0)," + + " I_ErrorMsg = NULL," + + " I_IsImported = 'N' " + + "WHERE I_IsImported<>'Y' OR I_IsImported IS NULL OR AD_Client_ID IS NULL OR AD_Org_ID IS NULL OR AD_Client_ID=0 OR AD_Org_ID=0"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info ("Reset=" + no); + + sql = new StringBuffer ("UPDATE I_Payment o " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Org, '" + + "WHERE (AD_Org_ID IS NULL OR AD_Org_ID=0" + + " OR EXISTS (SELECT * FROM AD_Org oo WHERE o.AD_Org_ID=oo.AD_Org_ID AND (oo.IsSummary='Y' OR oo.IsActive='N')))" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid Org=" + no); + + // Set Bank Account + sql = new StringBuffer("UPDATE I_Payment i " + + "SET C_BankAccount_ID=" + + "( " + + " SELECT C_BankAccount_ID " + + " FROM C_BankAccount a, C_Bank b " + + " WHERE b.IsOwnBank='Y' " + + " AND a.AD_Client_ID=i.AD_Client_ID " + + " AND a.C_Bank_ID=b.C_Bank_ID " + + " AND a.AccountNo=i.BankAccountNo " + + " AND b.RoutingNo=i.RoutingNo " + + " OR b.SwiftCode=i.RoutingNo " + + ") " + + "WHERE i.C_BankAccount_ID IS NULL " + + "AND i.I_IsImported<>'Y' " + + "OR i.I_IsImported IS NULL").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Bank Account (With Routing No)=" + no); + // + sql = new StringBuffer("UPDATE I_Payment i " + + "SET C_BankAccount_ID=" + + "( " + + " SELECT C_BankAccount_ID " + + " FROM C_BankAccount a, C_Bank b " + + " WHERE b.IsOwnBank='Y' " + + " AND a.C_Bank_ID=b.C_Bank_ID " + + " AND a.AccountNo=i.BankAccountNo " + + " AND a.AD_Client_ID=i.AD_Client_ID " + + ") " + + "WHERE i.C_BankAccount_ID IS NULL " + + "AND i.I_isImported<>'Y' " + + "OR i.I_isImported IS NULL").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Bank Account (Without Routing No)=" + no); + // + sql = new StringBuffer("UPDATE I_Payment i " + + "SET C_BankAccount_ID=(SELECT C_BankAccount_ID FROM C_BankAccount a WHERE a.C_BankAccount_ID=").append(p_C_BankAccount_ID); + sql.append(" and a.AD_Client_ID=i.AD_Client_ID) " + + "WHERE i.C_BankAccount_ID IS NULL " + + "AND i.BankAccountNo IS NULL " + + "AND i.I_isImported<>'Y' " + + "OR i.I_isImported IS NULL").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Bank Account=" + no); + // + sql = new StringBuffer("UPDATE I_Payment " + + "SET I_isImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid Bank Account, ' " + + "WHERE C_BankAccount_ID IS NULL " + + "AND I_isImported<>'Y' " + + "OR I_isImported IS NULL").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning("Invalid Bank Account=" + no); + + // Set Currency + sql = new StringBuffer ("UPDATE I_Payment i " + + "SET C_Currency_ID=(SELECT C_Currency_ID FROM C_Currency c" + + " WHERE i.ISO_Code=c.ISO_Code AND c.AD_Client_ID IN (0,i.AD_Client_ID)) " + + "WHERE C_Currency_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Set Currency=" + no); + // + sql = new StringBuffer("UPDATE I_Payment i " + + "SET i.C_Currency_ID=(SELECT C_Currency_ID FROM C_BankAccount WHERE C_BankAccount_ID=i.C_BankAccount_ID) " + + "WHERE i.C_Currency_ID IS NULL " + + "AND i.ISO_Code IS NULL").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Set Currency=" + no); + // + sql = new StringBuffer ("UPDATE I_Payment " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No Currency,' " + + "WHERE C_Currency_ID IS NULL " + + "AND I_IsImported<>'E' " + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning("No Currency=" + no); + + // Set Amount + sql = new StringBuffer("UPDATE I_Payment " + + "SET ChargeAmt=0 " + + "WHERE ChargeAmt IS NULL " + + "AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Charge Amount=" + no); + // + sql = new StringBuffer("UPDATE I_Payment " + + "SET TaxAmt=0 " + + "WHERE TaxAmt IS NULL " + + "AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Tax Amount=" + no); + // + sql = new StringBuffer("UPDATE I_Payment " + + "SET WriteOffAmt=0 " + + "WHERE WriteOffAmt IS NULL " + + "AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("WriteOff Amount=" + no); + // + sql = new StringBuffer("UPDATE I_Payment " + + "SET DiscountAmt=0 " + + "WHERE DiscountAmt IS NULL " + + "AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Discount Amount=" + no); + // + + // Set Date + sql = new StringBuffer("UPDATE I_Payment " + + "SET DateTrx=Created " + + "WHERE DateTrx IS NULL " + + "AND I_isImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Trx Date=" + no); + + sql = new StringBuffer("UPDATE I_Payment " + + "SET DateAcct=DateTrx " + + "WHERE DateAcct IS NULL " + + "AND I_isImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Acct Date=" + no); + + // Invoice + sql = new StringBuffer ("UPDATE I_Payment i " + + "SET C_Invoice_ID=(SELECT C_Invoice_ID FROM C_Invoice ii" + + " WHERE i.InvoiceDocumentNo=ii.DocumentNo AND i.AD_Client_ID=ii.AD_Client_ID AND ROWNUM=1) " + + "WHERE C_Invoice_ID IS NULL AND InvoiceDocumentNo IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.fine("Set Invoice from DocumentNo=" + no); + + // BPartner + sql = new StringBuffer ("UPDATE I_Payment i " + + "SET C_BPartner_ID=(SELECT C_BPartner_ID FROM C_BPartner bp" + + " WHERE i.BPartnerValue=bp.Value AND i.AD_Client_ID=bp.AD_Client_ID AND ROWNUM=1) " + + "WHERE C_BPartner_ID IS NULL AND BPartnerValue IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.fine("Set BP from Value=" + no); + + sql = new StringBuffer ("UPDATE I_Payment i " + + "SET C_BPartner_ID=(SELECT C_BPartner_ID FROM C_Invoice ii" + + " WHERE i.C_Invoice_ID=ii.C_Invoice_ID AND i.AD_Client_ID=ii.AD_Client_ID AND ROWNUM=1) " + + "WHERE C_BPartner_ID IS NULL AND C_Invoice_ID IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.fine("Set BP from Invoice=" + no); + + sql = new StringBuffer ("UPDATE I_Payment " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No BPartner,' " + + "WHERE C_BPartner_ID IS NULL " + + "AND I_IsImported<>'E' " + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning("No BPartner=" + no); + + + // Check Payment<->Invoice combination + sql = new StringBuffer("UPDATE I_Payment " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'Err=Invalid Payment<->Invoice, ' " + + "WHERE I_Payment_ID IN " + + "(SELECT I_Payment_ID " + + "FROM I_Payment i" + + " INNER JOIN C_Payment p ON (i.C_Payment_ID=p.C_Payment_ID) " + + "WHERE i.C_Invoice_ID IS NOT NULL " + + " AND p.C_Invoice_ID IS NOT NULL " + + " AND p.C_Invoice_ID<>i.C_Invoice_ID) ") + .append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Payment<->Invoice Mismatch=" + no); + + // Check Payment<->BPartner combination + sql = new StringBuffer("UPDATE I_Payment " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'Err=Invalid Payment<->BPartner, ' " + + "WHERE I_Payment_ID IN " + + "(SELECT I_Payment_ID " + + "FROM I_Payment i" + + " INNER JOIN C_Payment p ON (i.C_Payment_ID=p.C_Payment_ID) " + + "WHERE i.C_BPartner_ID IS NOT NULL " + + " AND p.C_BPartner_ID IS NOT NULL " + + " AND p.C_BPartner_ID<>i.C_BPartner_ID) ") + .append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Payment<->BPartner Mismatch=" + no); + + // Check Invoice<->BPartner combination + sql = new StringBuffer("UPDATE I_Payment " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'Err=Invalid Invoice<->BPartner, ' " + + "WHERE I_Payment_ID IN " + + "(SELECT I_Payment_ID " + + "FROM I_Payment i" + + " INNER JOIN C_Invoice v ON (i.C_Invoice_ID=v.C_Invoice_ID) " + + "WHERE i.C_BPartner_ID IS NOT NULL " + + " AND v.C_BPartner_ID IS NOT NULL " + + " AND v.C_BPartner_ID<>i.C_BPartner_ID) ") + .append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Invoice<->BPartner Mismatch=" + no); + + // Check Invoice.BPartner<->Payment.BPartner combination + sql = new StringBuffer("UPDATE I_Payment " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'Err=Invalid Invoice.BPartner<->Payment.BPartner, ' " + + "WHERE I_Payment_ID IN " + + "(SELECT I_Payment_ID " + + "FROM I_Payment i" + + " INNER JOIN C_Invoice v ON (i.C_Invoice_ID=v.C_Invoice_ID)" + + " INNER JOIN C_Payment p ON (i.C_Payment_ID=p.C_Payment_ID) " + + "WHERE p.C_Invoice_ID<>v.C_Invoice_ID" + + " AND v.C_BPartner_ID<>p.C_BPartner_ID) ") + .append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("Invoice.BPartner<->Payment.BPartner Mismatch=" + no); + + // TrxType + sql = new StringBuffer("UPDATE I_Payment " + + "SET TrxType='S' " // MPayment.TRXTYPE_Sales + + "WHERE TrxType IS NULL " + + "AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("TrxType Default=" + no); + + // TenderType + sql = new StringBuffer("UPDATE I_Payment " + + "SET TenderType='K' " // MPayment.TENDERTYPE_Check + + "WHERE TenderType IS NULL " + + "AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.info("TenderType Default=" + no); + + // Document Type + sql = new StringBuffer ("UPDATE I_Payment i " + + "SET C_DocType_ID=(SELECT C_DocType_ID FROM C_DocType d WHERE d.Name=i.DocTypeName" + + " AND d.DocBaseType IN ('ARR','APP') AND i.AD_Client_ID=d.AD_Client_ID) " + + "WHERE C_DocType_ID IS NULL AND DocTypeName IS NOT NULL AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.fine("Set DocType=" + no); + sql = new StringBuffer ("UPDATE I_Payment " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid DocTypeName, ' " + + "WHERE C_DocType_ID IS NULL AND DocTypeName IS NOT NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("Invalid DocTypeName=" + no); + sql = new StringBuffer ("UPDATE I_Payment " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No DocType, ' " + + "WHERE C_DocType_ID IS NULL" + + " AND I_IsImported<>'Y'").append (clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning ("No DocType=" + no); + + commit(); + + //Import Bank Statement + sql = new StringBuffer("SELECT * FROM I_Payment" + + " WHERE I_IsImported='N'" + + " ORDER BY C_BankAccount_ID, CheckNo, DateTrx, R_AuthCode"); + + MBankAccount account = null; + PreparedStatement pstmt = null; + int lineNo = 10; + int noInsert = 0; + int noInsertLine = 0; + try + { + pstmt = DB.prepareStatement(sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + + while (rs.next()) + { + X_I_Payment imp = new X_I_Payment(m_ctx, rs, get_TrxName()); + // Get the bank account + if (account == null || account.getC_BankAccount_ID() != imp.getC_BankAccount_ID()) + { + account = MBankAccount.get (m_ctx, imp.getC_BankAccount_ID()); + log.info("New Account=" + account.getAccountNo()); + } + + // New Payment + MPayment payment = new MPayment (m_ctx, 0, get_TrxName()); + payment.setAD_Org_ID(imp.getAD_Org_ID()); + payment.setDocumentNo(imp.getDocumentNo()); + payment.setPONum(imp.getPONum()); + + payment.setTrxType(imp.getTrxType()); + payment.setTenderType(imp.getTenderType()); + + payment.setC_BankAccount_ID(imp.getC_BankAccount_ID()); + payment.setRoutingNo(imp.getRoutingNo()); + payment.setAccountNo(imp.getAccountNo()); + payment.setCheckNo(imp.getCheckNo()); + payment.setMicr(imp.getMicr()); + + if (imp.getCreditCardType() != null) + payment.setCreditCardType(imp.getCreditCardType()); + payment.setCreditCardNumber(imp.getCreditCardNumber()); + if (imp.getCreditCardExpMM() != 0) + payment.setCreditCardExpMM(imp.getCreditCardExpMM()); + if (imp.getCreditCardExpYY() != 0) + payment.setCreditCardExpYY(imp.getCreditCardExpYY()); + payment.setCreditCardVV(imp.getCreditCardVV()); + payment.setSwipe(imp.getSwipe()); + + payment.setDateAcct(imp.getDateTrx()); + payment.setDateTrx(imp.getDateTrx()); + // payment.setDescription(imp.getDescription()); + // + payment.setC_BPartner_ID(imp.getC_BPartner_ID()); + payment.setC_Invoice_ID(imp.getC_Invoice_ID()); + payment.setC_DocType_ID(imp.getC_DocType_ID()); + payment.setC_Currency_ID(imp.getC_Currency_ID()); + // payment.setC_ConversionType_ID(imp.getC_ConversionType_ID()); + payment.setC_Charge_ID(imp.getC_Charge_ID()); + payment.setChargeAmt(imp.getChargeAmt()); + payment.setTaxAmt(imp.getTaxAmt()); + + payment.setPayAmt(imp.getPayAmt()); + payment.setWriteOffAmt(imp.getWriteOffAmt()); + payment.setDiscountAmt(imp.getDiscountAmt()); + payment.setWriteOffAmt(imp.getWriteOffAmt()); + + // Copy statement line reference data + payment.setA_City(imp.getA_City()); + payment.setA_Country(imp.getA_Country()); + payment.setA_EMail(imp.getA_EMail()); + payment.setA_Ident_DL(imp.getA_Ident_DL()); + payment.setA_Ident_SSN(imp.getA_Ident_SSN()); + payment.setA_Name(imp.getA_Name()); + payment.setA_State(imp.getA_State()); + payment.setA_Street(imp.getA_Street()); + payment.setA_Zip(imp.getA_Zip()); + payment.setR_AuthCode(imp.getR_AuthCode()); + payment.setR_Info(imp.getR_Info()); + payment.setR_PnRef(imp.getR_PnRef()); + payment.setR_RespMsg(imp.getR_RespMsg()); + payment.setR_Result(imp.getR_Result()); + payment.setOrig_TrxID(imp.getOrig_TrxID()); + payment.setVoiceAuthCode(imp.getVoiceAuthCode()); + + // Save patment + if (payment.save()) + { + imp.setC_Payment_ID(payment.getC_Payment_ID()); + imp.setI_IsImported(true); + imp.setProcessed(true); + imp.save(); + noInsert++; + } + + } + + // Close database connection + rs.close(); + pstmt.close(); + rs = null; + pstmt = null; + + } + catch(Exception e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + + // Set Error to indicator to not imported + sql = new StringBuffer ("UPDATE I_Payment " + + "SET I_IsImported='N', Updated=SysDate " + + "WHERE I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog (0, null, new BigDecimal (no), "@Errors@"); + // + addLog (0, null, new BigDecimal (noInsert), "@C_Payment_ID@: @Inserted@"); + return ""; + } // doIt + +} // ImportPayment diff --git a/base/src/org/compiere/process/ImportProduct.java b/base/src/org/compiere/process/ImportProduct.java new file mode 100644 index 0000000000..31d6c316a0 --- /dev/null +++ b/base/src/org/compiere/process/ImportProduct.java @@ -0,0 +1,621 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Import Products from I_Product + * + * @author Jorg Janke + * @version $Id: ImportProduct.java,v 1.3 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ImportProduct extends SvrProcess +{ + /** Client to be imported to */ + private int m_AD_Client_ID = 0; + /** Delete old Imported */ + private boolean m_deleteOldImported = false; + + /** Organization to be imported to */ + private int m_AD_Org_ID = 0; + /** Effective */ + private Timestamp m_DateValue = null; + /** Pricelist to Update */ + private int p_M_PriceList_Version_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (name.equals("AD_Client_ID")) + m_AD_Client_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("DeleteOldImported")) + m_deleteOldImported = "Y".equals(para[i].getParameter()); + else if (name.equals("M_PriceList_Version_ID")) + p_M_PriceList_Version_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + if (m_DateValue == null) + m_DateValue = new Timestamp (System.currentTimeMillis()); + } // prepare + + + /** + * Perrform process. + * @return Message + * @throws Exception + */ + protected String doIt() throws java.lang.Exception + { + StringBuffer sql = null; + int no = 0; + String clientCheck = " AND AD_Client_ID=" + m_AD_Client_ID; + + // **** Prepare **** + + // Delete Old Imported + if (m_deleteOldImported) + { + sql = new StringBuffer ("DELETE I_Product " + + "WHERE I_IsImported='Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info("Delete Old Impored =" + no); + } + + // Set Client, Org, IaActive, Created/Updated, ProductType + sql = new StringBuffer ("UPDATE I_Product " + + "SET AD_Client_ID = COALESCE (AD_Client_ID, ").append(m_AD_Client_ID).append(")," + + " AD_Org_ID = COALESCE (AD_Org_ID, 0)," + + " IsActive = COALESCE (IsActive, 'Y')," + + " Created = COALESCE (Created, SysDate)," + + " CreatedBy = COALESCE (CreatedBy, 0)," + + " Updated = COALESCE (Updated, SysDate)," + + " UpdatedBy = COALESCE (UpdatedBy, 0)," + + " ProductType = COALESCE (ProductType, 'I')," + + " I_ErrorMsg = NULL," + + " I_IsImported = 'N' " + + "WHERE I_IsImported<>'Y' OR I_IsImported IS NULL"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info("Reset=" + no); + + // Set Optional BPartner + sql = new StringBuffer ("UPDATE I_Product i " + + "SET C_BPartner_ID=(SELECT C_BPartner_ID FROM C_BPartner p" + + " WHERE i.BPartner_Value=p.Value AND i.AD_Client_ID=p.AD_Client_ID) " + + "WHERE C_BPartner_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info("BPartner=" + no); + // + sql = new StringBuffer ("UPDATE I_Product " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid BPartner,' " + + "WHERE C_BPartner_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning("Invalid BPartner=" + no); + + + // **** Find Product + // EAN/UPC + sql = new StringBuffer ("UPDATE I_Product i " + + "SET M_Product_ID=(SELECT M_Product_ID FROM M_Product p" + + " WHERE i.UPC=p.UPC AND i.AD_Client_ID=p.AD_Client_ID) " + + "WHERE M_Product_ID IS NULL" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info("Product Existing UPC=" + no); + + // Value + sql = new StringBuffer ("UPDATE I_Product i " + + "SET M_Product_ID=(SELECT M_Product_ID FROM M_Product p" + + " WHERE i.Value=p.Value AND i.AD_Client_ID=p.AD_Client_ID) " + + "WHERE M_Product_ID IS NULL" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info("Product Existing Value=" + no); + + // BP ProdNo + sql = new StringBuffer ("UPDATE I_Product i " + + "SET M_Product_ID=(SELECT M_Product_ID FROM M_Product_po p" + + " WHERE i.C_BPartner_ID=p.C_BPartner_ID" + + " AND i.VendorProductNo=p.VendorProductNo AND i.AD_Client_ID=p.AD_Client_ID) " + + "WHERE M_Product_ID IS NULL" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info("Product Existing Vendor ProductNo=" + no); + + // Set Product Category + sql = new StringBuffer ("UPDATE I_Product " + + "SET ProductCategory_Value=(SELECT Value FROM M_Product_Category" + + " WHERE IsDefault='Y' AND AD_Client_ID=").append(m_AD_Client_ID).append(" AND ROWNUM=1) " + + "WHERE ProductCategory_Value IS NULL AND M_Product_Category_ID IS NULL" + + " AND M_Product_ID IS NULL" // set category only if product not found + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Category Default Value=" + no); + // + sql = new StringBuffer ("UPDATE I_Product i " + + "SET M_Product_Category_ID=(SELECT M_Product_Category_ID FROM M_Product_Category c" + + " WHERE i.ProductCategory_Value=c.Value AND i.AD_Client_ID=c.AD_Client_ID) " + + "WHERE ProductCategory_Value IS NOT NULL AND M_Product_Category_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info("Set Category=" + no); + + + // Copy From Product if Import does not have value + String[] strFields = new String[] {"Value","Name","Description","DocumentNote","Help", + "UPC","SKU","Classification","ProductType", + "Discontinued","DiscontinuedBy","ImageURL","DescriptionURL"}; + for (int i = 0; i < strFields.length; i++) + { + sql = new StringBuffer ("UPDATE I_PRODUCT i " + + "SET ").append(strFields[i]).append(" = (SELECT ").append(strFields[i]).append(" FROM M_Product p" + + " WHERE i.M_Product_ID=p.M_Product_ID AND i.AD_Client_ID=p.AD_Client_ID) " + + "WHERE M_Product_ID IS NOT NULL" + + " AND ").append(strFields[i]).append(" IS NULL" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.fine(strFields[i] + " - default from existing Product=" + no); + } + String[] numFields = new String[] {"C_UOM_ID","M_Product_Category_ID", + "Volume","Weight","ShelfWidth","ShelfHeight","ShelfDepth","UnitsPerPallet"}; + for (int i = 0; i < numFields.length; i++) + { + sql = new StringBuffer ("UPDATE I_PRODUCT i " + + "SET ").append(numFields[i]).append(" = (SELECT ").append(numFields[i]).append(" FROM M_Product p" + + " WHERE i.M_Product_ID=p.M_Product_ID AND i.AD_Client_ID=p.AD_Client_ID) " + + "WHERE M_Product_ID IS NOT NULL" + + " AND (").append(numFields[i]).append(" IS NULL OR ").append(numFields[i]).append("=0)" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.fine(numFields[i] + " default from existing Product=" + no); + } + + // Copy From Product_PO if Import does not have value + String[] strFieldsPO = new String[] {"UPC", + "PriceEffective","VendorProductNo","VendorCategory","Manufacturer", + "Discontinued","DiscontinuedBy"}; + for (int i = 0; i < strFieldsPO.length; i++) + { + sql = new StringBuffer ("UPDATE I_PRODUCT i " + + "SET ").append(strFieldsPO[i]).append(" = (SELECT ").append(strFieldsPO[i]) + .append(" FROM M_Product_PO p" + + " WHERE i.M_Product_ID=p.M_Product_ID AND i.C_BPartner_ID=p.C_BPartner_ID AND i.AD_Client_ID=p.AD_Client_ID) " + + "WHERE M_Product_ID IS NOT NULL AND C_BPartner_ID IS NOT NULL" + + " AND ").append(strFieldsPO[i]).append(" IS NULL" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.fine(strFieldsPO[i] + " default from existing Product PO=" + no); + } + String[] numFieldsPO = new String[] {"C_UOM_ID","C_Currency_ID", + "PriceList","PricePO","RoyaltyAmt", + "Order_Min","Order_Pack","CostPerOrder","DeliveryTime_Promised"}; + for (int i = 0; i < numFieldsPO.length; i++) + { + sql = new StringBuffer ("UPDATE I_PRODUCT i " + + "SET ").append(numFieldsPO[i]).append(" = (SELECT ").append(numFieldsPO[i]) + .append(" FROM M_Product_PO p" + + " WHERE i.M_Product_ID=p.M_Product_ID AND i.C_BPartner_ID=p.C_BPartner_ID AND i.AD_Client_ID=p.AD_Client_ID) " + + "WHERE M_Product_ID IS NOT NULL AND C_BPartner_ID IS NOT NULL" + + " AND (").append(numFieldsPO[i]).append(" IS NULL OR ").append(numFieldsPO[i]).append("=0)" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.fine(numFieldsPO[i] + " default from existing Product PO=" + no); + } + + // Invalid Category + sql = new StringBuffer ("UPDATE I_Product " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid ProdCategorty,' " + + "WHERE M_Product_Category_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning("Invalid Category=" + no); + + + // Set UOM (System/own) + sql = new StringBuffer ("UPDATE I_Product i " + + "SET X12DE355 = " + + "(SELECT X12DE355 FROM C_UOM u WHERE u.IsDefault='Y' AND u.AD_Client_ID IN (0,i.AD_Client_ID) AND ROWNUM=1) " + + "WHERE X12DE355 IS NULL AND C_UOM_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set UOM Default=" + no); + // + sql = new StringBuffer ("UPDATE I_Product i " + + "SET C_UOM_ID = (SELECT C_UOM_ID FROM C_UOM u WHERE u.X12DE355=i.X12DE355 AND u.AD_Client_ID IN (0,i.AD_Client_ID)) " + + "WHERE C_UOM_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info("Set UOM=" + no); + // + sql = new StringBuffer ("UPDATE I_Product " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid UOM, ' " + + "WHERE C_UOM_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning("Invalid UOM=" + no); + + + // Set Currency + sql = new StringBuffer ("UPDATE I_Product i " + + "SET ISO_Code=(SELECT ISO_Code FROM C_Currency c" + + " INNER JOIN C_AcctSchema a ON (a.C_Currency_ID=c.C_Currency_ID)" + + " INNER JOIN AD_ClientInfo ci ON (a.C_AcctSchema_ID=ci.C_AcctSchema1_ID)" + + " WHERE ci.AD_Client_ID=i.AD_Client_ID) " + + "WHERE C_Currency_ID IS NULL AND ISO_Code IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set Currency Default=" + no); + // + sql = new StringBuffer ("UPDATE I_Product i " + + "SET C_Currency_ID=(SELECT C_Currency_ID FROM C_Currency c" + + " WHERE i.ISO_Code=c.ISO_Code AND c.AD_Client_ID IN (0,i.AD_Client_ID)) " + + "WHERE C_Currency_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info("doIt- Set Currency=" + no); + // + sql = new StringBuffer ("UPDATE I_Product " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Currency,' " + + "WHERE C_Currency_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning("Invalid Currency=" + no); + + // Verify ProductType + sql = new StringBuffer ("UPDATE I_Product " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid ProductType,' " + + "WHERE ProductType NOT IN ('I','S')" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning("Invalid ProductType=" + no); + + // Unique UPC/Value + sql = new StringBuffer ("UPDATE I_Product i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Value not unique,' " + + "WHERE I_IsImported<>'Y'" + + " AND Value IN (SELECT Value FROM I_Product ii WHERE i.AD_Client_ID=ii.AD_Client_ID GROUP BY Value HAVING COUNT(*) > 1)").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning("Not Unique Value=" + no); + // + sql = new StringBuffer ("UPDATE I_Product i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=UPC not unique,' " + + "WHERE I_IsImported<>'Y'" + + " AND UPC IN (SELECT UPC FROM I_Product ii WHERE i.AD_Client_ID=ii.AD_Client_ID GROUP BY UPC HAVING COUNT(*) > 1)").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning("Not Unique UPC=" + no); + + // Mandatory Value + sql = new StringBuffer ("UPDATE I_Product i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No Mandatory Value,' " + + "WHERE Value IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning("No Mandatory Value=" + no); + + // Vendor Product No + // sql = new StringBuffer ("UPDATE I_Product i " + // + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=No Mandatory VendorProductNo,' " + // + "WHERE I_IsImported<>'Y'" + // + " AND VendorProductNo IS NULL AND (C_BPartner_ID IS NOT NULL OR BPartner_Value IS NOT NULL)").append(clientCheck); + // no = DB.executeUpdate(sql.toString(), get_TrxName()); + // log.info(log.l3_Util, "No Mandatory VendorProductNo=" + no); + sql = new StringBuffer ("UPDATE I_Product " + + "SET VendorProductNo=Value " + + "WHERE C_BPartner_ID IS NOT NULL AND VendorProductNo IS NULL" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.info("VendorProductNo Set to Value=" + no); + // + sql = new StringBuffer ("UPDATE I_Product i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=VendorProductNo not unique,' " + + "WHERE I_IsImported<>'Y'" + + " AND C_BPartner_ID IS NOT NULL" + + " AND (C_BPartner_ID, VendorProductNo) IN " + + " (SELECT C_BPartner_ID, VendorProductNo FROM I_Product ii WHERE i.AD_Client_ID=ii.AD_Client_ID GROUP BY C_BPartner_ID, VendorProductNo HAVING COUNT(*) > 1)") + .append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no != 0) + log.warning("Not Unique VendorProductNo=" + no); + + // Get Default Tax Category + int C_TaxCategory_ID = 0; + try + { + PreparedStatement pstmt = DB.prepareStatement + ("SELECT C_TaxCategory_ID FROM C_TaxCategory WHERE IsDefault='Y'" + clientCheck, get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + C_TaxCategory_ID = rs.getInt(1); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + throw new Exception ("TaxCategory", e); + } + log.fine("C_TaxCategory_ID=" + C_TaxCategory_ID); + + commit(); + + // ------------------------------------------------------------------- + int noInsert = 0; + int noUpdate = 0; + int noInsertPO = 0; + int noUpdatePO = 0; + + // Go through Records + log.fine("start inserting/updating ..."); + sql = new StringBuffer ("SELECT * FROM I_Product WHERE I_IsImported='N'") + .append(clientCheck); + try + { + /* Insert Product from Import + PreparedStatement pstmt_insertProduct = conn.prepareStatement + ("INSERT INTO M_Product (M_Product_ID," + + "AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy," + + "Value,Name,Description,DocumentNote,Help," + + "UPC,SKU,C_UOM_ID,IsSummary,M_Product_Category_ID,C_TaxCategory_ID," + + "ProductType,ImageURL,DescriptionURL) " + + "SELECT ?," + + "AD_Client_ID,AD_Org_ID,'Y',SysDate,CreatedBy,SysDate,UpdatedBy," + + "Value,Name,Description,DocumentNote,Help," + + "UPC,SKU,C_UOM_ID,'N',M_Product_Category_ID," + C_TaxCategory_ID + "," + + "ProductType,ImageURL,DescriptionURL " + + "FROM I_Product " + + "WHERE I_Product_ID=?"); + */ + // Update Product from Import + PreparedStatement pstmt_updateProduct = DB.prepareStatement + ("UPDATE M_PRODUCT " + + "SET (Value,Name,Description,DocumentNote,Help," + + "UPC,SKU,C_UOM_ID,M_Product_Category_ID,Classification,ProductType," + + "Volume,Weight,ShelfWidth,ShelfHeight,ShelfDepth,UnitsPerPallet," + + "Discontinued,DiscontinuedBy,Updated,UpdatedBy)= " + + "(SELECT Value,Name,Description,DocumentNote,Help," + + "UPC,SKU,C_UOM_ID,M_Product_Category_ID,Classification,ProductType," + + "Volume,Weight,ShelfWidth,ShelfHeight,ShelfDepth,UnitsPerPallet," + + "Discontinued,DiscontinuedBy,SysDate,UpdatedBy" + + " FROM I_Product WHERE I_Product_ID=?) " + + "WHERE M_Product_ID=?", get_TrxName()); + + // Update Product_PO from Import + PreparedStatement pstmt_updateProductPO = DB.prepareStatement + ("UPDATE M_Product_PO " + + "SET (IsCurrentVendor,C_UOM_ID,C_Currency_ID,UPC," + + "PriceList,PricePO,RoyaltyAmt,PriceEffective," + + "VendorProductNo,VendorCategory,Manufacturer," + + "Discontinued,DiscontinuedBy,Order_Min,Order_Pack," + + "CostPerOrder,DeliveryTime_Promised,Updated,UpdatedBy)= " + + "(SELECT 'Y',C_UOM_ID,C_Currency_ID,UPC," + + "PriceList,PricePO,RoyaltyAmt,PriceEffective," + + "VendorProductNo,VendorCategory,Manufacturer," + + "Discontinued,DiscontinuedBy,Order_Min,Order_Pack," + + "CostPerOrder,DeliveryTime_Promised,SysDate,UpdatedBy" + + " FROM I_Product" + + " WHERE I_Product_ID=?) " + + "WHERE M_Product_ID=? AND C_BPartner_ID=?", get_TrxName()); + + // Insert Product from Import + PreparedStatement pstmt_insertProductPO = DB.prepareStatement + ("INSERT INTO M_Product_PO (M_Product_ID,C_BPartner_ID, " + + "AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy," + + "IsCurrentVendor,C_UOM_ID,C_Currency_ID,UPC," + + "PriceList,PricePO,RoyaltyAmt,PriceEffective," + + "VendorProductNo,VendorCategory,Manufacturer," + + "Discontinued,DiscontinuedBy,Order_Min,Order_Pack," + + "CostPerOrder,DeliveryTime_Promised) " + + "SELECT ?,?, " + + "AD_Client_ID,AD_Org_ID,'Y',SysDate,CreatedBy,SysDate,UpdatedBy," + + "'Y',C_UOM_ID,C_Currency_ID,UPC," + + "PriceList,PricePO,RoyaltyAmt,PriceEffective," + + "VendorProductNo,VendorCategory,Manufacturer," + + "Discontinued,DiscontinuedBy,Order_Min,Order_Pack," + + "CostPerOrder,DeliveryTime_Promised " + + "FROM I_Product " + + "WHERE I_Product_ID=?", get_TrxName()); + + // Set Imported = Y + PreparedStatement pstmt_setImported = DB.prepareStatement + ("UPDATE I_Product SET I_IsImported='Y', M_Product_ID=?, " + + "Updated=SysDate, Processed='Y' WHERE I_Product_ID=?", get_TrxName()); + + // + PreparedStatement pstmt = DB.prepareStatement(sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + X_I_Product imp = new X_I_Product(getCtx(), rs, get_TrxName()); + int I_Product_ID = imp.getI_Product_ID(); + int M_Product_ID = imp.getM_Product_ID(); + int C_BPartner_ID = imp.getC_BPartner_ID(); + boolean newProduct = M_Product_ID == 0; + log.fine("I_Product_ID=" + I_Product_ID + ", M_Product_ID=" + M_Product_ID + + ", C_BPartner_ID=" + C_BPartner_ID); + + // Product + if (newProduct) // Insert new Product + { + MProduct product = new MProduct(imp); + product.setC_TaxCategory_ID(C_TaxCategory_ID); + if (product.save()) + { + M_Product_ID = product.getM_Product_ID(); + log.finer("Insert Product"); + noInsert++; + } + else + { + StringBuffer sql0 = new StringBuffer ("UPDATE I_Product i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||").append(DB.TO_STRING("Insert Product failed")) + .append("WHERE I_Product_ID=").append(I_Product_ID); + DB.executeUpdate(sql0.toString(), get_TrxName()); + continue; + } + } + else // Update Product + { + pstmt_updateProduct.setInt(1, I_Product_ID); + pstmt_updateProduct.setInt(2, M_Product_ID); + try + { + no = pstmt_updateProduct.executeUpdate(); + log.finer("Update Product = " + no); + noUpdate++; + } + catch (SQLException ex) + { + log.warning("Update Product - " + ex.toString()); + StringBuffer sql0 = new StringBuffer ("UPDATE I_Product i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||").append(DB.TO_STRING("Update Product: " + ex.toString())) + .append("WHERE I_Product_ID=").append(I_Product_ID); + DB.executeUpdate(sql0.toString(), get_TrxName()); + continue; + } + } + + // Do we have PO Info + if (C_BPartner_ID != 0) + { + no = 0; + // If Product existed, Try to Update first + if (!newProduct) + { + pstmt_updateProductPO.setInt(1, I_Product_ID); + pstmt_updateProductPO.setInt(2, M_Product_ID); + pstmt_updateProductPO.setInt(3, C_BPartner_ID); + try + { + no = pstmt_updateProductPO.executeUpdate(); + log.finer("Update Product_PO = " + no); + noUpdatePO++; + } + catch (SQLException ex) + { + log.warning("Update Product_PO - " + ex.toString()); + noUpdate--; + rollback(); + StringBuffer sql0 = new StringBuffer ("UPDATE I_Product i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||").append(DB.TO_STRING("Update Product_PO: " + ex.toString())) + .append("WHERE I_Product_ID=").append(I_Product_ID); + DB.executeUpdate(sql0.toString(), get_TrxName()); + continue; + } + } + if (no == 0) // Insert PO + { + pstmt_insertProductPO.setInt(1, M_Product_ID); + pstmt_insertProductPO.setInt(2, C_BPartner_ID); + pstmt_insertProductPO.setInt(3, I_Product_ID); + try + { + no = pstmt_insertProductPO.executeUpdate(); + log.finer("Insert Product_PO = " + no); + noInsertPO++; + } + catch (SQLException ex) + { + log.warning("Insert Product_PO - " + ex.toString()); + noInsert--; // assume that product also did not exist + rollback(); + StringBuffer sql0 = new StringBuffer ("UPDATE I_Product i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||").append(DB.TO_STRING("Insert Product_PO: " + ex.toString())) + .append("WHERE I_Product_ID=").append(I_Product_ID); + DB.executeUpdate(sql0.toString(), get_TrxName()); + continue; + } + } + } // C_BPartner_ID != 0 + + // Price List + if (p_M_PriceList_Version_ID != 0) + { + BigDecimal PriceList = imp.getPriceList(); + BigDecimal PriceStd = imp.getPriceStd(); + BigDecimal PriceLimit = imp.getPriceLimit(); + if (PriceStd.signum() != 0 && PriceLimit.signum() != 0 && PriceList.signum() != 0) + { + MProductPrice pp = MProductPrice.get(getCtx(), + p_M_PriceList_Version_ID, M_Product_ID, get_TrxName()); + if (pp == null) + pp = new MProductPrice (getCtx(), + p_M_PriceList_Version_ID, M_Product_ID, get_TrxName()); + pp.setPrices(PriceList, PriceStd, PriceLimit); + pp.save(); + } + } + + // Update I_Product + pstmt_setImported.setInt(1, M_Product_ID); + pstmt_setImported.setInt(2, I_Product_ID); + no = pstmt_setImported.executeUpdate(); + // + commit(); + } // for all I_Product + rs.close(); + pstmt.close(); + + // + // pstmt_insertProduct.close(); + pstmt_updateProduct.close(); + pstmt_insertProductPO.close(); + pstmt_updateProductPO.close(); + pstmt_setImported.close(); + // + } + catch (SQLException e) + { + } + + // Set Error to indicator to not imported + sql = new StringBuffer ("UPDATE I_Product " + + "SET I_IsImported='N', Updated=SysDate " + + "WHERE I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog (0, null, new BigDecimal (no), "@Errors@"); + addLog (0, null, new BigDecimal (noInsert), "@M_Product_ID@: @Inserted@"); + addLog (0, null, new BigDecimal (noUpdate), "@M_Product_ID@: @Updated@"); + addLog (0, null, new BigDecimal (noInsertPO), "@M_Product_ID@ @Purchase@: @Inserted@"); + addLog (0, null, new BigDecimal (noUpdatePO), "@M_Product_ID@ @Purchase@: @Updated@"); + return ""; + } // doIt + +} // ImportProduct diff --git a/base/src/org/compiere/process/ImportReportLine.java b/base/src/org/compiere/process/ImportReportLine.java new file mode 100644 index 0000000000..c570476ef6 --- /dev/null +++ b/base/src/org/compiere/process/ImportReportLine.java @@ -0,0 +1,453 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Import ReportLines from I_ReportLine + * + * @author Jorg Janke + * @version $Id: ImportReportLine.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ImportReportLine extends SvrProcess +{ + /** Client to be imported to */ + private int m_AD_Client_ID = 0; + /** Default Report Line Set */ + private int m_PA_ReportLineSet_ID = 0; + /** Delete old Imported */ + private boolean m_deleteOldImported = false; + + /** Organization to be imported to */ + private int m_AD_Org_ID = 0; + /** Effective */ + private Timestamp m_DateValue = null; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Client_ID")) + m_AD_Client_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("PA_ReportLineSet_ID")) + m_PA_ReportLineSet_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("DeleteOldImported")) + m_deleteOldImported = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + if (m_DateValue == null) + m_DateValue = new Timestamp (System.currentTimeMillis()); + } // prepare + + + /** + * Perrform process. + * @return Message + * @throws Exception + */ + protected String doIt() throws java.lang.Exception + { + StringBuffer sql = null; + int no = 0; + String clientCheck = " AND AD_Client_ID=" + m_AD_Client_ID; + + // **** Prepare **** + + // Delete Old Imported + if (m_deleteOldImported) + { + sql = new StringBuffer ("DELETE I_ReportLine " + + "WHERE I_IsImported='Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Delete Old Impored =" + no); + } + + // Set Client, Org, IsActive, Created/Updated + sql = new StringBuffer ("UPDATE I_ReportLine " + + "SET AD_Client_ID = COALESCE (AD_Client_ID, ").append(m_AD_Client_ID).append(")," + + " AD_Org_ID = COALESCE (AD_Org_ID, 0)," + + " IsActive = COALESCE (IsActive, 'Y')," + + " Created = COALESCE (Created, SysDate)," + + " CreatedBy = COALESCE (CreatedBy, 0)," + + " Updated = COALESCE (Updated, SysDate)," + + " UpdatedBy = COALESCE (UpdatedBy, 0)," + + " I_ErrorMsg = NULL," + + " I_IsImported = 'N' " + + "WHERE I_IsImported<>'Y' OR I_IsImported IS NULL"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Reset=" + no); + + // ReportLineSetName (Default) + if (m_PA_ReportLineSet_ID != 0) + { + sql = new StringBuffer ("UPDATE I_ReportLine i " + + "SET ReportLineSetName=(SELECT Name FROM PA_ReportLineSet r" + + " WHERE PA_ReportLineSet_ID=").append(m_PA_ReportLineSet_ID).append(" AND i.AD_Client_ID=r.AD_Client_ID) " + + "WHERE ReportLineSetName IS NULL AND PA_ReportLineSet_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set ReportLineSetName Default=" + no); + } + // Set PA_ReportLineSet_ID + sql = new StringBuffer ("UPDATE I_ReportLine i " + + "SET PA_ReportLineSet_ID=(SELECT PA_ReportLineSet_ID FROM PA_ReportLineSet r" + + " WHERE i.ReportLineSetName=r.Name AND i.AD_Client_ID=r.AD_Client_ID) " + + "WHERE PA_ReportLineSet_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set PA_ReportLineSet_ID=" + no); + // + sql = new StringBuffer ("UPDATE I_ReportLine " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid ReportLineSet, ' " + + "WHERE PA_ReportLineSet_ID IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Invalid ReportLineSet=" + no); + + // Ignore if there is no Report Line Name or ID + sql = new StringBuffer ("UPDATE I_ReportLine " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'Ignored=NoLineName, ' " + + "WHERE PA_ReportLine_ID IS NULL AND Name IS NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Invalid LineName=" + no); + + // Validate ElementValue + sql = new StringBuffer ("UPDATE I_ReportLine i " + + "SET C_ElementValue_ID=(SELECT C_ElementValue_ID FROM C_ElementValue e" + + " WHERE i.ElementValue=e.Value AND i.AD_Client_ID=e.AD_Client_ID) " + + "WHERE C_ElementValue_ID IS NULL AND ElementValue IS NOT NULL" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set C_ElementValue_ID=" + no); + + // Validate C_ElementValue_ID + sql = new StringBuffer ("UPDATE I_ReportLine " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid ElementValue, ' " + + "WHERE C_ElementValue_ID IS NULL AND LineType<>'C'" // MReportLine.LINETYPE_Calculation + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Invalid AccountType=" + no); + + // Set SeqNo + sql = new StringBuffer ("UPDATE I_ReportLine " + + "SET SeqNo=I_ReportLine_ID " + + "WHERE SeqNo IS NULL" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set SeqNo Default=" + no); + + // Copy/Sync from first Row of Line + sql = new StringBuffer ("UPDATE I_ReportLine i " + + "SET (Description, SeqNo, IsSummary, IsPrinted, LineType, CalculationType, AmountType, PostingType)=" + + " (SELECT Description, SeqNo, IsSummary, IsPrinted, LineType, CalculationType, AmountType, PostingType" + + " FROM I_ReportLine ii WHERE i.Name=ii.Name AND i.PA_ReportLineSet_ID=ii.PA_ReportLineSet_ID" + + " AND ii.I_ReportLine_ID=(SELECT MIN(I_ReportLine_ID) FROM I_ReportLine iii" + + " WHERE i.Name=iii.Name AND i.PA_ReportLineSet_ID=iii.PA_ReportLineSet_ID)) " + + "WHERE EXISTS (SELECT *" + + " FROM I_ReportLine ii WHERE i.Name=ii.Name AND i.PA_ReportLineSet_ID=ii.PA_ReportLineSet_ID" + + " AND ii.I_ReportLine_ID=(SELECT MIN(I_ReportLine_ID) FROM I_ReportLine iii" + + " WHERE i.Name=iii.Name AND i.PA_ReportLineSet_ID=iii.PA_ReportLineSet_ID))" + + " AND I_IsImported='N'").append(clientCheck); // not if previous error + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Sync from first Row of Line=" + no); + + // Validate IsSummary - (N) Y + sql = new StringBuffer ("UPDATE I_ReportLine " + + "SET IsSummary='N' " + + "WHERE IsSummary IS NULL OR IsSummary NOT IN ('Y','N')" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set IsSummary Default=" + no); + + // Validate IsPrinted - (Y) N + sql = new StringBuffer ("UPDATE I_ReportLine " + + "SET IsPrinted='Y' " + + "WHERE IsPrinted IS NULL OR IsPrinted NOT IN ('Y','N')" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set IsPrinted Default=" + no); + + // Validate Line Type - (S) C + sql = new StringBuffer ("UPDATE I_ReportLine " + + "SET LineType='S' " + + "WHERE LineType IS NULL OR LineType NOT IN ('S','C')" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set LineType Default=" + no); + + // Validate Optional Calculation Type - A P R S + sql = new StringBuffer ("UPDATE I_ReportLine " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid CalculationType, ' " + + "WHERE CalculationType IS NOT NULL AND CalculationType NOT IN ('A','P','R','S')" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Invalid CalculationType=" + no); + + // Validate Optional Amount Type - + sql = new StringBuffer ("UPDATE I_ReportLine " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid CalculationType, ' " + + "WHERE AmountType IS NOT NULL AND UPPER(AmountType) NOT IN ('BP','CP','DP','QP', 'BY','CY','DY','QY', 'BT','CT','DT','QT')" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Invalid AmountType=" + no); + + // Validate Optional Posting Type - A B E S R + sql = new StringBuffer ("UPDATE I_ReportLine " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||'ERR=Invalid CalculationType, ' " + + "WHERE PostingType IS NOT NULL AND PostingType NOT IN ('A','B','E','S','R')" + + " AND I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Invalid PostingType=" + no); + + // Set PA_ReportLine_ID + sql = new StringBuffer ("UPDATE I_ReportLine i " + + "SET PA_ReportLine_ID=(SELECT PA_ReportLine_ID FROM PA_ReportLine r" + + " WHERE i.Name=r.Name AND i.PA_ReportLineSet_ID=r.PA_ReportLineSet_ID AND ROWNUM=1) " + + "WHERE PA_ReportLine_ID IS NULL AND PA_ReportLineSet_ID IS NOT NULL" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set PA_ReportLine_ID=" + no); + + commit(); + + // ------------------------------------------------------------------- + int noInsertLine = 0; + int noUpdateLine = 0; + + // **** Create Missing ReportLines + sql = new StringBuffer ("SELECT DISTINCT PA_ReportLineSet_ID, Name " + + "FROM I_ReportLine " + + "WHERE I_IsImported='N' AND PA_ReportLine_ID IS NULL" + + " AND I_IsImported='N'").append(clientCheck); + try + { + // Insert ReportLine + PreparedStatement pstmt_insertLine = DB.prepareStatement + ("INSERT INTO PA_ReportLine " + + "(PA_ReportLine_ID,PA_ReportLineSet_ID," + + "AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy," + + "Name,SeqNo,IsPrinted,IsSummary,LineType)" + + "SELECT ?,PA_ReportLineSet_ID," + + "AD_Client_ID,AD_Org_ID,'Y',SysDate,CreatedBy,SysDate,UpdatedBy," + + "Name,SeqNo,IsPrinted,IsSummary,LineType " + + "FROM I_ReportLine " + + "WHERE PA_ReportLineSet_ID=? AND Name=? AND ROWNUM=1" // #2..3 + + clientCheck, get_TrxName()); + + PreparedStatement pstmt = DB.prepareStatement(sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + int PA_ReportLineSet_ID = rs.getInt(1); + String Name = rs.getString(2); + // + try + { + int PA_ReportLine_ID = DB.getNextID(m_AD_Client_ID, "PA_ReportLine", get_TrxName()); + if (PA_ReportLine_ID <= 0) + throw new DBException("No NextID (" + PA_ReportLine_ID + ")"); + pstmt_insertLine.setInt(1, PA_ReportLine_ID); + pstmt_insertLine.setInt(2, PA_ReportLineSet_ID); + pstmt_insertLine.setString(3, Name); + // + no = pstmt_insertLine.executeUpdate(); + log.finest("Insert ReportLine = " + no + ", PA_ReportLine_ID=" + PA_ReportLine_ID); + noInsertLine++; + } + catch (Exception ex) + { + log.finest(ex.toString()); + continue; + } + } + rs.close(); + pstmt.close(); + // + pstmt_insertLine.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "Create ReportLine", e); + } + + // Set PA_ReportLine_ID (for newly created) + sql = new StringBuffer ("UPDATE I_ReportLine i " + + "SET PA_ReportLine_ID=(SELECT PA_ReportLine_ID FROM PA_ReportLine r" + + " WHERE i.Name=r.Name AND i.PA_ReportLineSet_ID=r.PA_ReportLineSet_ID AND ROWNUM=1) " + + "WHERE PA_ReportLine_ID IS NULL AND PA_ReportLineSet_ID IS NOT NULL" + + " AND I_IsImported='N'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Set PA_ReportLine_ID=" + no); + + // **** Update ReportLine + sql = new StringBuffer ("UPDATE PA_ReportLine r " + + "SET (Description,SeqNo,IsSummary,IsPrinted,LineType,CalculationType,AmountType,PostingType,Updated,UpdatedBy)=" + + " (SELECT Description,SeqNo,IsSummary,IsPrinted,LineType,CalculationType,AmountType,PostingType,SysDate,UpdatedBy" + + " FROM I_ReportLine i WHERE r.Name=i.Name AND r.PA_ReportLineSet_ID=i.PA_ReportLineSet_ID" + + " AND i.I_ReportLine_ID=(SELECT MIN(I_ReportLine_ID) FROM I_ReportLine iii" + + " WHERE i.Name=iii.Name AND i.PA_ReportLineSet_ID=iii.PA_ReportLineSet_ID)) " + + "WHERE EXISTS (SELECT *" + + " FROM I_ReportLine i WHERE r.Name=i.Name AND r.PA_ReportLineSet_ID=i.PA_ReportLineSet_ID" + + " AND i.I_ReportLine_ID=(SELECT MIN(I_ReportLine_ID) FROM I_ReportLine iii" + + " WHERE i.Name=iii.Name AND i.PA_ReportLineSet_ID=iii.PA_ReportLineSet_ID AND i.I_IsImported='N'))") + .append(clientCheck); + noUpdateLine = DB.executeUpdate(sql.toString(), get_TrxName()); + log.config("Update PA_ReportLine=" + noUpdateLine); + + + // ------------------------------------------------------------------- + int noInsertSource = 0; + int noUpdateSource = 0; + + // **** Create ReportSource + sql = new StringBuffer ("SELECT I_ReportLine_ID, PA_ReportSource_ID " + + "FROM I_ReportLine " + + "WHERE PA_ReportLine_ID IS NOT NULL" + + " AND I_IsImported='N'").append(clientCheck); + try + { + // Insert ReportSource + PreparedStatement pstmt_insertSource = DB.prepareStatement + ("INSERT INTO PA_ReportSource " + + "(PA_ReportSource_ID," + + "AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy," + + "PA_ReportLine_ID,ElementType,C_ElementValue_ID) " + + "SELECT ?," + + "AD_Client_ID,AD_Org_ID,'Y',SysDate,CreatedBy,SysDate,UpdatedBy," + + "PA_ReportLine_ID,'AC',C_ElementValue_ID " + + "FROM I_ReportLine " + + "WHERE I_ReportLine_ID=?" + + " AND I_IsImported='N'" + + clientCheck, get_TrxName()); + + // Update ReportSource + PreparedStatement pstmt_updateSource = DB.prepareStatement + ("UPDATE PA_ReportSource " + + "SET (ElementType,C_ElementValue_ID,Updated,UpdatedBy)=" + + " (SELECT 'AC',C_ElementValue_ID,SysDate,UpdatedBy" + + " FROM I_ReportLine" + + " WHERE I_ReportLine_ID=?) " + + "WHERE PA_ReportSource_ID=?" + + clientCheck, get_TrxName()); + + // Set Imported = Y + PreparedStatement pstmt_setImported = DB.prepareStatement + ("UPDATE I_ReportLine SET I_IsImported='Y'," + + " PA_ReportSource_ID=?, " + + " Updated=SysDate, Processed='Y' WHERE I_ReportLine_ID=?", get_TrxName()); + + PreparedStatement pstmt = DB.prepareStatement(sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + int I_ReportLine_ID = rs.getInt(1); + int PA_ReportSource_ID = rs.getInt(2); + // + if (PA_ReportSource_ID == 0) // New ReportSource + { + try + { + PA_ReportSource_ID = DB.getNextID(m_AD_Client_ID, "PA_ReportSource", get_TrxName()); + if (PA_ReportSource_ID <= 0) + throw new DBException("No NextID (" + PA_ReportSource_ID + ")"); + pstmt_insertSource.setInt(1, PA_ReportSource_ID); + pstmt_insertSource.setInt(2, I_ReportLine_ID); + // + no = pstmt_insertSource.executeUpdate(); + log.finest("Insert ReportSource = " + no + ", I_ReportLine_ID=" + I_ReportLine_ID + ", PA_ReportSource_ID=" + PA_ReportSource_ID); + noInsertSource++; + } + catch (Exception ex) + { + log.finest("Insert ReportSource - " + ex.toString()); + sql = new StringBuffer ("UPDATE I_ReportLine i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||").append(DB.TO_STRING("Insert ElementSource: " + ex.toString())) + .append("WHERE I_ReportLine_ID=").append(I_ReportLine_ID); + DB.executeUpdate(sql.toString(), get_TrxName()); + continue; + } + } + else // update Report Source + { + pstmt_updateSource.setInt(1, I_ReportLine_ID); + pstmt_updateSource.setInt(2, PA_ReportSource_ID); + try + { + no = pstmt_updateSource.executeUpdate(); + log.finest("Update ReportSource = " + no + ", I_ReportLine_ID=" + I_ReportLine_ID + ", PA_ReportSource_ID=" + PA_ReportSource_ID); + noUpdateSource++; + } + catch (SQLException ex) + { + log.finest( "Update ReportSource - " + ex.toString()); + sql = new StringBuffer ("UPDATE I_ReportLine i " + + "SET I_IsImported='E', I_ErrorMsg=I_ErrorMsg||").append(DB.TO_STRING("Update ElementSource: " + ex.toString())) + .append("WHERE I_ReportLine_ID=").append(I_ReportLine_ID); + DB.executeUpdate(sql.toString(), get_TrxName()); + continue; + } + } // update source + + // Set Imported to Y + pstmt_setImported.setInt(1, PA_ReportSource_ID); + pstmt_setImported.setInt(2, I_ReportLine_ID); + no = pstmt_setImported.executeUpdate(); + if (no != 1) + log.log(Level.SEVERE, "Set Imported=" + no); + // + commit(); + } + rs.close(); + pstmt.close(); + // + pstmt_insertSource.close(); + pstmt_updateSource.close(); + pstmt_setImported.close(); + // + } + catch (SQLException e) + { + } + + // Set Error to indicator to not imported + sql = new StringBuffer ("UPDATE I_ReportLine " + + "SET I_IsImported='N', Updated=SysDate " + + "WHERE I_IsImported<>'Y'").append(clientCheck); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog (0, null, new BigDecimal (no), "@Errors@"); + addLog (0, null, new BigDecimal (noInsertLine), "@PA_ReportLine_ID@: @Inserted@"); + addLog (0, null, new BigDecimal (noUpdateLine), "@PA_ReportLine_ID@: @Updated@"); + addLog (0, null, new BigDecimal (noInsertSource), "@PA_ReportSource_ID@: @Inserted@"); + addLog (0, null, new BigDecimal (noUpdateSource), "@PA_ReportSource_ID@: @Updated@"); + + return ""; + } // doIt + +} // ImportReportLine diff --git a/base/src/org/compiere/process/InOutCreateConfirm.java b/base/src/org/compiere/process/InOutCreateConfirm.java new file mode 100644 index 0000000000..f6e7c5ea21 --- /dev/null +++ b/base/src/org/compiere/process/InOutCreateConfirm.java @@ -0,0 +1,74 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import org.compiere.model.*; + +/** + * Create Confirmation From Shipment + * + * @author Jorg Janke + * @version $Id: InOutCreateConfirm.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class InOutCreateConfirm extends SvrProcess +{ + /** Shipment */ + private int p_M_InOut_ID = 0; + /** Confirmation Type */ + private String p_ConfirmType = null; + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("ConfirmType")) + p_ConfirmType = (String)para[i].getParameter(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + p_M_InOut_ID = getRecord_ID(); + } // prepare + + /** + * Create Confirmation + * @return document no + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("M_InOut_ID=" + p_M_InOut_ID + ", Type=" + p_ConfirmType); + MInOut shipment = new MInOut (getCtx(), p_M_InOut_ID, null); + if (shipment.get_ID() == 0) + throw new IllegalArgumentException("Not found M_InOut_ID=" + p_M_InOut_ID); + // + MInOutConfirm confirm = MInOutConfirm.create (shipment, p_ConfirmType, true); + if (confirm == null) + throw new Exception ("Cannot create Confirmation for " + shipment.getDocumentNo()); + // + return confirm.getDocumentNo(); + } // doIt + +} // InOutCreateConfirm diff --git a/base/src/org/compiere/process/InOutCreateInvoice.java b/base/src/org/compiere/process/InOutCreateInvoice.java new file mode 100644 index 0000000000..8641355a7f --- /dev/null +++ b/base/src/org/compiere/process/InOutCreateInvoice.java @@ -0,0 +1,99 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import org.compiere.model.*; + +/** + * Create (Generate) Invoice from Shipment + * + * @author Jorg Janke + * @version $Id: InOutCreateInvoice.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class InOutCreateInvoice extends SvrProcess +{ + /** Shipment */ + private int p_M_InOut_ID = 0; + /** Price List Version */ + private int p_M_PriceList_ID = 0; + /* Document No */ + private String p_InvoiceDocumentNo = null; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("M_PriceList_ID")) + p_M_PriceList_ID = para[i].getParameterAsInt(); + else if (name.equals("InvoiceDocumentNo")) + p_InvoiceDocumentNo = (String)para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_M_InOut_ID = getRecord_ID(); + } // prepare + + /** + * Create Invoice. + * @return document no + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("M_InOut_ID=" + p_M_InOut_ID + + ", M_PriceList_ID=" + p_M_PriceList_ID + + ", InvoiceDocumentNo=" + p_InvoiceDocumentNo); + if (p_M_InOut_ID == 0) + throw new IllegalArgumentException("No Shipment"); + // + MInOut ship = new MInOut (getCtx(), p_M_InOut_ID, null); + if (ship.get_ID() == 0) + throw new IllegalArgumentException("Shipment not found"); + if (!MInOut.DOCSTATUS_Completed.equals(ship.getDocStatus())) + throw new IllegalArgumentException("Shipment not completed"); + + MInvoice invoice = new MInvoice (ship, null); + if (p_M_PriceList_ID != 0) + invoice.setM_PriceList_ID(p_M_PriceList_ID); + if (p_InvoiceDocumentNo != null && p_InvoiceDocumentNo.length() > 0) + invoice.setDocumentNo(p_InvoiceDocumentNo); + if (!invoice.save()) + throw new IllegalArgumentException("Cannot save Invoice"); + MInOutLine[] shipLines = ship.getLines(false); + for (int i = 0; i < shipLines.length; i++) + { + MInOutLine sLine = shipLines[i]; + MInvoiceLine line = new MInvoiceLine(invoice); + line.setShipLine(sLine); + line.setQtyEntered(sLine.getQtyEntered()); + line.setQtyInvoiced(sLine.getMovementQty()); + if (!line.save()) + throw new IllegalArgumentException("Cannot save Invoice Line"); + } + + return invoice.getDocumentNo(); + } // InOutCreateInvoice + +} // InOutCreateInvoice diff --git a/base/src/org/compiere/process/InOutGenerate.java b/base/src/org/compiere/process/InOutGenerate.java new file mode 100644 index 0000000000..b7a9581517 --- /dev/null +++ b/base/src/org/compiere/process/InOutGenerate.java @@ -0,0 +1,672 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Generate Shipments. + * Manual or Automatic + * + * @author Jorg Janke + * @version $Id: InOutGenerate.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class InOutGenerate extends SvrProcess +{ + /** Manual Selection */ + private boolean p_Selection = false; + /** Warehouse */ + private int p_M_Warehouse_ID = 0; + /** BPartner */ + private int p_C_BPartner_ID = 0; + /** Promise Date */ + private Timestamp p_DatePromised = null; + /** Include Orders w. unconfirmed Shipments */ + private boolean p_IsUnconfirmedInOut = false; + /** DocAction */ + private String p_docAction = DocAction.ACTION_Complete; + /** Consolidate */ + private boolean p_ConsolidateDocument = true; + + /** The current Shipment */ + private MInOut m_shipment = null; + /** Numner of Shipments */ + private int m_created = 0; + /** Line Number */ + private int m_line = 0; + /** Movement Date */ + private Timestamp m_movementDate = null; + /** Last BP Location */ + private int m_lastC_BPartner_Location_ID = -1; + + /** The Query sql */ + private String m_sql = null; + + + /** Storages temp space */ + private HashMap m_map = new HashMap(); + /** Last Parameter */ + private SParameter m_lastPP = null; + /** Last Storage */ + private MStorage[] m_lastStorages = null; + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("M_Warehouse_ID")) + p_M_Warehouse_ID = para[i].getParameterAsInt(); + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = para[i].getParameterAsInt(); + else if (name.equals("DatePromised")) + p_DatePromised = (Timestamp)para[i].getParameter(); + else if (name.equals("Selection")) + p_Selection = "Y".equals(para[i].getParameter()); + else if (name.equals("IsUnconfirmedInOut")) + p_IsUnconfirmedInOut = "Y".equals(para[i].getParameter()); + else if (name.equals("ConsolidateDocument")) + p_ConsolidateDocument = "Y".equals(para[i].getParameter()); + else if (name.equals("DocAction")) + p_docAction = (String)para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + + // Login Date + m_movementDate = Env.getContextAsDate(getCtx(), "#Date"); + if (m_movementDate == null) + m_movementDate = new Timestamp(System.currentTimeMillis()); + // DocAction check + if (!DocAction.ACTION_Complete.equals(p_docAction)) + p_docAction = DocAction.ACTION_Prepare; + } + } // prepare + + /** + * Generate Shipments + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("Selection=" + p_Selection + + ", M_Warehouse_ID=" + p_M_Warehouse_ID + + ", C_BPartner_ID=" + p_C_BPartner_ID + + ", Consolidate=" + p_ConsolidateDocument + + ", IsUnconfirmed=" + p_IsUnconfirmedInOut + + ", Movement=" + m_movementDate); + + if (p_M_Warehouse_ID == 0) + throw new AdempiereUserError("@NotFound@ @M_Warehouse_ID@"); + + if (p_Selection) // VInOutGen + { + m_sql = "SELECT * FROM C_Order " + + "WHERE IsSelected='Y' AND DocStatus='CO' AND IsSOTrx='Y' AND AD_Client_ID=?"; + } + else + { + m_sql = "SELECT * FROM C_Order o " + + "WHERE DocStatus='CO' AND IsSOTrx='Y'" + // No Offer,POS + + " AND o.C_DocType_ID IN (SELECT C_DocType_ID FROM C_DocType " + + "WHERE DocBaseType='SOO' AND DocSubTypeSO NOT IN ('ON','OB','WR'))" + + " AND o.IsDropShip='N'" + // No Manual + + " AND o.DeliveryRule<>'M'" + // Open Order Lines with Warehouse + + " AND EXISTS (SELECT * FROM C_OrderLine ol " + + "WHERE ol.M_Warehouse_ID=?" + + " AND o.C_Order_ID=ol.C_Order_ID AND ol.QtyOrdered<>ol.QtyDelivered)"; + if (p_C_BPartner_ID != 0) + m_sql += " AND C_BPartner_ID=?"; + if (p_DatePromised != null) + m_sql += " AND TRUNC(DatePromised)<=?"; + } + m_sql += " ORDER BY M_Warehouse_ID, PriorityRule, M_Shipper_ID, C_BPartner_ID, C_BPartner_Location_ID, C_Order_ID"; + // m_sql += " FOR UPDATE"; + + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (m_sql, get_TrxName()); + int index = 1; + if (p_Selection) + pstmt.setInt(index++, Env.getAD_Client_ID(getCtx())); + else + { + pstmt.setInt(index++, p_M_Warehouse_ID); + if (p_C_BPartner_ID != 0) + pstmt.setInt(index++, p_C_BPartner_ID); + if (p_DatePromised != null) + pstmt.setTimestamp(index++, p_DatePromised); + } + } + catch (Exception e) + { + log.log(Level.SEVERE, m_sql, e); + } + return generate(pstmt); + } // doIt + + /** + * Generate Shipments + * @param pstmt Order Query + * @return info + */ + private String generate (PreparedStatement pstmt) + { + MClient client = MClient.get(getCtx()); + try + { + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) // Order + { + MOrder order = new MOrder (getCtx(), rs, get_TrxName()); + // New Header different Shipper, Shipment Location + if (!p_ConsolidateDocument + || (m_shipment != null + && (m_shipment.getC_BPartner_Location_ID() != order.getC_BPartner_Location_ID() + || m_shipment.getM_Shipper_ID() != order.getM_Shipper_ID() ))) + completeShipment(); + log.fine("check: " + order + " - DeliveryRule=" + order.getDeliveryRule()); + // + Timestamp minGuaranteeDate = m_movementDate; + boolean completeOrder = MOrder.DELIVERYRULE_CompleteOrder.equals(order.getDeliveryRule()); + // + String where = " AND M_Warehouse_ID=" + p_M_Warehouse_ID; + // Exclude Auto Delivery if not Force + if (!MOrder.DELIVERYRULE_Force.equals(order.getDeliveryRule())) + where += " AND (C_OrderLine.M_Product_ID IS NULL" + + " OR EXISTS (SELECT * FROM M_Product p " + + "WHERE C_OrderLine.M_Product_ID=p.M_Product_ID" + + " AND IsExcludeAutoDelivery='N'))"; + // Exclude Unconfirmed + if (!p_IsUnconfirmedInOut) + where += " AND NOT EXISTS (SELECT * FROM M_InOutLine iol" + + " INNER JOIN M_InOut io ON (iol.M_InOut_ID=io.M_InOut_ID) " + + "WHERE iol.C_OrderLine_ID=C_OrderLine.C_OrderLine_ID AND io.DocStatus IN ('IP','WC'))"; + // Deadlock Prevention - Order by M_Product_ID + MOrderLine[] lines = order.getLines (where, "ORDER BY C_BPartner_Location_ID, M_Product_ID"); + for (int i = 0; i < lines.length; i++) + { + MOrderLine line = lines[i]; + if (line.getM_Warehouse_ID() != p_M_Warehouse_ID) + continue; + log.fine("check: " + line); + BigDecimal onHand = Env.ZERO; + BigDecimal toDeliver = line.getQtyOrdered() + .subtract(line.getQtyDelivered()); + MProduct product = line.getProduct(); + // Nothing to Deliver + if (product != null && toDeliver.signum() == 0) + continue; + + // Check / adjust for confirmations + BigDecimal unconfirmedShippedQty = Env.ZERO; + if (p_IsUnconfirmedInOut && product != null && toDeliver.signum() != 0) + { + String where2 = "EXISTS (SELECT * FROM M_InOut io WHERE io.M_InOut_ID=M_InOutLine.M_InOut_ID AND io.DocStatus IN ('IP','WC'))"; + MInOutLine[] iols = MInOutLine.getOfOrderLine(getCtx(), + line.getC_OrderLine_ID(), where2, null); + for (int j = 0; j < iols.length; j++) + unconfirmedShippedQty = unconfirmedShippedQty.add(iols[j].getMovementQty()); + String logInfo = "Unconfirmed Qty=" + unconfirmedShippedQty + + " - ToDeliver=" + toDeliver + "->"; + toDeliver = toDeliver.subtract(unconfirmedShippedQty); + logInfo += toDeliver; + if (toDeliver.signum() < 0) + { + toDeliver = Env.ZERO; + logInfo += " (set to 0)"; + } + // Adjust On Hand + onHand = onHand.subtract(unconfirmedShippedQty); + log.fine(logInfo); + } + + // Comments & lines w/o product & services + if ((product == null || !product.isStocked()) + && (line.getQtyOrdered().signum() == 0 // comments + || toDeliver.signum() != 0)) // lines w/o product + { + if (!MOrder.DELIVERYRULE_CompleteOrder.equals(order.getDeliveryRule())) // printed later + createLine (order, line, toDeliver, null, false); + continue; + } + + // Stored Product + MProductCategory pc = MProductCategory.get(order.getCtx(), product.getM_Product_Category_ID()); + String MMPolicy = pc.getMMPolicy(); + if (MMPolicy == null || MMPolicy.length() == 0) + MMPolicy = client.getMMPolicy(); + // + MStorage[] storages = getStorages(line.getM_Warehouse_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), + product.getM_AttributeSet_ID(), + line.getM_AttributeSetInstance_ID()==0, minGuaranteeDate, + MClient.MMPOLICY_FiFo.equals(MMPolicy)); + + for (int j = 0; j < storages.length; j++) + { + MStorage storage = storages[j]; + onHand = onHand.add(storage.getQtyOnHand()); + } + boolean fullLine = onHand.compareTo(toDeliver) >= 0 + || toDeliver.signum() < 0; + + // Complete Order + if (completeOrder && !fullLine) + { + log.fine("Failed CompleteOrder - OnHand=" + onHand + + " (Unconfirmed=" + unconfirmedShippedQty + + "), ToDeliver=" + toDeliver + " - " + line); + completeOrder = false; + break; + } + // Complete Line + else if (fullLine && MOrder.DELIVERYRULE_CompleteLine.equals(order.getDeliveryRule())) + { + log.fine("CompleteLine - OnHand=" + onHand + + " (Unconfirmed=" + unconfirmedShippedQty + + ", ToDeliver=" + toDeliver + " - " + line); + // + createLine (order, line, toDeliver, storages, false); + } + // Availability + else if (MOrder.DELIVERYRULE_Availability.equals(order.getDeliveryRule()) + && (onHand.signum() > 0 + || toDeliver.signum() < 0)) + { + BigDecimal deliver = toDeliver; + if (deliver.compareTo(onHand) > 0) + deliver = onHand; + log.fine("Available - OnHand=" + onHand + + " (Unconfirmed=" + unconfirmedShippedQty + + "), ToDeliver=" + toDeliver + + ", Delivering=" + deliver + " - " + line); + // + createLine (order, line, deliver, storages, false); + } + // Force + else if (MOrder.DELIVERYRULE_Force.equals(order.getDeliveryRule())) + { + BigDecimal deliver = toDeliver; + log.fine("Force - OnHand=" + onHand + + " (Unconfirmed=" + unconfirmedShippedQty + + "), ToDeliver=" + toDeliver + + ", Delivering=" + deliver + " - " + line); + // + createLine (order, line, deliver, storages, true); + } + // Manual + else if (MOrder.DELIVERYRULE_Manual.equals(order.getDeliveryRule())) + log.fine("Manual - OnHand=" + onHand + + " (Unconfirmed=" + unconfirmedShippedQty + + ") - " + line); + else + log.fine("Failed: " + order.getDeliveryRule() + " - OnHand=" + onHand + + " (Unconfirmed=" + unconfirmedShippedQty + + "), ToDeliver=" + toDeliver + " - " + line); + } // for all order lines + + // Complete Order successful + if (completeOrder && MOrder.DELIVERYRULE_CompleteOrder.equals(order.getDeliveryRule())) + { + for (int i = 0; i < lines.length; i++) + { + MOrderLine line = lines[i]; + if (line.getM_Warehouse_ID() != p_M_Warehouse_ID) + continue; + MProduct product = line.getProduct(); + BigDecimal toDeliver = line.getQtyOrdered().subtract(line.getQtyDelivered()); + // + MStorage[] storages = null; + if (product != null && product.isStocked()) + { + MProductCategory pc = MProductCategory.get(order.getCtx(), product.getM_Product_Category_ID()); + String MMPolicy = pc.getMMPolicy(); + if (MMPolicy == null || MMPolicy.length() == 0) + MMPolicy = client.getMMPolicy(); + // + storages = getStorages(line.getM_Warehouse_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), + product.getM_AttributeSet_ID(), + line.getM_AttributeSetInstance_ID()==0, minGuaranteeDate, + MClient.MMPOLICY_FiFo.equals(MMPolicy)); + } + // + createLine (order, line, toDeliver, storages, false); + } + } + m_line += 1000; + } // while order + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, m_sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + completeShipment(); + return "@Created@ = " + m_created; + } // generate + + + + /************************************************************************** + * Create Line + * @param order order + * @param orderLine line + * @param qty qty + * @param storages storage info + * @param force force delivery + */ + private void createLine (MOrder order, MOrderLine orderLine, BigDecimal qty, + MStorage[] storages, boolean force) + { + // Complete last Shipment - can have multiple shipments + if (m_lastC_BPartner_Location_ID != orderLine.getC_BPartner_Location_ID() ) + completeShipment(); + m_lastC_BPartner_Location_ID = orderLine.getC_BPartner_Location_ID(); + // Create New Shipment + if (m_shipment == null) + { + m_shipment = new MInOut (order, 0, m_movementDate); + m_shipment.setM_Warehouse_ID(orderLine.getM_Warehouse_ID()); // sets Org too + if (order.getC_BPartner_ID() != orderLine.getC_BPartner_ID()) + m_shipment.setC_BPartner_ID(orderLine.getC_BPartner_ID()); + if (order.getC_BPartner_Location_ID() != orderLine.getC_BPartner_Location_ID()) + m_shipment.setC_BPartner_Location_ID(orderLine.getC_BPartner_Location_ID()); + if (!m_shipment.save()) + throw new IllegalStateException("Could not create Shipment"); + } + // Non Inventory Lines + if (storages == null) + { + MInOutLine line = new MInOutLine (m_shipment); + line.setOrderLine(orderLine, 0, Env.ZERO); + line.setQty(qty); // Correct UOM + if (orderLine.getQtyEntered().compareTo(orderLine.getQtyOrdered()) != 0) + line.setQtyEntered(qty + .multiply(orderLine.getQtyEntered()) + .divide(orderLine.getQtyOrdered(), 12, BigDecimal.ROUND_HALF_UP)); + line.setLine(m_line + orderLine.getLine()); + if (!line.save()) + throw new IllegalStateException("Could not create Shipment Line"); + log.fine(line.toString()); + return; + } + + // Product + MProduct product = orderLine.getProduct(); + boolean linePerASI = false; + if (product.getM_AttributeSet_ID() != 0) + { + MAttributeSet mas = MAttributeSet.get(getCtx(), product.getM_AttributeSet_ID()); + linePerASI = mas.isInstanceAttribute(); + } + + // Inventory Lines + ArrayList list = new ArrayList(); + BigDecimal toDeliver = qty; + for (int i = 0; i < storages.length; i++) + { + MStorage storage = storages[i]; + BigDecimal deliver = toDeliver; + // Not enough On Hand + if (deliver.compareTo(storage.getQtyOnHand()) > 0 + && storage.getQtyOnHand().signum() >= 0) // positive storage + { + if (!force // Adjust to OnHand Qty + || (force && i+1 != storages.length)) // if force not on last location + deliver = storage.getQtyOnHand(); + } + if (deliver.signum() == 0) // zero deliver + continue; + int M_Locator_ID = storage.getM_Locator_ID(); + // + MInOutLine line = null; + if (!linePerASI) // find line with Locator + { + for (int ll = 0; ll < list.size(); ll++) + { + MInOutLine test = (MInOutLine)list.get(ll); + if (test.getM_Locator_ID() == M_Locator_ID) + { + line = test; + break; + } + } + } + if (line == null) // new line + { + line = new MInOutLine (m_shipment); + line.setOrderLine(orderLine, M_Locator_ID, order.isSOTrx() ? deliver : Env.ZERO); + line.setQty(deliver); + list.add(line); + } + else // existing line + line.setQty(line.getMovementQty().add(deliver)); + if (orderLine.getQtyEntered().compareTo(orderLine.getQtyOrdered()) != 0) + line.setQtyEntered(line.getMovementQty().multiply(orderLine.getQtyEntered()) + .divide(orderLine.getQtyOrdered(), 12, BigDecimal.ROUND_HALF_UP)); + line.setLine(m_line + orderLine.getLine()); + if (linePerASI) + line.setM_AttributeSetInstance_ID(storage.getM_AttributeSetInstance_ID()); + if (!line.save()) + throw new IllegalStateException("Could not create Shipment Line"); + log.fine("ToDeliver=" + qty + "/" + deliver + " - " + line); + toDeliver = toDeliver.subtract(deliver); + // Temp adjustment + storage.setQtyOnHand(storage.getQtyOnHand().subtract(deliver)); + // + if (toDeliver.signum() == 0) + break; + } + if (toDeliver.signum() != 0) + throw new IllegalStateException("Not All Delivered - Remainder=" + toDeliver); + } // createLine + + + /** + * Get Storages + * @param M_Warehouse_ID + * @param M_Product_ID + * @param M_AttributeSetInstance_ID + * @param M_AttributeSet_ID + * @param allAttributeInstances + * @param minGuaranteeDate + * @param FiFo + * @return storages + */ + private MStorage[] getStorages(int M_Warehouse_ID, + int M_Product_ID, int M_AttributeSetInstance_ID, int M_AttributeSet_ID, + boolean allAttributeInstances, Timestamp minGuaranteeDate, + boolean FiFo) + { + m_lastPP = new SParameter(M_Warehouse_ID, + M_Product_ID, M_AttributeSetInstance_ID, M_AttributeSet_ID, + allAttributeInstances, minGuaranteeDate, FiFo); + // + m_lastStorages = m_map.get(m_lastPP); + + if (m_lastStorages == null) + { + m_lastStorages = MStorage.getWarehouse(getCtx(), + M_Warehouse_ID, M_Product_ID, M_AttributeSetInstance_ID, + M_AttributeSet_ID, allAttributeInstances, minGuaranteeDate, + FiFo, get_TrxName()); + m_map.put(m_lastPP, m_lastStorages); + } + return m_lastStorages; + } // getStorages + + + /** + * Complete Shipment + */ + private void completeShipment() + { + if (m_shipment != null) + { + // Fails if there is a confirmation + if (!m_shipment.processIt(p_docAction)) + log.warning("Failed: " + m_shipment); + m_shipment.save(); + // + addLog(m_shipment.getM_InOut_ID(), m_shipment.getMovementDate(), null, m_shipment.getDocumentNo()); + m_created++; + m_map = new HashMap(); + if (m_lastPP != null && m_lastStorages != null) + m_map.put(m_lastPP, m_lastStorages); + } + m_shipment = null; + m_line = 0; + } // completeOrder + + /** + * InOutGenerate Parameter + */ + class SParameter + { + /** + * Parameter + * @param p_Warehouse_ID warehouse + * @param p_Product_ID + * @param p_AttributeSetInstance_ID + * @param p_AttributeSet_ID + * @param p_allAttributeInstances + * @param p_minGuaranteeDate + * @param p_FiFo + */ + protected SParameter (int p_Warehouse_ID, + int p_Product_ID, int p_AttributeSetInstance_ID, int p_AttributeSet_ID, + boolean p_allAttributeInstances, Timestamp p_minGuaranteeDate, + boolean p_FiFo) + { + this.M_Warehouse_ID = p_Warehouse_ID; + this.M_Product_ID = p_Product_ID; + this.M_AttributeSetInstance_ID = p_AttributeSetInstance_ID; + this.M_AttributeSet_ID = p_AttributeSet_ID; + this.allAttributeInstances = p_allAttributeInstances; + this.minGuaranteeDate = p_minGuaranteeDate; + this.FiFo = p_FiFo; + } + /** Warehouse */ + public int M_Warehouse_ID; + /** Product */ + public int M_Product_ID; + /** ASI */ + public int M_AttributeSetInstance_ID; + /** AS */ + public int M_AttributeSet_ID; + /** All instances */ + public boolean allAttributeInstances; + /** Mon Guarantee Date */ + public Timestamp minGuaranteeDate; + /** FiFo */ + public boolean FiFo; + + /** + * Equals + * @param obj + * @return true if equal + */ + public boolean equals (Object obj) + { + if (obj != null && obj instanceof SParameter) + { + SParameter cmp = (SParameter)obj; + boolean eq = cmp.M_Warehouse_ID == M_Warehouse_ID + && cmp.M_Product_ID == M_Product_ID + && cmp.M_AttributeSetInstance_ID == M_AttributeSetInstance_ID + && cmp.M_AttributeSet_ID == M_AttributeSet_ID + && cmp.allAttributeInstances == allAttributeInstances + && cmp.FiFo == FiFo; + if (eq) + { + if (cmp.minGuaranteeDate == null && minGuaranteeDate == null) + ; + else if (cmp.minGuaranteeDate != null && minGuaranteeDate != null + && cmp.minGuaranteeDate.equals(minGuaranteeDate)) + ; + else + eq = false; + } + return eq; + } + return false; + } // equals + + /** + * hashCode + * @return hash code + */ + public int hashCode () + { + long hash = M_Warehouse_ID + + (M_Product_ID * 2) + + (M_AttributeSetInstance_ID * 3) + + (M_AttributeSet_ID * 4); + + if (allAttributeInstances) + hash *= -1; + if (FiFo); + hash *= -2; + if (hash < 0) + hash = -hash + 7; + while (hash > Integer.MAX_VALUE) + hash -= Integer.MAX_VALUE; + // + if (minGuaranteeDate != null) + { + hash += minGuaranteeDate.hashCode(); + while (hash > Integer.MAX_VALUE) + hash -= Integer.MAX_VALUE; + } + + return (int)hash; + } // hashCode + + } // Parameter + +} // InOutGenerate diff --git a/base/src/org/compiere/process/InfoWindowValidate.java b/base/src/org/compiere/process/InfoWindowValidate.java new file mode 100644 index 0000000000..a3a41fcf59 --- /dev/null +++ b/base/src/org/compiere/process/InfoWindowValidate.java @@ -0,0 +1,49 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +/** + * Validate Info Window SQL + * + * @author Jorg Janke + * @version $Id: InfoWindowValidate.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class InfoWindowValidate extends SvrProcess +{ + /** Info Window */ + private int p_AD_InfoWindow_ID = 0; + + /** + * Prepare + */ + protected void prepare () + { + p_AD_InfoWindow_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt () + throws Exception + { + return null; + } // doIt + +} // InfoWindowValidate diff --git a/base/src/org/compiere/process/InventoryCountCreate.java b/base/src/org/compiere/process/InventoryCountCreate.java new file mode 100644 index 0000000000..bb95c789e9 --- /dev/null +++ b/base/src/org/compiere/process/InventoryCountCreate.java @@ -0,0 +1,324 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Create Inventory Count List with current Book value + * + * @author Jorg Janke + * @version $Id: InventoryCountCreate.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class InventoryCountCreate extends SvrProcess +{ + + /** Physical Inventory Parameter */ + private int p_M_Inventory_ID = 0; + /** Physical Inventory */ + private MInventory m_inventory = null; + /** Locator Parameter */ + private int p_M_Locator_ID = 0; + /** Locator Parameter */ + private String p_LocatorValue = null; + /** Product Parameter */ + private String p_ProductValue = null; + /** Product Category Parameter */ + private int p_M_Product_Category_ID = 0; + /** Qty Range Parameter */ + private String p_QtyRange = null; + /** Update to What */ + private boolean p_InventoryCountSetZero = false; + /** Delete Parameter */ + private boolean p_DeleteOld = false; + + /** Inventory Line */ + private MInventoryLine m_line = null; + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("M_Locator_ID")) + p_M_Locator_ID = para[i].getParameterAsInt(); + else if (name.equals("LocatorValue")) + p_LocatorValue = (String)para[i].getParameter(); + else if (name.equals("ProductValue")) + p_ProductValue = (String)para[i].getParameter(); + else if (name.equals("M_Product_Category_ID")) + p_M_Product_Category_ID = para[i].getParameterAsInt(); + else if (name.equals("QtyRange")) + p_QtyRange = (String)para[i].getParameter(); + else if (name.equals("InventoryCountSet")) + p_InventoryCountSetZero = "Z".equals(para[i].getParameter()); + else if (name.equals("DeleteOld")) + p_DeleteOld = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_M_Inventory_ID = getRecord_ID(); + } // prepare + + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("M_Inventory_ID=" + p_M_Inventory_ID + + ", M_Locator_ID=" + p_M_Locator_ID + ", LocatorValue=" + p_LocatorValue + + ", ProductValue=" + p_ProductValue + + ", M_Product_Category_ID=" + p_M_Product_Category_ID + + ", QtyRange=" + p_QtyRange + ", DeleteOld=" + p_DeleteOld); + m_inventory = new MInventory (getCtx(), p_M_Inventory_ID, get_TrxName()); + if (m_inventory.get_ID() == 0) + throw new AdempiereSystemError ("Not found: M_Inventory_ID=" + p_M_Inventory_ID); + if (m_inventory.isProcessed()) + throw new AdempiereSystemError ("@M_Inventory_ID@ @Processed@"); + // + if (p_DeleteOld) + { + String sql = "DELETE M_InventoryLine WHERE Processed='N' " + + "AND M_Inventory_ID=" + p_M_Inventory_ID; + int no = DB.executeUpdate(sql, get_TrxName()); + log.fine("doIt - Deleted #" + no); + } + + // Create Null Storage records + if (p_QtyRange != null && p_QtyRange.equals("=")) + { + String sql = "INSERT INTO M_Storage " + + "(AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " M_Locator_ID, M_Product_ID, M_AttributeSetInstance_ID," + + " QtyOnHand, QtyReserved, QtyOrdered, DateLastInventory) " + + "SELECT l.AD_CLIENT_ID, l.AD_ORG_ID, 'Y', SysDate, 0,SysDate, 0," + + " l.M_Locator_ID, p.M_Product_ID, 0," + + " 0,0,0,null " + + "FROM M_Locator l" + + " INNER JOIN M_Product p ON (l.AD_Client_ID=p.AD_Client_ID) " + + "WHERE l.M_Warehouse_ID=" + m_inventory.getM_Warehouse_ID(); + if (p_M_Locator_ID != 0) + sql += " AND l.M_Locator_ID=" + p_M_Locator_ID; + sql += " AND l.IsDefault='Y'" + + " AND p.IsActive='Y' AND p.IsStocked='Y' and p.ProductType='I'" + + " AND NOT EXISTS (SELECT * FROM M_Storage s" + + " INNER JOIN M_Locator sl ON (s.M_Locator_ID=sl.M_Locator_ID) " + + "WHERE sl.M_Warehouse_ID=l.M_Warehouse_ID" + + " AND s.M_Product_ID=p.M_Product_ID)"; + int no = DB.executeUpdate(sql, get_TrxName()); + log.fine("'0' Inserted #" + no); + } + + StringBuffer sql = new StringBuffer( + "SELECT s.M_Product_ID, s.M_Locator_ID, s.M_AttributeSetInstance_ID," + + " s.QtyOnHand, p.M_AttributeSet_ID " + + "FROM M_Product p" + + " INNER JOIN M_Storage s ON (s.M_Product_ID=p.M_Product_ID)" + + " INNER JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID) " + + "WHERE l.M_Warehouse_ID=?" + + " AND p.IsActive='Y' AND p.IsStocked='Y' and p.ProductType='I'"); + // + if (p_M_Locator_ID != 0) + sql.append(" AND s.M_Locator_ID=?"); + // + if (p_LocatorValue != null && + (p_LocatorValue.trim().length() == 0 || p_LocatorValue.equals("%"))) + p_LocatorValue = null; + if (p_LocatorValue != null) + sql.append(" AND UPPER(l.Value) LIKE ?"); + // + if (p_ProductValue != null && + (p_ProductValue.trim().length() == 0 || p_ProductValue.equals("%"))) + p_ProductValue = null; + if (p_ProductValue != null) + sql.append(" AND UPPER(p.Value) LIKE ?"); + // + if (p_M_Product_Category_ID != 0) + sql.append(" AND p.M_Product_Category_ID=?"); + + // Do not overwrite existing records + if (!p_DeleteOld) + sql.append(" AND NOT EXISTS (SELECT * FROM M_InventoryLine il " + + "WHERE il.M_Inventory_ID=?" + + " AND il.M_Product_ID=s.M_Product_ID" + + " AND il.M_Locator_ID=s.M_Locator_ID" + + " AND COALESCE(il.M_AttributeSetInstance_ID,0)=COALESCE(s.M_AttributeSetInstance_ID,0))"); + // + sql.append(" ORDER BY l.Value, p.Value, s.QtyOnHand DESC"); // Locator/Product + // + int count = 0; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql.toString(), get_TrxName()); + int index = 1; + pstmt.setInt (index++, m_inventory.getM_Warehouse_ID()); + if (p_M_Locator_ID != 0) + pstmt.setInt(index++, p_M_Locator_ID); + if (p_LocatorValue != null) + pstmt.setString(index++, p_LocatorValue.toUpperCase()); + if (p_ProductValue != null) + pstmt.setString(index++, p_ProductValue.toUpperCase()); + if (p_M_Product_Category_ID != 0) + pstmt.setInt(index++, p_M_Product_Category_ID); + if (!p_DeleteOld) + pstmt.setInt(index++, p_M_Inventory_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + int M_Product_ID = rs.getInt(1); + int M_Locator_ID = rs.getInt(2); + int M_AttributeSetInstance_ID = rs.getInt(3); + BigDecimal QtyOnHand = rs.getBigDecimal(4); + if (QtyOnHand == null) + QtyOnHand = Env.ZERO; + int M_AttributeSet_ID = rs.getInt(5); + // + int compare = QtyOnHand.compareTo(Env.ZERO); + if (p_QtyRange == null + || (p_QtyRange.equals(">") && compare > 0) + || (p_QtyRange.equals("<") && compare < 0) + || (p_QtyRange.equals("=") && compare == 0) + || (p_QtyRange.equals("N") && compare != 0)) + { + count += createInventoryLine (M_Locator_ID, M_Product_ID, + M_AttributeSetInstance_ID, QtyOnHand, M_AttributeSet_ID); + } + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + // Set Count to Zero + if (p_InventoryCountSetZero) + { + String sql1 = "UPDATE M_InventoryLine l " + + "SET QtyCount=0 " + + "WHERE M_Inventory_ID=" + p_M_Inventory_ID; + int no = DB.executeUpdate(sql1, get_TrxName()); + log.info("Set Cont to Zero=" + no); + } + + // + return "@M_InventoryLine_ID@ - #" + count; + } // doIt + + /** + * Create/Add to Inventory Line + * @param M_Product_ID product + * @param M_Locator_ID locator + * @param M_AttributeSetInstance_ID asi + * @param QtyOnHand qty + * @param M_AttributeSet_ID as + * @return lines added + */ + private int createInventoryLine (int M_Locator_ID, int M_Product_ID, + int M_AttributeSetInstance_ID, BigDecimal QtyOnHand, int M_AttributeSet_ID) + { + boolean oneLinePerASI = false; + if (M_AttributeSet_ID != 0) + { + MAttributeSet mas = MAttributeSet.get(getCtx(), M_AttributeSet_ID); + oneLinePerASI = mas.isInstanceAttribute(); + } + if (oneLinePerASI) + { + MInventoryLine line = new MInventoryLine (m_inventory, M_Locator_ID, + M_Product_ID, M_AttributeSetInstance_ID, + QtyOnHand, QtyOnHand); // book/count + if (line.save()) + return 1; + return 0; + } + + if (QtyOnHand.signum() == 0) + M_AttributeSetInstance_ID = 0; + + if (m_line != null + && m_line.getM_Locator_ID() == M_Locator_ID + && m_line.getM_Product_ID() == M_Product_ID) + { + if (QtyOnHand.signum() == 0) + return 0; + // Same ASI (usually 0) + if (m_line.getM_AttributeSetInstance_ID() == M_AttributeSetInstance_ID) + { + m_line.setQtyBook(m_line.getQtyBook().add(QtyOnHand)); + m_line.setQtyCount(m_line.getQtyCount().add(QtyOnHand)); + m_line.save(); + return 0; + } + // Save Old Line info + else if (m_line.getM_AttributeSetInstance_ID() != 0) + { + MInventoryLineMA ma = new MInventoryLineMA (m_line, + m_line.getM_AttributeSetInstance_ID(), m_line.getQtyBook()); + if (!ma.save()) + ; + } + m_line.setM_AttributeSetInstance_ID(0); + m_line.setQtyBook(m_line.getQtyBook().add(QtyOnHand)); + m_line.setQtyCount(m_line.getQtyCount().add(QtyOnHand)); + m_line.save(); + // + MInventoryLineMA ma = new MInventoryLineMA (m_line, + M_AttributeSetInstance_ID, QtyOnHand); + if (!ma.save()) + ; + return 0; + } + // new line + m_line = new MInventoryLine (m_inventory, M_Locator_ID, + M_Product_ID, M_AttributeSetInstance_ID, + QtyOnHand, QtyOnHand); // book/count + if (m_line.save()) + return 1; + return 0; + } // createInventoryLine + +} // InventoryCountCreate diff --git a/base/src/org/compiere/process/InventoryCountUpdate.java b/base/src/org/compiere/process/InventoryCountUpdate.java new file mode 100644 index 0000000000..0a16caa6c5 --- /dev/null +++ b/base/src/org/compiere/process/InventoryCountUpdate.java @@ -0,0 +1,187 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import java.sql.*; +import java.math.*; + +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Update existing Inventory Count List with current Book value + * + * @author Jorg Janke + * @version $Id: InventoryCountUpdate.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class InventoryCountUpdate extends SvrProcess +{ + /** Physical Inventory */ + private int p_M_Inventory_ID = 0; + /** Update to What */ + private boolean p_InventoryCountSetZero = false; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("InventoryCountSet")) + p_InventoryCountSetZero = "Z".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_M_Inventory_ID = getRecord_ID(); + } // prepare + + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("M_Inventory_ID=" + p_M_Inventory_ID); + MInventory inventory = new MInventory (getCtx(), p_M_Inventory_ID, get_TrxName()); + if (inventory.get_ID() == 0) + throw new AdempiereSystemError ("Not found: M_Inventory_ID=" + p_M_Inventory_ID); + + // Multiple Lines for one item + String sql = "UPDATE M_InventoryLine SET IsActive='N' " + + "WHERE M_Inventory_ID=" + p_M_Inventory_ID + + " AND (M_Product_ID, M_Locator_ID, M_AttributeSetInstance_ID) IN " + + "(SELECT M_Product_ID, M_Locator_ID, M_AttributeSetInstance_ID " + + "FROM M_InventoryLine " + + "WHERE M_Inventory_ID=" + p_M_Inventory_ID + + " GROUP BY M_Product_ID, M_Locator_ID, M_AttributeSetInstance_ID " + + "HAVING COUNT(*) > 1)"; + int multiple = DB.executeUpdate(sql, get_TrxName()); + log.info("Multiple=" + multiple); + + int delMA = MInventoryLineMA.deleteInventoryMA(p_M_Inventory_ID, get_TrxName()); + log.info("DeletedMA=" + delMA); + + // ASI + sql = "UPDATE M_InventoryLine l " + + "SET (QtyBook,QtyCount) = " + + "(SELECT QtyOnHand,QtyOnHand FROM M_Storage s " + + "WHERE s.M_Product_ID=l.M_Product_ID AND s.M_Locator_ID=l.M_Locator_ID" + + " AND s.M_AttributeSetInstance_ID=l.M_AttributeSetInstance_ID)," + + " Updated=SysDate," + + " UpdatedBy=" + getAD_User_ID() + // + + " WHERE M_Inventory_ID=" + p_M_Inventory_ID + + " AND EXISTS (SELECT * FROM M_Storage s " + + "WHERE s.M_Product_ID=l.M_Product_ID AND s.M_Locator_ID=l.M_Locator_ID" + + " AND s.M_AttributeSetInstance_ID=l.M_AttributeSetInstance_ID)"; + int no = DB.executeUpdate(sql, get_TrxName()); + log.info("Update with ASI=" + no); + + // No ASI + int noMA = updateWithMA(); + + // Set Count to Zero + if (p_InventoryCountSetZero) + { + sql = "UPDATE M_InventoryLine l " + + "SET QtyCount=0 " + + "WHERE M_Inventory_ID=" + p_M_Inventory_ID; + no = DB.executeUpdate(sql, get_TrxName()); + log.info("Set Cont to Zero=" + no); + } + + if (multiple > 0) + return "@M_InventoryLine_ID@ - #" + (no + noMA) + " --> @InventoryProductMultiple@"; + + return "@M_InventoryLine_ID@ - #" + no; + } // doIt + + /** + * Update Inventory Lines With Material Allocation + * @return no updated + */ + private int updateWithMA() + { + int no = 0; + // + String sql = "SELECT * FROM M_InventoryLine WHERE M_Inventory_ID=? AND M_AttributeSetInstance_ID=0"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, p_M_Inventory_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MInventoryLine il = new MInventoryLine (getCtx(), rs, get_TrxName()); + BigDecimal onHand = Env.ZERO; + MStorage[] storages = MStorage.getAll(getCtx(), il.getM_Product_ID(), il.getM_Locator_ID(), get_TrxName()); + MInventoryLineMA ma = null; + for (int i = 0; i < storages.length; i++) + { + MStorage storage = storages[i]; + if (storage.getQtyOnHand().signum() == 0) + continue; + onHand = onHand.add(storage.getQtyOnHand()); + // No ASI + if (storage.getM_AttributeSetInstance_ID() == 0 + && storages.length == 1) + continue; + // Save ASI + ma = new MInventoryLineMA (il, + storage.getM_AttributeSetInstance_ID(), storage.getQtyOnHand()); + if (!ma.save()) + ; + } + il.setQtyBook(onHand); + il.setQtyCount(onHand); + if (il.save()) + no++; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + log.info("#" + no); + return no; + } // updateWithMA + + +} // InventoryCountUpdate diff --git a/base/src/org/compiere/process/InventoryValue.java b/base/src/org/compiere/process/InventoryValue.java new file mode 100644 index 0000000000..b4531e13ea --- /dev/null +++ b/base/src/org/compiere/process/InventoryValue.java @@ -0,0 +1,284 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; + +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Inventory Valuation. + * Process to fill T_InventoryValue + * + * @author Jorg Janke + * @version $Id: InventoryValue.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class InventoryValue extends SvrProcess +{ + /** Price List Used */ + private int p_M_PriceList_Version_ID; + /** Valuation Date */ + private Timestamp p_DateValue; + /** Warehouse */ + private int p_M_Warehouse_ID; + /** Currency */ + private int p_C_Currency_ID; + /** Optional Cost Element */ + private int p_M_CostElement_ID; + + /** + * Prepare - get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("M_PriceList_Version_ID")) + p_M_PriceList_Version_ID = para[i].getParameterAsInt(); + else if (name.equals("DateValue")) + p_DateValue = (Timestamp)para[i].getParameter(); + else if (name.equals("M_Warehouse_ID")) + p_M_Warehouse_ID = para[i].getParameterAsInt(); + else if (name.equals("C_Currency_ID")) + p_C_Currency_ID = para[i].getParameterAsInt(); + else if (name.equals("M_CostElement_ID")) + p_M_CostElement_ID = para[i].getParameterAsInt(); + } + if (p_DateValue == null) + p_DateValue = new Timestamp (System.currentTimeMillis()); + } // prepare + + /** + * Perrform process. + *
+	 *  - Fill Table with QtyOnHand for Warehouse and Valuation Date
+	 *  - Perform Price Calculations
+	 *  
+ * @return Message + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info("M_Warehouse_ID=" + p_M_Warehouse_ID + + ",C_Currency_ID=" + p_C_Currency_ID + + ",DateValue=" + p_DateValue + + ",M_PriceList_Version_ID=" + p_M_PriceList_Version_ID + + ",M_CostElement_ID=" + p_M_CostElement_ID); + + MWarehouse wh = MWarehouse.get(getCtx(), p_M_Warehouse_ID); + MClient c = MClient.get(getCtx(), wh.getAD_Client_ID()); + MAcctSchema as = c.getAcctSchema(); + + // Delete (just to be sure) + StringBuffer sql = new StringBuffer ("DELETE T_InventoryValue WHERE AD_PInstance_ID="); + sql.append(getAD_PInstance_ID()); + int no = DB.executeUpdate(sql.toString(), get_TrxName()); + + // Insert Standard Costs + sql = new StringBuffer ("INSERT INTO T_InventoryValue " + + "(AD_PInstance_ID, M_Warehouse_ID, M_Product_ID, M_AttributeSetInstance_ID," + + " AD_Client_ID, AD_Org_ID, CostStandard) " + + "SELECT ").append(getAD_PInstance_ID()) + .append(", w.M_Warehouse_ID, c.M_Product_ID, c.M_AttributeSetInstance_ID," + + " w.AD_Client_ID, w.AD_Org_ID, c.CurrentCostPrice " + + "FROM M_Warehouse w" + + " INNER JOIN AD_ClientInfo ci ON (w.AD_Client_ID=ci.AD_Client_ID)" + + " INNER JOIN C_AcctSchema acs ON (ci.C_AcctSchema1_ID=acs.C_AcctSchema_ID)" + + " INNER JOIN M_Cost c ON (acs.C_AcctSchema_ID=c.C_AcctSchema_ID AND acs.M_CostType_ID=c.M_CostType_ID AND c.AD_Org_ID IN (0, w.AD_Org_ID))" + + " INNER JOIN M_CostElement ce ON (c.M_CostElement_ID=ce.M_CostElement_ID AND ce.CostingMethod='S' AND ce.CostElementType='M') " + + "WHERE w.M_Warehouse_ID=").append(p_M_Warehouse_ID); + int noInsertStd = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Inserted Std=" + noInsertStd); + if (noInsertStd == 0) + return "No Standard Costs found"; + + // Insert addl Costs + int noInsertCost = 0; + if (p_M_CostElement_ID != 0) + { + sql = new StringBuffer ("INSERT INTO T_InventoryValue " + + "(AD_PInstance_ID, M_Warehouse_ID, M_Product_ID, M_AttributeSetInstance_ID," + + " AD_Client_ID, AD_Org_ID, CostStandard, Cost, M_CostElement_ID) " + + "SELECT ").append(getAD_PInstance_ID()) + .append(", w.M_Warehouse_ID, c.M_Product_ID, c.M_AttributeSetInstance_ID," + + " w.AD_Client_ID, w.AD_Org_ID, 0, c.CurrentCostPrice, c.M_CostElement_ID " + + "FROM M_Warehouse w" + + " INNER JOIN AD_ClientInfo ci ON (w.AD_Client_ID=ci.AD_Client_ID)" + + " INNER JOIN C_AcctSchema acs ON (ci.C_AcctSchema1_ID=acs.C_AcctSchema_ID)" + + " INNER JOIN M_Cost c ON (acs.C_AcctSchema_ID=c.C_AcctSchema_ID AND acs.M_CostType_ID=c.M_CostType_ID AND c.AD_Org_ID IN (0, w.AD_Org_ID)) " + + "WHERE w.M_Warehouse_ID=").append(p_M_Warehouse_ID) + .append(" AND c.M_CostElement_ID=").append(p_M_CostElement_ID) + .append(" AND NOT EXISTS (SELECT * FROM T_InventoryValue iv " + + "WHERE iv.AD_PInstance_ID=").append(getAD_PInstance_ID()) + .append(" AND iv.M_Warehouse_ID=w.M_Warehouse_ID" + + " AND iv.M_Product_ID=c.M_Product_ID" + + " AND iv.M_AttributeSetInstance_ID=c.M_AttributeSetInstance_ID)"); + noInsertCost = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Inserted Cost=" + noInsertCost); + // Update Std Cost Records + sql = new StringBuffer ("UPDATE T_InventoryValue iv " + + "SET (Cost, M_CostElement_ID)=" + + "(SELECT c.CurrentCostPrice, c.M_CostElement_ID " + + "FROM M_Warehouse w" + + " INNER JOIN AD_ClientInfo ci ON (w.AD_Client_ID=ci.AD_Client_ID)" + + " INNER JOIN C_AcctSchema acs ON (ci.C_AcctSchema1_ID=acs.C_AcctSchema_ID)" + + " INNER JOIN M_Cost c ON (acs.C_AcctSchema_ID=c.C_AcctSchema_ID" + + " AND acs.M_CostType_ID=c.M_CostType_ID AND c.AD_Org_ID IN (0, w.AD_Org_ID)) " + + "WHERE c.M_CostElement_ID=" + p_M_CostElement_ID + + " AND iv.M_Warehouse_ID=w.M_Warehouse_ID" + + " AND iv.M_Product_ID=c.M_Product_ID" + + " AND iv.M_AttributeSetInstance_ID=c.M_AttributeSetInstance_ID) " + + "WHERE EXISTS (SELECT * FROM T_InventoryValue ivv " + + "WHERE ivv.AD_PInstance_ID=" + getAD_PInstance_ID() + + " AND ivv.M_CostElement_ID IS NULL)"); + int noUpdatedCost = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Updated Cost=" + noUpdatedCost); + } + if ((noInsertStd+noInsertCost) == 0) + return "No Costs found"; + + // Update Constants + // YYYY-MM-DD HH24:MI:SS.mmmm JDBC Timestamp format + String myDate = p_DateValue.toString(); + sql = new StringBuffer ("UPDATE T_InventoryValue SET ") + .append("DateValue=TO_DATE('").append(myDate.substring(0,10)) + .append(" 23:59:59','YYYY-MM-DD HH24:MI:SS'),") + .append("M_PriceList_Version_ID=").append(p_M_PriceList_Version_ID).append(",") + .append("C_Currency_ID=").append(p_C_Currency_ID); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Constants=" + no); + + // Get current QtyOnHand with ASI + sql = new StringBuffer ("UPDATE T_InventoryValue iv SET QtyOnHand = " + + "(SELECT SUM(QtyOnHand) FROM M_Storage s" + + " INNER JOIN M_Locator l ON (l.M_Locator_ID=s.M_Locator_ID) " + + "WHERE iv.M_Product_ID=s.M_Product_ID" + + " AND iv.M_Warehouse_ID=l.M_Warehouse_ID" + + " AND iv.M_AttributeSetInstance_ID=s.M_AttributeSetInstance_ID) " + + "WHERE AD_PInstance_ID=").append(getAD_PInstance_ID()) + .append(" AND iv.M_AttributeSetInstance_ID<>0"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("QtHand with ASI=" + no); + // Get current QtyOnHand without ASI + sql = new StringBuffer ("UPDATE T_InventoryValue iv SET QtyOnHand = " + + "(SELECT SUM(QtyOnHand) FROM M_Storage s" + + " INNER JOIN M_Locator l ON (l.M_Locator_ID=s.M_Locator_ID) " + + "WHERE iv.M_Product_ID=s.M_Product_ID" + + " AND iv.M_Warehouse_ID=l.M_Warehouse_ID) " + + "WHERE AD_PInstance_ID=").append(getAD_PInstance_ID()) + .append(" AND iv.M_AttributeSetInstance_ID=0"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("QtHand w/o ASI=" + no); + + // Adjust for Valuation Date + sql = new StringBuffer("UPDATE T_InventoryValue iv " + + "SET QtyOnHand=" + + "(SELECT iv.QtyOnHand - NVL(SUM(t.MovementQty), 0) " + + "FROM M_Transaction t" + + " INNER JOIN M_Locator l ON (t.M_Locator_ID=l.M_Locator_ID) " + + "WHERE t.M_Product_ID=iv.M_Product_ID" + + " AND t.M_AttributeSetInstance_ID=iv.M_AttributeSetInstance_ID" + + " AND t.MovementDate > iv.DateValue" + + " AND l.M_Warehouse_ID=iv.M_Warehouse_ID) " + + "WHERE iv.M_AttributeSetInstance_ID<>0"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Update with ASI=" + no); + // + sql = new StringBuffer("UPDATE T_InventoryValue iv " + + "SET QtyOnHand=" + + "(SELECT iv.QtyOnHand - NVL(SUM(t.MovementQty), 0) " + + "FROM M_Transaction t" + + " INNER JOIN M_Locator l ON (t.M_Locator_ID=l.M_Locator_ID) " + + "WHERE t.M_Product_ID=iv.M_Product_ID" + + " AND t.MovementDate > iv.DateValue" + + " AND l.M_Warehouse_ID=iv.M_Warehouse_ID) " + + "WHERE iv.M_AttributeSetInstance_ID=0"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Update w/o ASI=" + no); + + // Delete Records w/o OnHand Qty + sql = new StringBuffer("DELETE T_InventoryValue " + + "WHERE (QtyOnHand=0 OR QtyOnHand IS NULL) AND AD_PInstance_ID=").append(getAD_PInstance_ID()); + int noQty = DB.executeUpdate (sql.toString(), get_TrxName()); + log.fine("NoQty Deleted=" + noQty); + + // Update Prices + no = DB.executeUpdate ("UPDATE T_InventoryValue iv " + + "SET PricePO = " + + "(SELECT currencyConvert (po.PriceList,po.C_Currency_ID,iv.C_Currency_ID,iv.DateValue,null, po.AD_Client_ID,po.AD_Org_ID)" + + " FROM M_Product_PO po WHERE po.M_Product_ID=iv.M_Product_ID" + + " AND po.IsCurrentVendor='Y' AND RowNum=1), " + + "PriceList = " + + "(SELECT currencyConvert(pp.PriceList,pl.C_Currency_ID,iv.C_Currency_ID,iv.DateValue,null, pl.AD_Client_ID,pl.AD_Org_ID)" + + " FROM M_PriceList pl, M_PriceList_Version plv, M_ProductPrice pp" + + " WHERE pp.M_Product_ID=iv.M_Product_ID AND pp.M_PriceList_Version_ID=iv.M_PriceList_Version_ID" + + " AND pp.M_PriceList_Version_ID=plv.M_PriceList_Version_ID" + + " AND plv.M_PriceList_ID=pl.M_PriceList_ID), " + + "PriceStd = " + + "(SELECT currencyConvert(pp.PriceStd,pl.C_Currency_ID,iv.C_Currency_ID,iv.DateValue,null, pl.AD_Client_ID,pl.AD_Org_ID)" + + " FROM M_PriceList pl, M_PriceList_Version plv, M_ProductPrice pp" + + " WHERE pp.M_Product_ID=iv.M_Product_ID AND pp.M_PriceList_Version_ID=iv.M_PriceList_Version_ID" + + " AND pp.M_PriceList_Version_ID=plv.M_PriceList_Version_ID" + + " AND plv.M_PriceList_ID=pl.M_PriceList_ID), " + + "PriceLimit = " + + "(SELECT currencyConvert(pp.PriceLimit,pl.C_Currency_ID,iv.C_Currency_ID,iv.DateValue,null, pl.AD_Client_ID,pl.AD_Org_ID)" + + " FROM M_PriceList pl, M_PriceList_Version plv, M_ProductPrice pp" + + " WHERE pp.M_Product_ID=iv.M_Product_ID AND pp.M_PriceList_Version_ID=iv.M_PriceList_Version_ID" + + " AND pp.M_PriceList_Version_ID=plv.M_PriceList_Version_ID" + + " AND plv.M_PriceList_ID=pl.M_PriceList_ID)" + , get_TrxName()); + String msg = ""; + if (no == 0) + msg = "No Prices"; + + // Convert if different Currency + if (as.getC_Currency_ID() != p_C_Currency_ID) + { + sql = new StringBuffer ("UPDATE T_InventoryValue iv " + + "SET CostStandard= " + + "(SELECT currencyConvert(iv.CostStandard,acs.C_Currency_ID,iv.C_Currency_ID,iv.DateValue,null, iv.AD_Client_ID,iv.AD_Org_ID) " + + "FROM C_AcctSchema acs WHERE acs.C_AcctSchema_ID=" + as.getC_AcctSchema_ID() + ")," + + " Cost= " + + "(SELECT currencyConvert(iv.Cost,acs.C_Currency_ID,iv.C_Currency_ID,iv.DateValue,null, iv.AD_Client_ID,iv.AD_Org_ID) " + + "FROM C_AcctSchema acs WHERE acs.C_AcctSchema_ID=" + as.getC_AcctSchema_ID() + ") " + + "WHERE AD_PInstance_ID=" + getAD_PInstance_ID()); + no = DB.executeUpdate (sql.toString(), get_TrxName()); + log.fine("Convered=" + no); + } + + // Update Values + no = DB.executeUpdate("UPDATE T_InventoryValue SET " + + "PricePOAmt = QtyOnHand * PricePO, " + + "PriceListAmt = QtyOnHand * PriceList, " + + "PriceStdAmt = QtyOnHand * PriceStd, " + + "PriceLimitAmt = QtyOnHand * PriceLimit, " + + "CostStandardAmt = QtyOnHand * CostStandard, " + + "CostAmt = QtyOnHand * Cost " + + "WHERE AD_PInstance_ID=" + getAD_PInstance_ID() + , get_TrxName()); + log.fine("Calculation=" + no); + // + return msg; + } // doIt + +} // InventoryValue diff --git a/base/src/org/compiere/process/InvoiceBatchProcess.java b/base/src/org/compiere/process/InvoiceBatchProcess.java new file mode 100644 index 0000000000..0dbe6c74d8 --- /dev/null +++ b/base/src/org/compiere/process/InvoiceBatchProcess.java @@ -0,0 +1,164 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Process Invoice Batch + * + * @author Jorg Janke + * @version $Id: InvoiceBatchProcess.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class InvoiceBatchProcess extends SvrProcess +{ + /** Batch to process */ + private int p_C_InvoiceBatch_ID = 0; + /** Action */ + private String p_DocAction = null; + + /** Invoice */ + private MInvoice m_invoice = null; + /** Old DocumentNo */ + private String m_oldDocumentNo = null; + /** Old BPartner */ + private int m_oldC_BPartner_ID = 0; + /** Old BPartner Loc */ + private int m_oldC_BPartner_Location_ID = 0; + + /** Counter */ + private int m_count = 0; + + /** + * Prepare - get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("DocAction")) + p_DocAction = (String)para[i].getParameter(); + } + p_C_InvoiceBatch_ID = getRecord_ID(); + } // prepare + + /** + * Process Invoice Batch + * @return message + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("C_InvoiceBatch_ID=" + p_C_InvoiceBatch_ID + ", DocAction=" + p_DocAction); + if (p_C_InvoiceBatch_ID == 0) + throw new AdempiereUserError("C_InvoiceBatch_ID = 0"); + MInvoiceBatch batch = new MInvoiceBatch(getCtx(), p_C_InvoiceBatch_ID, get_TrxName()); + if (batch.get_ID() == 0) + throw new AdempiereUserError("@NotFound@: @C_InvoiceBatch_ID@ - " + p_C_InvoiceBatch_ID); + if (batch.isProcessed()) + throw new AdempiereUserError("@Processed@"); + // + if (batch.getControlAmt().signum() != 0 + && batch.getControlAmt().compareTo(batch.getDocumentAmt()) != 0) + throw new AdempiereUserError("@ControlAmt@ <> @DocumentAmt@"); + // + MInvoiceBatchLine[] lines = batch.getLines(false); + for (int i = 0; i < lines.length; i++) + { + MInvoiceBatchLine line = lines[i]; + if (line.getC_Invoice_ID() != 0 || line.getC_InvoiceLine_ID() != 0) + continue; + + if ((m_oldDocumentNo != null + && !m_oldDocumentNo.equals(line.getDocumentNo())) + || m_oldC_BPartner_ID != line.getC_BPartner_ID() + || m_oldC_BPartner_Location_ID != line.getC_BPartner_Location_ID()) + completeInvoice(); + // New Invoice + if (m_invoice == null) + { + m_invoice = new MInvoice (batch, line); + if (!m_invoice.save()) + throw new AdempiereUserError("Cannot save Invoice"); + // + m_oldDocumentNo = line.getDocumentNo(); + m_oldC_BPartner_ID = line.getC_BPartner_ID(); + m_oldC_BPartner_Location_ID = line.getC_BPartner_Location_ID(); + } + + if (line.isTaxIncluded() != m_invoice.isTaxIncluded()) + { + // rollback + throw new AdempiereUserError("Line " + line.getLine() + " TaxIncluded inconsistent"); + } + + // Add Line + MInvoiceLine invoiceLine = new MInvoiceLine (m_invoice); + invoiceLine.setDescription(line.getDescription()); + invoiceLine.setC_Charge_ID(line.getC_Charge_ID()); + invoiceLine.setQty(line.getQtyEntered()); // Entered/Invoiced + invoiceLine.setPrice(line.getPriceEntered()); + invoiceLine.setC_Tax_ID(line.getC_Tax_ID()); + invoiceLine.setTaxAmt(line.getTaxAmt()); + invoiceLine.setLineNetAmt(line.getLineNetAmt()); + invoiceLine.setLineTotalAmt(line.getLineTotalAmt()); + if (!invoiceLine.save()) + { + // rollback + throw new AdempiereUserError("Cannot save Invoice Line"); + } + + // Update Batch Line + line.setC_Invoice_ID(m_invoice.getC_Invoice_ID()); + line.setC_InvoiceLine_ID(invoiceLine.getC_InvoiceLine_ID()); + line.save(); + + } // for all lines + completeInvoice(); + // + batch.setProcessed(true); + batch.save(); + + return "#" + m_count; + } // doIt + + + /** + * Complete Invoice + */ + private void completeInvoice() + { + if (m_invoice == null) + return; + + m_invoice.setDocAction(p_DocAction); + m_invoice.processIt(p_DocAction); + m_invoice.save(); + + addLog(0, m_invoice.getDateInvoiced(), m_invoice.getGrandTotal(), m_invoice.getDocumentNo()); + m_count++; + + m_invoice = null; + } // completeInvoice + +} // InvoiceBatchProcess diff --git a/base/src/org/compiere/process/InvoiceCreateInOut.java b/base/src/org/compiere/process/InvoiceCreateInOut.java new file mode 100644 index 0000000000..74467a3953 --- /dev/null +++ b/base/src/org/compiere/process/InvoiceCreateInOut.java @@ -0,0 +1,106 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; + +import org.compiere.util.*; +import org.compiere.model.*; + +/** + * Create (Generate) Shipment from Invoice + * + * @author Jorg Janke + * @version $Id: InvoiceCreateInOut.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class InvoiceCreateInOut extends SvrProcess +{ + /** Warehouse */ + private int p_M_Warehouse_ID = 0; + /** Invoice */ + private int p_C_Invoice_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("M_Warehouse_ID")) + p_M_Warehouse_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_C_Invoice_ID = getRecord_ID(); + } // prepare + + + /** + * Create Shipment + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("C_Invoice_ID=" + p_C_Invoice_ID + + ", M_Warehouse_ID=" + p_M_Warehouse_ID); + if (p_C_Invoice_ID == 0) + throw new IllegalArgumentException("@NotFound@ @C_Invoice_ID@"); + if (p_M_Warehouse_ID == 0) + throw new IllegalArgumentException("@NotFound@ @M_Warehouse_ID@"); + // + MInvoice invoice = new MInvoice (getCtx(), p_C_Invoice_ID, null); + if (invoice.get_ID() == 0) + throw new IllegalArgumentException("@NotFound@ @C_Invoice_ID@"); + if (!MInvoice.DOCSTATUS_Completed.equals(invoice.getDocStatus())) + throw new IllegalArgumentException("@InvoiceCreateDocNotCompleted@"); + // + MInOut ship = new MInOut (invoice, 0, null, p_M_Warehouse_ID); + if (!ship.save()) + throw new IllegalArgumentException("@SaveError@ Receipt"); + // + MInvoiceLine[] invoiceLines = invoice.getLines(false); + for (int i = 0; i < invoiceLines.length; i++) + { + MInvoiceLine invoiceLine = invoiceLines[i]; + MInOutLine sLine = new MInOutLine(ship); + sLine.setInvoiceLine(invoiceLine, 0, // Locator + invoice.isSOTrx() ? invoiceLine.getQtyInvoiced() : Env.ZERO); + sLine.setQtyEntered(invoiceLine.getQtyEntered()); + sLine.setMovementQty(invoiceLine.getQtyInvoiced()); + if (invoice.isCreditMemo()) + { + sLine.setQtyEntered(sLine.getQtyEntered().negate()); + sLine.setMovementQty(sLine.getMovementQty().negate()); + } + if (!sLine.save()) + throw new IllegalArgumentException("@SaveError@ @M_InOutLine_ID@"); + // + invoiceLine.setM_InOutLine_ID(sLine.getM_InOutLine_ID()); + if (!invoiceLine.save()) + throw new IllegalArgumentException("@SaveError@ @C_InvoiceLine_ID@"); + } + + return ship.getDocumentNo(); + } // doIt + +} // InvoiceCreateInOut diff --git a/base/src/org/compiere/process/InvoiceGenerate.java b/base/src/org/compiere/process/InvoiceGenerate.java new file mode 100644 index 0000000000..93283cb9f8 --- /dev/null +++ b/base/src/org/compiere/process/InvoiceGenerate.java @@ -0,0 +1,424 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Generate Invoices + * + * @author Jorg Janke + * @version $Id: InvoiceGenerate.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class InvoiceGenerate extends SvrProcess +{ + /** Manual Selection */ + private boolean p_Selection = false; + /** Date Invoiced */ + private Timestamp p_DateInvoiced = null; + /** Org */ + private int p_AD_Org_ID = 0; + /** BPartner */ + private int p_C_BPartner_ID = 0; + /** Order */ + private int p_C_Order_ID = 0; + /** Consolidate */ + private boolean p_ConsolidateDocument = true; + /** Invoice Document Action */ + private String p_docAction = DocAction.ACTION_Complete; + + /** The current Invoice */ + private MInvoice m_invoice = null; + /** The current Shipment */ + private MInOut m_ship = null; + /** Numner of Invoices */ + private int m_created = 0; + /** Line Number */ + private int m_line = 0; + /** Business Partner */ + private MBPartner m_bp = null; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("Selection")) + p_Selection = "Y".equals(para[i].getParameter()); + else if (name.equals("DateInvoiced")) + p_DateInvoiced = (Timestamp)para[i].getParameter(); + else if (name.equals("AD_Org_ID")) + p_AD_Org_ID = para[i].getParameterAsInt(); + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = para[i].getParameterAsInt(); + else if (name.equals("C_Order_ID")) + p_C_Order_ID = para[i].getParameterAsInt(); + else if (name.equals("ConsolidateDocument")) + p_ConsolidateDocument = "Y".equals(para[i].getParameter()); + else if (name.equals("DocAction")) + p_docAction = (String)para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + + // Login Date + if (p_DateInvoiced == null) + p_DateInvoiced = Env.getContextAsDate(getCtx(), "#Date"); + if (p_DateInvoiced == null) + p_DateInvoiced = new Timestamp(System.currentTimeMillis()); + + // DocAction check + if (!DocAction.ACTION_Complete.equals(p_docAction)) + p_docAction = DocAction.ACTION_Prepare; + } // prepare + + /** + * Generate Invoices + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("Selection=" + p_Selection + ", DateInvoiced=" + p_DateInvoiced + + ", AD_Org_ID=" + p_AD_Org_ID + ", C_BPartner_ID=" + p_C_BPartner_ID + + ", C_Order_ID=" + p_C_Order_ID + ", DocAction=" + p_docAction + + ", Consolidate=" + p_ConsolidateDocument); + // + String sql = null; + if (p_Selection) // VInvoiceGen + { + sql = "SELECT * FROM C_Order " + + "WHERE IsSelected='Y' AND DocStatus='CO' AND IsSOTrx='Y' " + + "ORDER BY M_Warehouse_ID, PriorityRule, C_BPartner_ID, C_Order_ID"; + } + else + { + sql = "SELECT * FROM C_Order o " + + "WHERE DocStatus IN('CO','CL') AND IsSOTrx='Y'"; + if (p_AD_Org_ID != 0) + sql += " AND AD_Org_ID=?"; + if (p_C_BPartner_ID != 0) + sql += " AND C_BPartner_ID=?"; + if (p_C_Order_ID != 0) + sql += " AND C_Order_ID=?"; + // + sql += " AND EXISTS (SELECT * FROM C_OrderLine ol " + + "WHERE o.C_Order_ID=ol.C_Order_ID AND ol.QtyOrdered<>ol.QtyInvoiced) " + + "ORDER BY M_Warehouse_ID, PriorityRule, C_BPartner_ID, C_Order_ID"; + } + // sql += " FOR UPDATE"; + + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + int index = 1; + if (!p_Selection && p_AD_Org_ID != 0) + pstmt.setInt(index++, p_AD_Org_ID); + if (!p_Selection && p_C_BPartner_ID != 0) + pstmt.setInt(index++, p_C_BPartner_ID); + if (!p_Selection && p_C_Order_ID != 0) + pstmt.setInt(index++, p_C_Order_ID); + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + return generate(pstmt); + } // doIt + + + /** + * Generate Shipments + * @param pstmt order query + * @return info + */ + private String generate (PreparedStatement pstmt) + { + try + { + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MOrder order = new MOrder (getCtx(), rs, get_TrxName()); + + // New Invoice Location + if (!p_ConsolidateDocument + || (m_invoice != null + && m_invoice.getC_BPartner_Location_ID() != order.getBill_Location_ID()) ) + completeInvoice(); + boolean completeOrder = MOrder.INVOICERULE_AfterOrderDelivered.equals(order.getInvoiceRule()); + + // Schedule After Delivery + boolean doInvoice = false; + if (MOrder.INVOICERULE_CustomerScheduleAfterDelivery.equals(order.getInvoiceRule())) + { + m_bp = new MBPartner (getCtx(), order.getBill_BPartner_ID(), null); + if (m_bp.getC_InvoiceSchedule_ID() == 0) + { + log.warning("BPartner has no Schedule - set to After Delivery"); + order.setInvoiceRule(MOrder.INVOICERULE_AfterDelivery); + order.save(); + } + else + { + MInvoiceSchedule is = MInvoiceSchedule.get(getCtx(), m_bp.getC_InvoiceSchedule_ID(), get_TrxName()); + if (is.canInvoice(order.getDateOrdered(), order.getGrandTotal())) + doInvoice = true; + else + continue; + } + } // Schedule + + // After Delivery + if (doInvoice || MOrder.INVOICERULE_AfterDelivery.equals(order.getInvoiceRule())) + { + MInOut[] shipments = order.getShipments(); + for (int i = 0; i < shipments.length; i++) + { + MInOut ship = shipments[i]; + if (!ship.isComplete() // ignore incomplete or reversals + || ship.getDocStatus().equals(MInOut.DOCSTATUS_Reversed)) + continue; + MInOutLine[] shipLines = ship.getLines(false); + for (int j = 0; j < shipLines.length; j++) + { + MInOutLine shipLine = shipLines[j]; + if (!order.isOrderLine(shipLine.getC_OrderLine_ID())) + continue; + if (!shipLine.isInvoiced()) + createLine (order, ship, shipLine); + } + m_line += 1000; + } + } + // After Order Delivered, Immediate + else + { + MOrderLine[] oLines = order.getLines(true, null); + for (int i = 0; i < oLines.length; i++) + { + MOrderLine oLine = oLines[i]; + BigDecimal toInvoice = oLine.getQtyOrdered().subtract(oLine.getQtyInvoiced()); + if (toInvoice.compareTo(Env.ZERO) == 0 && oLine.getM_Product_ID() != 0) + continue; + BigDecimal notInvoicedShipment = oLine.getQtyDelivered().subtract(oLine.getQtyInvoiced()); + // + boolean fullyDelivered = oLine.getQtyOrdered().compareTo(oLine.getQtyDelivered()) == 0; + + // Complete Order + if (completeOrder && !fullyDelivered) + { + log.fine("Failed CompleteOrder - " + oLine); + completeOrder = false; + break; + } + // Immediate + else if (MOrder.INVOICERULE_Immediate.equals(order.getInvoiceRule())) + { + log.fine("Immediate - ToInvoice=" + toInvoice + " - " + oLine); + BigDecimal qtyEntered = toInvoice; + // Correct UOM for QtyEntered + if (oLine.getQtyEntered().compareTo(oLine.getQtyOrdered()) != 0) + qtyEntered = toInvoice + .multiply(oLine.getQtyEntered()) + .divide(oLine.getQtyOrdered(), 12, BigDecimal.ROUND_HALF_UP); + createLine (order, oLine, toInvoice, qtyEntered); + } + else + log.fine("Failed: " + order.getInvoiceRule() + + " - ToInvoice=" + toInvoice + " - " + oLine); + } // for all order lines + if (MOrder.INVOICERULE_Immediate.equals(order.getInvoiceRule())) + m_line += 1000; + } + + // Complete Order successful + if (completeOrder && MOrder.INVOICERULE_AfterOrderDelivered.equals(order.getInvoiceRule())) + { + MInOut[] shipments = order.getShipments(); + for (int i = 0; i < shipments.length; i++) + { + MInOut ship = shipments[i]; + if (!ship.isComplete() // ignore incomplete or reversals + || ship.getDocStatus().equals(MInOut.DOCSTATUS_Reversed)) + continue; + MInOutLine[] shipLines = ship.getLines(false); + for (int j = 0; j < shipLines.length; j++) + { + MInOutLine shipLine = shipLines[j]; + if (!order.isOrderLine(shipLine.getC_OrderLine_ID())) + continue; + if (!shipLine.isInvoiced()) + createLine (order, ship, shipLine); + } + m_line += 1000; + } + } // complete Order + } // for all orders + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + completeInvoice(); + return "@Created@ = " + m_created; + } // generate + + + + /************************************************************************** + * Create Invoice Line from Order Line + * @param order order + * @param orderLine line + * @param qtyInvoiced qty + * @param qtyEntered qty + */ + private void createLine (MOrder order, MOrderLine orderLine, + BigDecimal qtyInvoiced, BigDecimal qtyEntered) + { + if (m_invoice == null) + { + m_invoice = new MInvoice (order, 0, p_DateInvoiced); + if (!m_invoice.save()) + throw new IllegalStateException("Could not create Invoice (o)"); + } + // + MInvoiceLine line = new MInvoiceLine (m_invoice); + line.setOrderLine(orderLine); + line.setQtyInvoiced(qtyInvoiced); + line.setQtyEntered(qtyEntered); + line.setLine(m_line + orderLine.getLine()); + if (!line.save()) + throw new IllegalStateException("Could not create Invoice Line (o)"); + log.fine(line.toString()); + } // createLine + + /** + * Create Invoice Line from Shipment + * @param order order + * @param ship shipment header + * @param sLine shipment line + */ + private void createLine (MOrder order, MInOut ship, MInOutLine sLine) + { + if (m_invoice == null) + { + m_invoice = new MInvoice (order, 0, p_DateInvoiced); + if (!m_invoice.save()) + throw new IllegalStateException("Could not create Invoice (s)"); + } + // Create Shipment Comment Line + if (m_ship == null + || m_ship.getM_InOut_ID() != ship.getM_InOut_ID()) + { + MDocType dt = MDocType.get(getCtx(), ship.getC_DocType_ID()); + if (m_bp == null || m_bp.getC_BPartner_ID() != ship.getC_BPartner_ID()) + m_bp = new MBPartner (getCtx(), ship.getC_BPartner_ID(), get_TrxName()); + + // Reference: Delivery: 12345 - 12.12.12 + MClient client = MClient.get(getCtx()); + String AD_Language = client.getAD_Language(); + if (client.isMultiLingualDocument() && m_bp.getAD_Language() != null) + AD_Language = m_bp.getAD_Language(); + if (AD_Language == null) + AD_Language = Language.getBaseAD_Language(); + java.text.SimpleDateFormat format = DisplayType.getDateFormat + (DisplayType.Date, Language.getLanguage(AD_Language)); + String reference = dt.getPrintName(m_bp.getAD_Language()) + + ": " + ship.getDocumentNo() + + " - " + format.format(ship.getMovementDate()); + m_ship = ship; + // + MInvoiceLine line = new MInvoiceLine (m_invoice); + line.setIsDescription(true); + line.setDescription(reference); + line.setLine(m_line + sLine.getLine() - 2); + if (!line.save()) + throw new IllegalStateException("Could not create Invoice Comment Line (sh)"); + // Optional Ship Address if not Bill Address + if (order.getBill_Location_ID() != ship.getC_BPartner_Location_ID()) + { + MLocation addr = MLocation.getBPLocation(getCtx(), ship.getC_BPartner_Location_ID(), null); + line = new MInvoiceLine (m_invoice); + line.setIsDescription(true); + line.setDescription(addr.toString()); + line.setLine(m_line + sLine.getLine() - 1); + if (!line.save()) + throw new IllegalStateException("Could not create Invoice Comment Line 2 (sh)"); + } + } + // + MInvoiceLine line = new MInvoiceLine (m_invoice); + line.setShipLine(sLine); + line.setQtyEntered(sLine.getQtyEntered()); + line.setQtyInvoiced(sLine.getMovementQty()); + line.setLine(m_line + sLine.getLine()); + if (!line.save()) + throw new IllegalStateException("Could not create Invoice Line (s)"); + // Link + sLine.setIsInvoiced(true); + if (!sLine.save()) + throw new IllegalStateException("Could not update Shipment Line"); + + log.fine(line.toString()); + } // createLine + + + /** + * Complete Invoice + */ + private void completeInvoice() + { + if (m_invoice != null) + { + if (!m_invoice.processIt(p_docAction)) + log.warning("completeInvoice - failed: " + m_invoice); + m_invoice.save(); + // + addLog(m_invoice.getC_Invoice_ID(), m_invoice.getDateInvoiced(), null, m_invoice.getDocumentNo()); + m_created++; + } + m_invoice = null; + m_ship = null; + m_line = 0; + } // completeInvoice + +} // InvoiceGenerate diff --git a/base/src/org/compiere/process/InvoiceNGL.java b/base/src/org/compiere/process/InvoiceNGL.java new file mode 100644 index 0000000000..05a436e2ff --- /dev/null +++ b/base/src/org/compiere/process/InvoiceNGL.java @@ -0,0 +1,368 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import java.math.*; + +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Invoice Not realized Gain & Loss. + * The actual data shown is T_InvoiceGL_v + * @author Jorg Janke + * @version $Id: InvoiceNGL.java,v 1.3 2006/08/04 03:53:59 jjanke Exp $ + */ +public class InvoiceNGL extends SvrProcess +{ + /** Mandatory Acct Schema */ + private int p_C_AcctSchema_ID = 0; + /** Mandatory Conversion Type */ + private int p_C_ConversionTypeReval_ID = 0; + /** Revaluation Date */ + private Timestamp p_DateReval = null; + /** Only AP/AR Transactions */ + private String p_APAR = "A"; + private static String ONLY_AP = "P"; + private static String ONLY_AR = "R"; + /** Report all Currencies */ + private boolean p_IsAllCurrencies = false; + /** Optional Invoice Currency */ + private int p_C_Currency_ID = 0; + /** GL Document Type */ + private int p_C_DocTypeReval_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_AcctSchema_ID")) + p_C_AcctSchema_ID = para[i].getParameterAsInt(); + else if (name.equals("C_ConversionTypeReval_ID")) + p_C_ConversionTypeReval_ID = para[i].getParameterAsInt(); + else if (name.equals("DateReval")) + p_DateReval = (Timestamp)para[i].getParameter(); + else if (name.equals("APAR")) + p_APAR = (String)para[i].getParameter(); + else if (name.equals("IsAllCurrencies")) + p_IsAllCurrencies = "Y".equals((String)para[i].getParameter()); + else if (name.equals("C_Currency_ID")) + p_C_Currency_ID = para[i].getParameterAsInt(); + else if (name.equals("C_DocTypeReval_ID")) + p_C_DocTypeReval_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + if (p_IsAllCurrencies) + p_C_Currency_ID = 0; + log.info("C_AcctSchema_ID=" + p_C_AcctSchema_ID + + ",C_ConversionTypeReval_ID=" + p_C_ConversionTypeReval_ID + + ",DateReval=" + p_DateReval + + ", APAR=" + p_APAR + + ", IsAllCurrencies=" + p_IsAllCurrencies + + ",C_Currency_ID=" + p_C_Currency_ID + + ", C_DocType_ID=" + p_C_DocTypeReval_ID); + + // Parameter + if (p_DateReval == null) + p_DateReval = new Timestamp(System.currentTimeMillis()); + + // Delete - just to be sure + String sql = "DELETE T_InvoiceGL WHERE AD_PInstance_ID=" + getAD_PInstance_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + if (no > 0) + log.info("Deleted #" + no); + + // Insert Trx + String dateStr = DB.TO_DATE(p_DateReval, true); + sql = "INSERT INTO T_InvoiceGL (AD_Client_ID, AD_Org_ID, IsActive, Created,CreatedBy, Updated,UpdatedBy," + + " AD_PInstance_ID, C_Invoice_ID, GrandTotal, OpenAmt, " + + " Fact_Acct_ID, AmtSourceBalance, AmtAcctBalance, " + + " AmtRevalDr, AmtRevalCr, C_DocTypeReval_ID, IsAllCurrencies, " + + " DateReval, C_ConversionTypeReval_ID, AmtRevalDrDiff, AmtRevalCrDiff, APAR) " + // -- + + "SELECT i.AD_Client_ID, i.AD_Org_ID, i.IsActive, i.Created,i.CreatedBy, i.Updated,i.UpdatedBy," + + getAD_PInstance_ID() + ", i.C_Invoice_ID, i.GrandTotal, invoiceOpen(i.C_Invoice_ID, 0), " + + " fa.Fact_Acct_ID, fa.AmtSourceDr-fa.AmtSourceCr, fa.AmtAcctDr-fa.AmtAcctCr, " + // AmtRevalDr, AmtRevalCr, + + " currencyConvert(fa.AmtSourceDr, i.C_Currency_ID, a.C_Currency_ID, " + dateStr + ", " + p_C_ConversionTypeReval_ID + ", i.AD_Client_ID, i.AD_Org_ID)," + + " currencyConvert(fa.AmtSourceCr, i.C_Currency_ID, a.C_Currency_ID, " + dateStr + ", " + p_C_ConversionTypeReval_ID + ", i.AD_Client_ID, i.AD_Org_ID)," + + (p_C_DocTypeReval_ID==0 ? "NULL" : String.valueOf(p_C_DocTypeReval_ID)) + ", " + + (p_IsAllCurrencies ? "'Y'," : "'N',") + + dateStr + ", " + p_C_ConversionTypeReval_ID + ", 0, 0, '" + p_APAR + "' " + // + + "FROM C_Invoice_v i" + + " INNER JOIN Fact_Acct fa ON (fa.AD_Table_ID=318 AND fa.Record_ID=i.C_Invoice_ID" + + " AND (i.GrandTotal=fa.AmtSourceDr OR i.GrandTotal=fa.AmtSourceCr))" + + " INNER JOIN C_AcctSchema a ON (fa.C_AcctSchema_ID=a.C_AcctSchema_ID) " + + "WHERE i.IsPaid='N'" + + " AND EXISTS (SELECT * FROM C_ElementValue ev " + + "WHERE ev.C_ElementValue_ID=fa.Account_ID AND (ev.AccountType='A' OR ev.AccountType='L'))" + + " AND fa.C_AcctSchema_ID=" + p_C_AcctSchema_ID; + if (!p_IsAllCurrencies) + sql += " AND i.C_Currency_ID<>a.C_Currency_ID"; + if (ONLY_AR.equals(p_APAR)) + sql += " AND i.IsSOTrx='Y'"; + else if (ONLY_AP.equals(p_APAR)) + sql += " AND i.IsSOTrx='N'"; + if (!p_IsAllCurrencies && p_C_Currency_ID != 0) + sql += " AND i.C_Currency_ID=" + p_C_Currency_ID; + + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.info("Inserted #" + no); + else if (CLogMgt.isLevelFiner()) + log.warning("Inserted #" + no + " - " + sql); + else + log.warning("Inserted #" + no); + + // Calculate Difference + sql = "UPDATE T_InvoiceGL gl " + + "SET (AmtRevalDrDiff,AmtRevalCrDiff)=" + + "(SELECT gl.AmtRevalDr-fa.AmtAcctDr, gl.AmtRevalCr-fa.AmtAcctCr " + + "FROM Fact_Acct fa " + + "WHERE gl.Fact_Acct_ID=fa.Fact_Acct_ID) " + + "WHERE AD_PInstance_ID=" + getAD_PInstance_ID(); + int noT = DB.executeUpdate(sql, get_TrxName()); + if (noT > 0) + log.config("Difference #" + noT); + + // Percentage + sql = "UPDATE T_InvoiceGL SET Percent = 100 " + + "WHERE GrandTotal=OpenAmt AND AD_PInstance_ID=" + getAD_PInstance_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no > 0) + log.info("Not Paid #" + no); + + sql = "UPDATE T_InvoiceGL SET Percent = ROUND(OpenAmt*100/GrandTotal,4) " + + "WHERE GrandTotal<>OpenAmt AND GrandTotal <> 0 AND AD_PInstance_ID=" + getAD_PInstance_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no > 0) + log.info("Partial Paid #" + no); + + sql = "UPDATE T_InvoiceGL SET AmtRevalDr = AmtRevalDr * Percent/100," + + " AmtRevalCr = AmtRevalCr * Percent/100," + + " AmtRevalDrDiff = AmtRevalDrDiff * Percent/100," + + " AmtRevalCrDiff = AmtRevalCrDiff * Percent/100 " + + "WHERE Percent <> 100 AND AD_PInstance_ID=" + getAD_PInstance_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no > 0) + log.config("Partial Calc #" + no); + + // Create Document + String info = ""; + if (p_C_DocTypeReval_ID != 0) + { + if (p_C_Currency_ID != 0) + log.warning("Can create Journal only for all currencies"); + else + info = createGLJournal(); + } + return "#" + noT + info; + } // doIt + + /** + * Create GL Journal + * @return document info + */ + private String createGLJournal() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM T_InvoiceGL " + + "WHERE AD_PInstance_ID=" + getAD_PInstance_ID() + + " ORDER BY AD_Org_ID"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + list.add (new X_T_InvoiceGL (getCtx(), rs, get_TrxName())); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (list.size() == 0) + return " - No Records found"; + + // + MAcctSchema as = MAcctSchema.get(getCtx(), p_C_AcctSchema_ID); + MAcctSchemaDefault asDefaultAccts = MAcctSchemaDefault.get(getCtx(), p_C_AcctSchema_ID); + MGLCategory cat = MGLCategory.getDefaultSystem(getCtx()); + if (cat == null) + { + MDocType docType = MDocType.get(getCtx(), p_C_DocTypeReval_ID); + cat = MGLCategory.get(getCtx(), docType.getGL_Category_ID()); + } + // + MJournalBatch batch = new MJournalBatch(getCtx(), 0, get_TrxName()); + batch.setDescription (getName()); + batch.setC_DocType_ID(p_C_DocTypeReval_ID); + batch.setDateDoc(new Timestamp(System.currentTimeMillis())); + batch.setDateAcct(p_DateReval); + batch.setC_Currency_ID(as.getC_Currency_ID()); + if (!batch.save()) + return " - Could not create Batch"; + // + MJournal journal = null; + BigDecimal drTotal = Env.ZERO; + BigDecimal crTotal = Env.ZERO; + int AD_Org_ID = 0; + for (int i = 0; i < list.size(); i++) + { + X_T_InvoiceGL gl = list.get(i); + if (gl.getAmtRevalDrDiff().signum() == 0 && gl.getAmtRevalCrDiff().signum() == 0) + continue; + MInvoice invoice = new MInvoice(getCtx(), gl.getC_Invoice_ID(), null); + if (invoice.getC_Currency_ID() == as.getC_Currency_ID()) + continue; + // + if (journal == null) + { + journal = new MJournal (batch); + journal.setC_AcctSchema_ID (as.getC_AcctSchema_ID()); + journal.setC_Currency_ID(as.getC_Currency_ID()); + journal.setC_ConversionType_ID(p_C_ConversionTypeReval_ID); + MOrg org = MOrg.get(getCtx(), gl.getAD_Org_ID()); + journal.setDescription (getName() + " - " + org.getName()); + journal.setGL_Category_ID (cat.getGL_Category_ID()); + if (!journal.save()) + return " - Could not create Journal"; + } + // + MJournalLine line = new MJournalLine(journal); + line.setLine((i+1) * 10); + line.setDescription(invoice.getSummary()); + // + MFactAcct fa = new MFactAcct (getCtx(), gl.getFact_Acct_ID(), null); + line.setC_ValidCombination_ID(MAccount.get(fa)); + BigDecimal dr = gl.getAmtRevalDrDiff(); + BigDecimal cr = gl.getAmtRevalCrDiff(); + drTotal = drTotal.add(dr); + crTotal = crTotal.add(cr); + line.setAmtSourceDr (dr); + line.setAmtAcctDr (dr); + line.setAmtSourceCr (cr); + line.setAmtAcctCr (cr); + line.save(); + // + if (AD_Org_ID == 0) // invoice org id + AD_Org_ID = gl.getAD_Org_ID(); + // Change in Org + if (AD_Org_ID != gl.getAD_Org_ID()) + { + createBalancing (asDefaultAccts, journal, drTotal, crTotal, AD_Org_ID, (i+1) * 10); + // + AD_Org_ID = gl.getAD_Org_ID(); + drTotal = Env.ZERO; + crTotal = Env.ZERO; + journal = null; + } + } + createBalancing (asDefaultAccts, journal, drTotal, crTotal, AD_Org_ID, (list.size()+1) * 10); + + return " - " + batch.getDocumentNo() + " #" + list.size(); + } // createGLJournal + + /** + * Create Balancing Entry + * @param asDefaultAccts acct schema default accounts + * @param journal journal + * @param drTotal dr + * @param crTotal cr + * @param AD_Org_ID org + * @param lineNo base line no + */ + private void createBalancing (MAcctSchemaDefault asDefaultAccts, MJournal journal, + BigDecimal drTotal, BigDecimal crTotal, int AD_Org_ID, int lineNo) + { + if (journal == null) + throw new IllegalArgumentException("Jornal is null"); + // CR Entry = Gain + if (drTotal.signum() != 0) + { + MJournalLine line = new MJournalLine(journal); + line.setLine(lineNo+1); + MAccount base = MAccount.get(getCtx(), asDefaultAccts.getUnrealizedGain_Acct()); + MAccount acct = MAccount.get(getCtx(), asDefaultAccts.getAD_Client_ID(), AD_Org_ID, + asDefaultAccts.getC_AcctSchema_ID(), base.getAccount_ID(), base.getC_SubAcct_ID(), + base.getM_Product_ID(), base.getC_BPartner_ID(), base.getAD_OrgTrx_ID(), + base.getC_LocFrom_ID(), base.getC_LocTo_ID(), base.getC_SalesRegion_ID(), + base.getC_Project_ID(), base.getC_Campaign_ID(), base.getC_Activity_ID(), + base.getUser1_ID(), base.getUser2_ID(), base.getUserElement1_ID(), base.getUserElement2_ID()); + line.setDescription(Msg.getElement(getCtx(), "UnrealizedGain_Acct")); + line.setC_ValidCombination_ID(acct.getC_ValidCombination_ID()); + line.setAmtSourceCr (drTotal); + line.setAmtAcctCr (drTotal); + line.save(); + } + // DR Entry = Loss + if (crTotal.signum() != 0) + { + MJournalLine line = new MJournalLine(journal); + line.setLine(lineNo+2); + MAccount base = MAccount.get(getCtx(), asDefaultAccts.getUnrealizedLoss_Acct()); + MAccount acct = MAccount.get(getCtx(), asDefaultAccts.getAD_Client_ID(), AD_Org_ID, + asDefaultAccts.getC_AcctSchema_ID(), base.getAccount_ID(), base.getC_SubAcct_ID(), + base.getM_Product_ID(), base.getC_BPartner_ID(), base.getAD_OrgTrx_ID(), + base.getC_LocFrom_ID(), base.getC_LocTo_ID(), base.getC_SalesRegion_ID(), + base.getC_Project_ID(), base.getC_Campaign_ID(), base.getC_Activity_ID(), + base.getUser1_ID(), base.getUser2_ID(), base.getUserElement1_ID(), base.getUserElement2_ID()); + line.setDescription(Msg.getElement(getCtx(), "UnrealizedLoss_Acct")); + line.setC_ValidCombination_ID(acct.getC_ValidCombination_ID()); + line.setAmtSourceDr (crTotal); + line.setAmtAcctDr (crTotal); + line.save(); + } + } // createBalancing + +} // InvoiceNGL diff --git a/base/src/org/compiere/process/InvoicePayScheduleValidate.java b/base/src/org/compiere/process/InvoicePayScheduleValidate.java new file mode 100644 index 0000000000..79c3723fbc --- /dev/null +++ b/base/src/org/compiere/process/InvoicePayScheduleValidate.java @@ -0,0 +1,92 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Validate Invoice Payment Schedule + * + * @author Jorg Janke + * @version $Id: InvoicePayScheduleValidate.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class InvoicePayScheduleValidate extends SvrProcess +{ + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info ("C_InvoicePaySchedule_ID=" + getRecord_ID()); + MInvoicePaySchedule[] schedule = MInvoicePaySchedule.getInvoicePaySchedule + (getCtx(), 0, getRecord_ID(), null); + if (schedule.length == 0) + throw new IllegalArgumentException("InvoicePayScheduleValidate - No Schedule"); + // Get Invoice + MInvoice invoice = new MInvoice (getCtx(), schedule[0].getC_Invoice_ID(), null); + if (invoice.get_ID() == 0) + throw new IllegalArgumentException("InvoicePayScheduleValidate - No Invoice"); + // + BigDecimal total = Env.ZERO; + for (int i = 0; i < schedule.length; i++) + { + BigDecimal due = schedule[i].getDueAmt(); + if (due != null) + total = total.add(due); + } + boolean valid = invoice.getGrandTotal().compareTo(total) == 0; + invoice.setIsPayScheduleValid(valid); + invoice.save(); + // Schedule + for (int i = 0; i < schedule.length; i++) + { + if (schedule[i].isValid() != valid) + { + schedule[i].setIsValid(valid); + schedule[i].save(); + } + } + String msg = "@OK@"; + if (!valid) + msg = "@GrandTotal@ = " + invoice.getGrandTotal() + + " <> @Total@ = " + total + + " - @Difference@ = " + invoice.getGrandTotal().subtract(total); + return Msg.parseTranslation(getCtx(), msg); + } // doIt + +} // InvoicePayScheduleValidate diff --git a/base/src/org/compiere/process/InvoicePrint.java b/base/src/org/compiere/process/InvoicePrint.java new file mode 100644 index 0000000000..aee8a1f4c4 --- /dev/null +++ b/base/src/org/compiere/process/InvoicePrint.java @@ -0,0 +1,328 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.io.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.print.*; +import org.compiere.util.*; + +/** + * Print Invoices on Paperor send PDFs + * + * @author Jorg Janke + * @version $Id: InvoicePrint.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class InvoicePrint extends SvrProcess +{ + /** Mail PDF */ + private boolean p_EMailPDF = false; + /** Mail Template */ + private int p_R_MailText_ID = 0; + + private Timestamp m_dateInvoiced_From = null; + private Timestamp m_dateInvoiced_To = null; + private int m_C_BPartner_ID = 0; + private int m_C_Invoice_ID = 0; + private String m_DocumentNo_From = null; + private String m_DocumentNo_To = null; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("DateInvoiced")) + { + m_dateInvoiced_From = ((Timestamp)para[i].getParameter()); + m_dateInvoiced_To = ((Timestamp)para[i].getParameter_To()); + } + else if (name.equals("EMailPDF")) + p_EMailPDF = "Y".equals(para[i].getParameter()); + else if (name.equals("R_MailText_ID")) + p_R_MailText_ID = para[i].getParameterAsInt(); + else if (name.equals("C_BPartner_ID")) + m_C_BPartner_ID = para[i].getParameterAsInt(); + else if (name.equals("C_Invoice_ID")) + m_C_Invoice_ID = para[i].getParameterAsInt(); + else if (name.equals("DocumentNo")) + { + m_DocumentNo_From = (String)para[i].getParameter(); + m_DocumentNo_To = (String)para[i].getParameter_To(); + } + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + if (m_DocumentNo_From != null && m_DocumentNo_From.length() == 0) + m_DocumentNo_From = null; + if (m_DocumentNo_To != null && m_DocumentNo_To.length() == 0) + m_DocumentNo_To = null; + } // prepare + + /** + * Perrform process. + * @return Message + * @throws Exception + */ + protected String doIt() throws java.lang.Exception + { + // Need to have Template + if (p_EMailPDF && p_R_MailText_ID == 0) + throw new AdempiereUserError ("@NotFound@: @R_MailText_ID@"); + + MMailText mText = null; + if (p_R_MailText_ID != 0) + { + mText = new MMailText(getCtx(), p_R_MailText_ID, get_TrxName()); + if (mText.get_ID() != p_R_MailText_ID) + throw new AdempiereUserError ("@NotFound@: @R_MailText_ID@ - " + p_R_MailText_ID); + } + + // Too broad selection + if (m_C_BPartner_ID == 0 && m_C_Invoice_ID == 0 && m_dateInvoiced_From == null && m_dateInvoiced_To == null + && m_DocumentNo_From == null && m_DocumentNo_To == null) + throw new AdempiereUserError ("@RestrictSelection@"); + + MClient client = MClient.get(getCtx()); + + // Get Info + StringBuffer sql = new StringBuffer ( + "SELECT i.C_Invoice_ID,bp.AD_Language,c.IsMultiLingualDocument," // 1..3 + // Prio: 1. BPartner 2. DocType, 3. PrintFormat (Org) // see ReportCtl+MInvoice + + " COALESCE(bp.Invoice_PrintFormat_ID, dt.AD_PrintFormat_ID, pf.Invoice_PrintFormat_ID)," // 4 + + " dt.DocumentCopies+bp.DocumentCopies," // 5 + + " bpc.AD_User_ID, i.DocumentNo," // 6..7 + + " bp.C_BPartner_ID " // 8 + + "FROM C_Invoice i" + + " INNER JOIN C_BPartner bp ON (i.C_BPartner_ID=bp.C_BPartner_ID)" + + " LEFT OUTER JOIN AD_User bpc ON (i.AD_User_ID=bpc.AD_User_ID)" + + " INNER JOIN AD_Client c ON (i.AD_Client_ID=c.AD_Client_ID)" + + " INNER JOIN AD_PrintForm pf ON (i.AD_Client_ID=pf.AD_Client_ID)" + + " INNER JOIN C_DocType dt ON (i.C_DocType_ID=dt.C_DocType_ID)") + .append(" WHERE pf.AD_Org_ID IN (0,i.AD_Org_ID) AND "); // more them 1 PF + boolean needAnd = false; + if (m_C_Invoice_ID != 0) + sql.append("i.C_Invoice_ID=").append(m_C_Invoice_ID); + else + { + if (m_C_BPartner_ID != 0) + { + sql.append ("i.C_BPartner_ID=").append (m_C_BPartner_ID); + needAnd = true; + } + if (m_dateInvoiced_From != null && m_dateInvoiced_To != null) + { + if (needAnd) + sql.append(" AND "); + sql.append("TRUNC(i.DateInvoiced) BETWEEN ") + .append(DB.TO_DATE(m_dateInvoiced_From, true)).append(" AND ") + .append(DB.TO_DATE(m_dateInvoiced_To, true)); + needAnd = true; + } + else if (m_dateInvoiced_From != null) + { + if (needAnd) + sql.append(" AND "); + sql.append("TRUNC(i.DateInvoiced) >= ") + .append(DB.TO_DATE(m_dateInvoiced_From, true)); + needAnd = true; + } + else if (m_dateInvoiced_To != null) + { + if (needAnd) + sql.append(" AND "); + sql.append("TRUNC(i.DateInvoiced) <= ") + .append(DB.TO_DATE(m_dateInvoiced_To, true)); + needAnd = true; + } + else if (m_DocumentNo_From != null && m_DocumentNo_To != null) + { + if (needAnd) + sql.append(" AND "); + sql.append("i.DocumentNo BETWEEN ") + .append(DB.TO_STRING(m_DocumentNo_From)).append(" AND ") + .append(DB.TO_STRING(m_DocumentNo_To)); + } + else if (m_DocumentNo_From != null) + { + if (needAnd) + sql.append(" AND "); + if (m_DocumentNo_From.indexOf('%') == -1) + sql.append("i.DocumentNo >= ") + .append(DB.TO_STRING(m_DocumentNo_From)); + else + sql.append("i.DocumentNo LIKE ") + .append(DB.TO_STRING(m_DocumentNo_From)); + } + } + sql.append(" ORDER BY i.C_Invoice_ID, pf.AD_Org_ID DESC"); // more than 1 PF record + log.fine(sql.toString()); + + MPrintFormat format = null; + int old_AD_PrintFormat_ID = -1; + int old_C_Invoice_ID = -1; + int C_BPartner_ID = 0; + int count = 0; + int errors = 0; + try + { + Statement stmt = DB.createStatement(); + ResultSet rs = stmt.executeQuery(sql.toString()); + while (rs.next()) + { + int C_Invoice_ID = rs.getInt(1); + if (C_Invoice_ID == old_C_Invoice_ID) // multiple pf records + continue; + old_C_Invoice_ID = C_Invoice_ID; + // Set Language when enabled + Language language = Language.getLoginLanguage(); // Base Language + String AD_Language = rs.getString(2); + if (AD_Language != null && "Y".equals(rs.getString(3))) + language = Language.getLanguage(AD_Language); + // + int AD_PrintFormat_ID = rs.getInt(4); + int copies = rs.getInt(5); + if (copies == 0) + copies = 1; + int AD_User_ID = rs.getInt(6); + MUser to = new MUser (getCtx(), AD_User_ID, get_TrxName()); + String DocumentNo = rs.getString(7); + C_BPartner_ID = rs.getInt(8); + // + String documentDir = client.getDocumentDir(); + if (documentDir == null || documentDir.length() == 0) + documentDir = "."; + // + if (p_EMailPDF && (to.get_ID() == 0 || to.getEMail() == null || to.getEMail().length() == 0)) + { + addLog (C_Invoice_ID, null, null, DocumentNo + " @RequestActionEMailNoTo@"); + errors++; + continue; + } + if (AD_PrintFormat_ID == 0) + { + addLog (C_Invoice_ID, null, null, DocumentNo + " No Print Format"); + errors++; + continue; + } + // Get Format & Data + if (AD_PrintFormat_ID != old_AD_PrintFormat_ID) + { + format = MPrintFormat.get (getCtx(), AD_PrintFormat_ID, false); + old_AD_PrintFormat_ID = AD_PrintFormat_ID; + } + format.setLanguage(language); + format.setTranslationLanguage(language); + // query + MQuery query = new MQuery("C_Invoice_Header_v"); + query.addRestriction("C_Invoice_ID", MQuery.EQUAL, new Integer(C_Invoice_ID)); + + // Engine + PrintInfo info = new PrintInfo( + DocumentNo, + X_C_Invoice.Table_ID, + C_Invoice_ID, + C_BPartner_ID); + info.setCopies(copies); + ReportEngine re = new ReportEngine(getCtx(), format, query, info); + boolean printed = false; + if (p_EMailPDF) + { + String subject = mText.getMailHeader() + " - " + DocumentNo; + EMail email = client.createEMail(to.getEMail(), subject, null); + if (!email.isValid()) + { + addLog (C_Invoice_ID, null, null, + DocumentNo + " @RequestActionEMailError@ Invalid EMail: " + to); + errors++; + continue; + } + mText.setUser(to); // Context + mText.setBPartner(C_BPartner_ID); // Context + mText.setPO(new MInvoice(getCtx(), C_Invoice_ID, get_TrxName())); + String message = mText.getMailText(true); + if (mText.isHtml()) + email.setMessageHTML(subject, message); + else + { + email.setSubject (subject); + email.setMessageText (message); + } + // + File invoice = null; + if (!Ini.isClient()) + invoice = new File(MInvoice.getPDFFileName(documentDir, C_Invoice_ID)); + File attachment = re.getPDF(invoice); + log.fine(to + " - " + attachment); + email.addAttachment(attachment); + // + String msg = email.send(); + MUserMail um = new MUserMail(mText, getAD_User_ID(), email); + um.save(); + if (msg.equals(EMail.SENT_OK)) + { + addLog (C_Invoice_ID, null, null, + DocumentNo + " @RequestActionEMailOK@ - " + to.getEMail()); + count++; + printed = true; + } + else + { + addLog (C_Invoice_ID, null, null, + DocumentNo + " @RequestActionEMailError@ " + msg + + " - " + to.getEMail()); + errors++; + } + } + else + { + re.print(); + count++; + printed = true; + } + // Print Confirm + if (printed) + { + StringBuffer sb = new StringBuffer ("UPDATE C_Invoice " + + "SET DatePrinted=SysDate, IsPrinted='Y' WHERE C_Invoice_ID=") + .append (C_Invoice_ID); + int no = DB.executeUpdate(sb.toString(), get_TrxName()); + } + } // for all entries + rs.close(); + stmt.close(); + } + catch (Exception e) + { + log.log(Level.SEVERE, "doIt - " + sql, e); + throw new Exception (e); + } + // + if (p_EMailPDF) + return "@Sent@=" + count + " - @Errors@=" + errors; + return "@Printed@=" + count; + } // doIt + +} // InvoicePrint diff --git a/base/src/org/compiere/process/InvoiceWriteOff.java b/base/src/org/compiere/process/InvoiceWriteOff.java new file mode 100644 index 0000000000..5d25f2cdeb --- /dev/null +++ b/base/src/org/compiere/process/InvoiceWriteOff.java @@ -0,0 +1,328 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Write-off Open Invoices + * + * @author Jorg Janke + * @version $Id: InvoiceWriteOff.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class InvoiceWriteOff extends SvrProcess +{ + /** BPartner */ + private int p_C_BPartner_ID = 0; + /** BPartner Group */ + private int p_C_BP_Group_ID = 0; + /** Invoice */ + private int p_C_Invoice_ID = 0; + + /** Max Amt */ + private BigDecimal p_MaxInvWriteOffAmt = Env.ZERO; + /** AP or AR */ + private String p_APAR = "R"; + private static String ONLY_AP = "P"; + private static String ONLY_AR = "R"; + + /** Invoice Date From */ + private Timestamp p_DateInvoiced_From = null; + /** Invoice Date To */ + private Timestamp p_DateInvoiced_To = null; + /** Accounting Date */ + private Timestamp p_DateAcct = null; + /** Create Payment */ + private boolean p_CreatePayment = false; + /** Bank Account */ + private int p_C_BankAccount_ID = 0; + /** Simulation */ + private boolean p_IsSimulation = true; + + /** Allocation Hdr */ + private MAllocationHdr m_alloc = null; + /** Payment */ + private MPayment m_payment = null; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = para[i].getParameterAsInt(); + else if (name.equals("C_BP_Group_ID")) + p_C_BP_Group_ID = para[i].getParameterAsInt(); + else if (name.equals("C_Invoice_ID")) + p_C_Invoice_ID = para[i].getParameterAsInt(); + // + else if (name.equals("MaxInvWriteOffAmt")) + p_MaxInvWriteOffAmt = (BigDecimal)para[i].getParameter(); + else if (name.equals("APAR")) + p_APAR = (String)para[i].getParameter(); + // + else if (name.equals("DateInvoiced")) + { + p_DateInvoiced_From = (Timestamp)para[i].getParameter(); + p_DateInvoiced_To = (Timestamp)para[i].getParameter_To(); + } + else if (name.equals("DateAcct")) + p_DateAcct = (Timestamp)para[i].getParameter(); + // + else if (name.equals("CreatePayment")) + p_CreatePayment = "Y".equals(para[i].getParameter()); + else if (name.equals("C_BankAccount_ID")) + p_C_BankAccount_ID = para[i].getParameterAsInt(); + // + else if (name.equals("IsSimulation")) + p_IsSimulation = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Execute + * @return message + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("C_BPartner_ID=" + p_C_BPartner_ID + + ", C_BP_Group_ID=" + p_C_BP_Group_ID + + ", C_Invoice_ID=" + p_C_Invoice_ID + + "; APAR=" + p_APAR + + ", " + p_DateInvoiced_From + " - " + p_DateInvoiced_To + + "; CreatePayment=" + p_CreatePayment + + ", C_BankAccount_ID=" + p_C_BankAccount_ID); + // + if (p_C_BPartner_ID == 0 && p_C_Invoice_ID == 0 && p_C_BP_Group_ID == 0) + throw new AdempiereUserError ("@FillMandatory@ @C_Invoice_ID@ / @C_BPartner_ID@ / "); + // + if (p_CreatePayment && p_C_BankAccount_ID == 0) + throw new AdempiereUserError ("@FillMandatory@ @C_BankAccount_ID@"); + // + StringBuffer sql = new StringBuffer( + "SELECT C_Invoice_ID,DocumentNo,DateInvoiced," + + " C_Currency_ID,GrandTotal, invoiceOpen(C_Invoice_ID, 0) AS OpenAmt " + + "FROM C_Invoice WHERE "); + if (p_C_Invoice_ID != 0) + sql.append("C_Invoice_ID=").append(p_C_Invoice_ID); + else + { + if (p_C_BPartner_ID != 0) + sql.append("C_BPartner_ID=").append(p_C_BPartner_ID); + else + sql.append("EXISTS (SELECT * FROM C_BPartner bp WHERE C_Invoice.C_BPartner_ID=bp.C_BPartner_ID AND bp.C_BP_Group_ID=") + .append(p_C_BP_Group_ID).append(")"); + // + if (ONLY_AR.equals(p_APAR)) + sql.append(" AND IsSOTrx='Y'"); + else if (ONLY_AP.equals(p_APAR)) + sql.append(" AND IsSOTrx='N'"); + // + if (p_DateInvoiced_From != null && p_DateInvoiced_To != null) + sql.append(" AND TRIM(DateInvoiced) BETWEEN ") + .append(DB.TO_DATE(p_DateInvoiced_From, true)) + .append(" AND ") + .append(DB.TO_DATE(p_DateInvoiced_To, true)); + else if (p_DateInvoiced_From != null) + sql.append(" AND TRIM(DateInvoiced) >= ") + .append(DB.TO_DATE(p_DateInvoiced_From, true)); + else if (p_DateInvoiced_To != null) + sql.append(" AND TRIM(DateInvoiced) <= ") + .append(DB.TO_DATE(p_DateInvoiced_To, true)); + } + sql.append(" AND IsPaid='N' ORDER BY C_Currency_ID, C_BPartner_ID, DateInvoiced"); + log.finer(sql.toString()); + // + int counter = 0; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + if (writeOff(rs.getInt(1), rs.getString(2), rs.getTimestamp(3), + rs.getInt(4), rs.getBigDecimal(6))); + counter++; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // final + processPayment(); + processAllocation(); + return "#" + counter; + } // doIt + + /** + * Write Off + * @param C_Invoice_ID invoice + * @param DocumentNo doc no + * @param DateInvoiced date + * @param C_Currency_ID currency + * @param OpenAmt open amt + * @return true if written off + */ + private boolean writeOff (int C_Invoice_ID, String DocumentNo, Timestamp DateInvoiced, + int C_Currency_ID, BigDecimal OpenAmt) + { + // Nothing to do + if (OpenAmt == null || OpenAmt.signum() == 0) + return false; + if (OpenAmt.abs().compareTo(p_MaxInvWriteOffAmt) >= 0) + return false; + // + if (p_IsSimulation) + { + addLog(C_Invoice_ID, DateInvoiced, OpenAmt, DocumentNo); + return true; + } + + // Invoice + MInvoice invoice = new MInvoice(getCtx(), C_Invoice_ID, get_TrxName()); + if (!invoice.isSOTrx()) + OpenAmt = OpenAmt.negate(); + + // Allocation + if (m_alloc == null || C_Currency_ID != m_alloc.getC_Currency_ID()) + { + processAllocation(); + m_alloc = new MAllocationHdr (getCtx(), true, + p_DateAcct, C_Currency_ID, + getProcessInfo().getTitle() + " #" + getAD_PInstance_ID(), get_TrxName()); + m_alloc.setAD_Org_ID(invoice.getAD_Org_ID()); + if (!m_alloc.save()) + { + log.log(Level.SEVERE, "Cannot create allocation header"); + return false; + } + } + // Payment + if (p_CreatePayment + && (m_payment == null + || invoice.getC_BPartner_ID() != m_payment.getC_BPartner_ID() + || C_Currency_ID != m_payment.getC_Currency_ID())) + { + processPayment(); + m_payment = new MPayment(getCtx(), 0, get_TrxName()); + m_payment.setAD_Org_ID(invoice.getAD_Org_ID()); + m_payment.setC_BankAccount_ID(p_C_BankAccount_ID); + m_payment.setTenderType(MPayment.TENDERTYPE_Check); + m_payment.setDateTrx(p_DateAcct); + m_payment.setDateAcct(p_DateAcct); + m_payment.setDescription(getProcessInfo().getTitle() + " #" + getAD_PInstance_ID()); + m_payment.setC_BPartner_ID(invoice.getC_BPartner_ID()); + m_payment.setIsReceipt(true); // payments are negative + m_payment.setC_Currency_ID(C_Currency_ID); + if (!m_payment.save()) + { + log.log(Level.SEVERE, "Cannot create payment"); + return false; + } + } + + // Line + MAllocationLine aLine = null; + if (p_CreatePayment) + { + aLine = new MAllocationLine (m_alloc, OpenAmt, + Env.ZERO, Env.ZERO, Env.ZERO); + m_payment.setPayAmt(m_payment.getPayAmt().add(OpenAmt)); + aLine.setC_Payment_ID(m_payment.getC_Payment_ID()); + } + else + aLine = new MAllocationLine (m_alloc, Env.ZERO, + Env.ZERO, OpenAmt, Env.ZERO); + aLine.setC_Invoice_ID(C_Invoice_ID); + if (aLine.save()) + { + addLog(C_Invoice_ID, DateInvoiced, OpenAmt, DocumentNo); + return true; + } + // Error + log.log(Level.SEVERE, "Cannot create allocation line for C_Invoice_ID=" + C_Invoice_ID); + return false; + } // writeOff + + /** + * Process Allocation + * @return true if processed + */ + private boolean processAllocation() + { + if (m_alloc == null) + return true; + processPayment(); + // Process It + if (m_alloc.processIt(DocAction.ACTION_Complete) && m_alloc.save()) + { + m_alloc = null; + return true; + } + // + m_alloc = null; + return false; + } // processAllocation + + /** + * Process Payment + * @return true if processed + */ + private boolean processPayment() + { + if (m_payment == null) + return true; + // Process It + if (m_payment.processIt(DocAction.ACTION_Complete) && m_payment.save()) + { + m_payment = null; + return true; + } + // + m_payment = null; + return false; + } // processPayment + +} // InvoiceWriteOff diff --git a/base/src/org/compiere/process/KIndexRerun.java b/base/src/org/compiere/process/KIndexRerun.java new file mode 100644 index 0000000000..d42266c8ed --- /dev/null +++ b/base/src/org/compiere/process/KIndexRerun.java @@ -0,0 +1,84 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; + +import org.compiere.model.*; + +/** + * Reindex all Content + * + * @author Yves Sandfort + * @version $Id$ + */ +public class KIndexRerun extends SvrProcess +{ + /** WebProject Parameter */ + private int p_CM_WebProject_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("CM_WebProject_ID")) + p_CM_WebProject_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + // ReIndex Container + int[] containers = MContainer.getAllIDs("CM_Container","CM_WebProject_ID=" + p_CM_WebProject_ID, get_TrxName()); + for(int i=0;i 0 "; + + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + if (cntu == -1) + raiseError( + "Update The PricePO to PriceLastPO of M_Product_PO WHERE (PricePO IS NULL OR PricePO = 0) AND PriceLastPO <> 0 ", + sqlupd); + totu += cntu; + log.fine("Updated " + cntu); + + sqlupd = "UPDATE M_Product_PO " + " SET PricePO = 0 " + + " WHERE PricePO IS NULL "; + + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + if (cntu == -1) + raiseError( + "Update The PricePO to Zero of M_Product_PO WHERE PricePO IS NULL", + sqlupd); + totu += cntu; + log.fine("Updated " + cntu); + // + // Set default current vendor + // + sqlupd = "UPDATE M_Product_PO " + " SET IsCurrentVendor = 'Y' " + + " WHERE IsCurrentVendor = 'N' " + " AND NOT EXISTS " + + " (SELECT pp.M_Product_ID " + " FROM M_Product_PO pp " + + " WHERE pp.M_Product_ID = M_Product_PO.M_Product_ID" + + " GROUP BY pp.M_Product_ID HAVING COUNT(*) > 1) "; + + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + if (cntu == -1) + raiseError("Update IsCurrentVendor to Y of M_Product_PO ", sqlupd); + totu += cntu; + log.fine("Updated " + cntu); + + DB.commit(true, get_TrxName()); + + // + // Make sure that we have only one active product + // + sql = "SELECT DISTINCT M_Product_ID " + " FROM M_Product_PO po " + + " WHERE IsCurrentVendor='Y' " + " AND IsActive='Y' " + + " AND EXISTS (SELECT M_Product_ID " + + " FROM M_Product_PO x " + + " WHERE x.M_Product_ID=po.M_Product_ID " + + " GROUP BY M_Product_ID " + " HAVING COUNT(*) > 1 ) "; + + PreparedStatement Cur_Duplicates = null; + Cur_Duplicates = DB.prepareStatement(sql, get_TrxName()); + ResultSet dupl = Cur_Duplicates.executeQuery(); + while (dupl.next()) { + sql = "SELECT M_Product_ID " + " ,C_BPartner_ID " + + " FROM M_Product_PO " + " WHERE IsCurrentVendor = 'Y' " + + " AND IsActive = 'Y' " + + " AND M_Product_ID = " + dupl.getInt("M_Product_ID") + + " ORDER BY PriceList DESC "; + + PreparedStatement Cur_Vendors = null; + Cur_Duplicates = DB.prepareStatement(sql, get_TrxName()); + ResultSet Vend = Cur_Vendors.executeQuery(); + // + // Leave First + // + Vend.next(); + while (Vend.next()) { + sqlupd = "UPDATE M_Product_PO " + + " SET IsCurrentVendor = 'N' " + + " WHERE M_Product_ID= " + Vend.getInt("M_Product_ID") + + " AND C_BPartner_ID= " + + Vend.getInt("C_BPartner_ID"); + + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + if (cntu == -1) + raiseError( + "Update IsCurrentVendor to N of M_Product_PO for a M_Product_ID and C_BPartner_ID ingresed", + sqlupd); + totu += cntu; + log.fine("Updated " + cntu); + + } + Vend.close(); + Cur_Vendors.close(); + Cur_Vendors = null; + + } + dupl.close(); + Cur_Duplicates.close(); + Cur_Duplicates = null; + + // + //Commit + // + + DB.commit(true, get_TrxName()); + + // + // Delete Old Data + // + if (p_DeleteOld == "Y") { + sqldel = "DELETE M_ProductPrice " + + " WHERE M_PriceList_Version_ID = " + + p_PriceList_Version_ID; + cntd = DB.executeUpdate(sqldel, get_TrxName()); + if (cntd == -1) + raiseError(" DELETE M_ProductPrice ", sqldel); + totd += cntd; + Message = "@Deleted@=" + cntd + " - "; + log.fine("Deleted " + cntd); + } + // + // Get PriceList Info + // + sql = "SELECT p.C_Currency_ID " + " , c.StdPrecision " + + " , v.AD_Client_ID " + " , v.AD_Org_ID " + " , v.UpdatedBy " + + " , v.M_DiscountSchema_ID " + + " , M_PriceList_Version_Base_ID " + " FROM M_PriceList p " + + " ,M_PriceList_Version v " + " ,C_Currency c " + + " WHERE p.M_PriceList_ID = v.M_PriceList_ID " + + " AND p.C_Currency_ID = c.C_Currency_ID" + + " AND v.M_PriceList_Version_ID = " + p_PriceList_Version_ID; + PreparedStatement curgen = null; + curgen = DB.prepareStatement(sql, get_TrxName()); + ResultSet v = curgen.executeQuery(); + while (v.next()) { + // + // For All Discount Lines in Sequence + // + sql = "SELECT m_discountschemaline_id" + + " ,ad_client_id" + " ,ad_org_id" + + " ,isactive" + " ,created" + + " ,createdby" + " ,updated" + + " ,updatedby" + " ,m_discountschema_id" + + " ,seqno" + " ,m_product_category_id" + + " ,c_bpartner_id" + " ,m_product_id" + + " ,conversiondate" + " ,list_base " + + " ,list_addamt" + " ,list_discount" + + " ,list_rounding" + " ,list_minamt" + + " ,list_maxamt" + " ,list_fixed" + + " ,std_base" + " ,std_addamt" + + " ,std_discount" + " ,std_rounding" + + " ,std_minamt" + " ,std_maxamt" + + " ,std_fixed" + " ,limit_base" + + " ,limit_addamt" + " ,limit_discount" + + " ,limit_rounding" + " ,limit_minamt" + + " ,limit_maxamt" + " ,limit_fixed" + + " ,c_conversiontype_id" + + " FROM M_DiscountSchemaLine" + + " WHERE M_DiscountSchema_ID=" + + v.getInt("M_DiscountSchema_ID") + + " AND IsActive='Y' ORDER BY SeqNo"; + PreparedStatement Cur_DiscountLine = null; + Cur_DiscountLine = DB.prepareStatement(sql, get_TrxName()); + ResultSet dl = Cur_DiscountLine.executeQuery(); + while (dl.next()) { + // + //Clear Temporary Table + // + sqldel = "DELETE FROM T_Selection "; + cntd = DB.executeUpdate(sqldel, get_TrxName()); + if (cntd == -1) + raiseError(" DELETE T_Selection ", sqldel); + totd += cntd; + log.fine("Deleted " + cntd); + // + //Create Selection in temporary table + // + V_temp = v.getInt("M_PriceList_Version_Base_ID"); + if (v.wasNull()) { + // + //Create Selection from M_Product_PO + // + sqlins = "INSERT INTO T_Selection (T_Selection_ID) " + + " SELECT DISTINCT po.M_Product_ID " + + " FROM M_Product p, M_Product_PO po" + + " WHERE p.M_Product_ID=po.M_Product_ID " + + " AND (p.AD_Client_ID=" + + v.getInt("AD_Client_ID") + + " OR p.AD_Client_ID=0)" + + " AND p.IsActive='Y' AND po.IsActive='Y' AND po.IsCurrentVendor='Y' " + // + //Optional Restrictions + // + // globalqss - detected bug, JDBC returns zero for null values + // so we're going to use NULLIF(value, 0) + + " AND (NULLIF(" + dl.getInt("M_Product_Category_ID") + + ",0) IS NULL OR p.M_Product_Category_ID=" + + dl.getInt("M_Product_Category_ID") + ")" + + " AND (NULLIF(" + dl.getInt("C_BPartner_ID") + + ",0) IS NULL OR po.C_BPartner_ID=" + + dl.getInt("C_BPartner_ID") + ")" + + " AND (NULLIF(" + dl.getInt("M_Product_ID") + + ",0) IS NULL OR p.M_Product_ID=" + + dl.getInt("M_Product_ID") + ")"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + if (cnti == -1) + raiseError(" INSERT INTO T_Selection ", sqlins); + toti += cnti; + log.fine("Inserted " + cnti); + + } else { + // + // Create Selection from existing PriceList + // + sqlins = "INSERT INTO T_Selection (T_Selection_ID)" + + " SELECT DISTINCT p.M_Product_ID" + + " FROM M_Product p, M_ProductPrice pp" + + " WHERE p.M_Product_ID=pp.M_Product_ID" + + " AND pp.M_PriceList_Version_ID = " + + v.getInt("M_PriceList_Version_Base_ID") + + " AND p.IsActive='Y' AND pp.IsActive='Y'" + // + //Optional Restrictions + // + + " AND (NULLIF(" + dl.getInt("M_Product_Category_ID") + + ",0) IS NULL OR p.M_Product_Category_ID=" + + dl.getInt("M_Product_Category_ID") + ")" + + " AND (NULLIF(" + dl.getInt("C_BPartner_ID") + + ",0) IS NULL OR EXISTS " + + " (SELECT m_product_id" + + " , c_bpartner_id" + + " , ad_client_id" + + " , ad_org_id" + + " , isactive" + + " , created " + + " , createdby" + + " , updated " + + " , updatedby" + + " , iscurrentvendor" + + " , c_uom_id" + + " , c_currency_id" + + " , pricelist" + + " , pricepo" + + " ,priceeffective" + + " ,pricelastpo" + + " ,pricelastinv" + + " ,vendorproductno" + + " ,upc" + + " ,vendorcategory" + + " ,discontinued" + + " ,discontinuedby" + + " ,order_min" + + " ,order_pack" + + " ,costperorder" + + " ,deliverytime_promised" + + " ,deliverytime_actual" + + " ,qualityrating" + + " ,royaltyamt" + + " , manufacturer FROM M_Product_PO po WHERE po.M_Product_ID=p.M_Product_ID AND po.C_BPartner_ID=" + + dl.getInt("C_BPartner_ID") + "))" + + " AND (NULLIF(" + dl.getInt("M_Product_ID") + + ",0) IS NULL OR p.M_Product_ID=" + + dl.getInt("M_Product_ID") + ")"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + if (cnti == -1) + raiseError( + " INSERT INTO T_Selection from existing PriceList", + sqlins); + toti += cnti; + log.fine("Inserted " + cnti); + + } + + Message = Message + "@Selected@=" + cnti; + + // + //Delete Prices in Selection, so that we can insert + // + V_temp = v.getInt("M_PriceList_Version_Base_ID"); + if (v.wasNull() || V_temp != p_PriceList_Version_ID) { + + sqldel = "DELETE M_ProductPrice pp" + + " WHERE pp.M_PriceList_Version_ID = " + + p_PriceList_Version_ID + + " AND EXISTS (SELECT t_selection_id FROM T_Selection s WHERE pp.M_Product_ID=s.T_Selection_ID)"; + + cntd = DB.executeUpdate(sqldel, get_TrxName()); + if (cntd == -1) + raiseError(" DELETE M_ProductPrice ", sqldel); + totd += cntd; + Message = Message + ", @Deleted@=" + cntd; + log.fine("Deleted " + cntd); + } + + // + // Copy (Insert) Prices + // + V_temp = v.getInt("M_PriceList_Version_Base_ID"); + if (V_temp == p_PriceList_Version_ID) + // + // We have Prices already + // + ; + else if (v.wasNull()) + // + //Copy and Convert from Product_PO + // + { + sqlins = "INSERT INTO M_ProductPrice " + + "(M_PriceList_Version_ID" + + " ,M_Product_ID " + + " ,AD_Client_ID" + + " , AD_Org_ID" + + " , IsActive" + + " , Created" + + " , CreatedBy" + + " , Updated" + + " , UpdatedBy" + + " , PriceList" + + " , PriceStd" + + " , PriceLimit) " + + "SELECT " + + p_PriceList_Version_ID + + " ,po.M_Product_ID " + + " ," + + v.getInt("AD_Client_ID") + + " ," + + v.getInt("AD_Org_ID") + + " ,'Y'" + + " ,SysDate," + + v.getInt("UpdatedBy") + + " ,SysDate," + + v.getInt("UpdatedBy") + // + //Price List + // + + " ,COALESCE(currencyConvert(po.PriceList, po.C_Currency_ID, " + + v.getInt("C_Currency_ID") + + ", ? , " + + dl.getInt("C_ConversionType_ID") + + ", " + + v.getInt("AD_Client_ID") + + ", " + + v.getInt("AD_Org_ID") + + "),0)" + + // Price Std + + " ,COALESCE(currencyConvert(po.PriceList, po.C_Currency_ID, " + + v.getInt("C_Currency_ID") + + ", ? , " + + dl.getInt("C_ConversionType_ID") + + ", " + + v.getInt("AD_Client_ID") + + ", " + + v.getInt("AD_Org_ID") + + "),0)" + + // Price Limit + + " ,COALESCE(currencyConvert(po.PricePO ,po.C_Currency_ID, " + + v.getInt("C_Currency_ID") + + ",? , " + + dl.getInt("C_ConversionType_ID") + + ", " + + v.getInt("AD_Client_ID") + + ", " + + v.getInt("AD_Org_ID") + + "),0)" + + " FROM M_Product_PO po " + + " WHERE EXISTS (SELECT * FROM T_Selection s WHERE po.M_Product_ID=s.T_Selection_ID) " + + " AND po.IsCurrentVendor='Y' AND po.IsActive='Y'"; + + PreparedStatement pstmt = DB.prepareStatement(sqlins, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_UPDATABLE, get_TrxName()); + pstmt.setTimestamp(1, dl.getTimestamp("ConversionDate")); + pstmt.setTimestamp(2, dl.getTimestamp("ConversionDate")); + pstmt.setTimestamp(3, dl.getTimestamp("ConversionDate")); + + cnti = pstmt.executeUpdate(); + if (cnti == -1) + raiseError( + " INSERT INTO T_Selection from existing PriceList", + sqlins); + toti += cnti; + log.fine("Inserted " + cnti); + } else { + // + //Copy and Convert from other PriceList_Version + // + sqlins = "INSERT INTO M_ProductPrice " + + " (M_PriceList_Version_ID, M_Product_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " PriceList, PriceStd, PriceLimit)" + + " SELECT " + + p_PriceList_Version_ID + + ", pp.M_Product_ID," + + v.getInt("AD_Client_ID") + + ", " + + v.getInt("AD_Org_ID") + + ", 'Y', SysDate, " + + v.getInt("UpdatedBy") + + ", SysDate, " + + v.getInt("UpdatedBy") + + " ," + // Price List + + "COALESCE(currencyConvert(pp.PriceList, pl.C_Currency_ID, " + + v.getInt("C_Currency_ID") + + ", ?, " + + dl.getInt("C_ConversionType_ID") + + ", " + + v.getInt("AD_Client_ID") + + ", " + + v.getInt("AD_Org_ID") + + "),0)," + // Price Std + + "COALESCE(currencyConvert(pp.PriceStd,pl.C_Currency_ID, " + + v.getInt("C_Currency_ID") + + " , ? , " + + dl.getInt("C_ConversionType_ID") + + ", " + + v.getInt("AD_Client_ID") + + ", " + + v.getInt("AD_Org_ID") + + "),0)," + //Price Limit + + " COALESCE(currencyConvert(pp.PriceLimit,pl.C_Currency_ID, " + + v.getInt("C_Currency_ID") + + " , ? , " + + dl.getInt("C_ConversionType_ID") + + ", " + + v.getInt("AD_Client_ID") + + ", " + + v.getInt("AD_Org_ID") + + "),0)" + + " FROM M_ProductPrice pp" + + " INNER JOIN M_PriceList_Version plv ON (pp.M_PriceList_Version_ID=plv.M_PriceList_Version_ID)" + + " INNER JOIN M_PriceList pl ON (plv.M_PriceList_ID=pl.M_PriceList_ID)" + + " WHERE pp.M_PriceList_Version_ID=" + + v.getInt("M_PriceList_Version_Base_ID") + + " AND EXISTS (SELECT * FROM T_Selection s WHERE pp.M_Product_ID=s.T_Selection_ID)" + + "AND pp.IsActive='Y'"; + + PreparedStatement pstmt = DB.prepareStatement(sqlins, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_UPDATABLE, get_TrxName()); + pstmt.setTimestamp(1, dl.getTimestamp("ConversionDate")); + pstmt.setTimestamp(2, dl.getTimestamp("ConversionDate")); + pstmt.setTimestamp(3, dl.getTimestamp("ConversionDate")); + + cnti = pstmt.executeUpdate(); + + if (cnti == -1) + raiseError( + " INSERT INTO T_Selection from existing PriceList", + sqlins); + toti += cnti; + log.fine("Inserted " + cnti); + + } + Message = Message + ", @Inserted@=" + cnti; + // + // Calculation + // + sqlupd = "UPDATE M_ProductPrice p " + + " SET PriceList = (DECODE( '" + + dl.getString("List_Base") + + "', 'S', PriceStd, 'X', PriceLimit, PriceList)" + + " + ?) * (1 - ?/100)," + " PriceStd = (DECODE('" + + dl.getString("Std_Base") + + "', 'L', PriceList, 'X', PriceLimit, PriceStd) " + + " + ?) * (1 - ?/100), " + " PriceLimit = (DECODE('" + + dl.getString("Limit_Base") + + "', 'L', PriceList, 'S', PriceStd, PriceLimit) " + + " + ?) * (1 - ? /100) " + + " WHERE M_PriceList_Version_ID = " + + p_PriceList_Version_ID + + " AND EXISTS (SELECT * FROM T_Selection s " + + " WHERE s.T_Selection_ID = p.M_Product_ID)"; + PreparedStatement pstmu = DB.prepareStatement(sqlupd, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_UPDATABLE, get_TrxName()); + + pstmu.setDouble(1, dl.getDouble("List_AddAmt")); + pstmu.setDouble(2, dl.getDouble("List_Discount")); + pstmu.setDouble(3, dl.getDouble("Std_AddAmt")); + pstmu.setDouble(4, dl.getDouble("Std_Discount")); + pstmu.setDouble(5, dl.getDouble("Limit_AddAmt")); + pstmu.setDouble(6, dl.getDouble("Limit_Discount")); + + cntu = pstmu.executeUpdate(); + + if (cntu == -1) + raiseError("Update M_ProductPrice ", sqlupd); + totu += cntu; + log.fine("Updated " + cntu); + + // + //Rounding (AD_Reference_ID=155) + // + sqlupd = "UPDATE M_ProductPrice p " + + " SET PriceList = DECODE('" + + dl.getString("List_Rounding") + "'," + + " 'N', PriceList, " + " '0', ROUND(PriceList, 0)," //Even .00 + + " 'D', ROUND(PriceList, 1)," //Dime .10 + + " 'T', ROUND(PriceList, -1), " //Ten 10.00 + + " '5', ROUND(PriceList*20,0)/20," //Nickle .05 + + " 'Q', ROUND(PriceList*4,0)/4," //Quarter .25 + + " ROUND(PriceList, " + v.getInt("StdPrecision") + + "))," //Currency + + " PriceStd = DECODE('" + dl.getString("Std_Rounding") + + "'," + " 'N', PriceStd, " + + " '0', ROUND(PriceStd, 0), " //Even .00 + + " 'D', ROUND(PriceStd, 1), " //Dime .10 + + "'T', ROUND(PriceStd, -1)," //Ten 10.00 + + "'5', ROUND(PriceStd*20,0)/20," //Nickle .05 + + "'Q', ROUND(PriceStd*4,0)/4," //Quarter .25 + + "ROUND(PriceStd, " + v.getInt("StdPrecision") + "))," //Currency + + "PriceLimit = DECODE('" + + dl.getString("Limit_Rounding") + "', " + + " 'N', PriceLimit, " + + " '0', ROUND(PriceLimit, 0), " // Even .00 + + " 'D', ROUND(PriceLimit, 1), " // Dime .10 + + " 'T', ROUND(PriceLimit, -1), " // Ten 10.00 + + " '5', ROUND(PriceLimit*20,0)/20, " // Nickle .05 + + " 'Q', ROUND(PriceLimit*4,0)/4, " //Quarter .25 + + " ROUND(PriceLimit, " + v.getInt("StdPrecision") + + ")) " // Currency + + " WHERE M_PriceList_Version_ID=" + + p_PriceList_Version_ID + + " AND EXISTS (SELECT * FROM T_Selection s " + + " WHERE s.T_Selection_ID=p.M_Product_ID)"; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + if (cntu == -1) + raiseError("Update M_ProductPrice ", sqlupd); + totu += cntu; + log.fine("Updated " + cntu); + + Message = Message + ", @Updated@=" + cntu; + // + //Fixed Price overwrite + // + sqlupd = "UPDATE M_ProductPrice p " + + " SET PriceList = DECODE('" + + dl.getString("List_Base") + "', 'F', " + + dl.getDouble("List_Fixed") + ", PriceList), " + + " PriceStd = DECODE('" + + dl.getString("Std_Base") + "', 'F', " + + dl.getDouble("Std_Fixed") + ", PriceStd)," + + " PriceLimit = DECODE('" + + dl.getString("Limit_Base") + "', 'F', " + + dl.getDouble("Limit_Fixed") + ", PriceLimit)" + + " WHERE M_PriceList_Version_ID=" + + p_PriceList_Version_ID + + " AND EXISTS (SELECT * FROM T_Selection s" + + " WHERE s.T_Selection_ID=p.M_Product_ID)"; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + if (cntu == -1) + raiseError("Update M_ProductPrice ", sqlupd); + totu += cntu; + log.fine("Updated " + cntu); + + v_NextNo = v_NextNo + 1; + addLog(0, null, null, Message); + Message = ""; + } + dl.close(); + Cur_DiscountLine.close(); + Cur_DiscountLine = null; + + // + // Delete Temporary Selection + // + sqldel = "DELETE FROM T_Selection "; + cntd = DB.executeUpdate(sqldel, get_TrxName()); + if (cntd == -1) + raiseError(" DELETE T_Selection ", sqldel); + totd += cntd; + log.fine("Deleted " + cntd); + + // + //commit; + // + log.fine("Committing ..."); + DB.commit(true, get_TrxName()); + + } + v.close(); + curgen.close(); + curgen = null; + + return "OK"; + + } // del doIt + + private void raiseError(String string, String sql) throws Exception { + DB.rollback(false, get_TrxName()); + String msg = string; + ValueNamePair pp = CLogger.retrieveError(); + if (pp != null) + msg = pp.getName() + " - "; + msg += sql; + throw new AdempiereUserError(msg); + } + +} // M_PriceList_Create + diff --git a/base/src/org/compiere/process/M_Product_BOM_Check.java b/base/src/org/compiere/process/M_Product_BOM_Check.java new file mode 100644 index 0000000000..0d93f59a98 --- /dev/null +++ b/base/src/org/compiere/process/M_Product_BOM_Check.java @@ -0,0 +1,162 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + * Portions created by Carlos Ruiz are Copyright (C) 2005 QSS Ltda. + * Contributor(s): Carlos Ruiz (globalqss) + *****************************************************************************/ +package org.compiere.process; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.logging.*; + +import org.compiere.model.X_M_Product; +import org.compiere.util.*; + +/** + * Title: Check BOM Structure (free of cycles) + * Description: + * Tree cannot contain BOMs which are already referenced + * + * @author Carlos Ruiz (globalqss) + * @version $Id: M_Product_BOM_Check.java,v 1.0 2005/09/17 13:32:00 globalqss Exp $ + */ +public class M_Product_BOM_Check extends SvrProcess +{ + + /** The Record */ + private int p_Record_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_Record_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt() throws Exception + { + StringBuffer sql1 = null; + int no = 0; + + log.info("Check BOM Structure"); + + // Record ID is M_Product_ID of product to be tested + X_M_Product xp = new X_M_Product(Env.getCtx(), p_Record_ID, get_TrxName()); + + if (! xp.isBOM()) { + log.info("NOT BOM Product"); + // No BOM - should not happen, but no problem + xp.setIsVerified(true); + xp.save(get_TrxName()); + return "OK"; + } + + // Table to put all BOMs - duplicate will cause exception + sql1 = new StringBuffer("DELETE FROM T_Selection2 WHERE Query_ID = 0"); + no = DB.executeUpdate(sql1.toString(), get_TrxName()); + sql1 = new StringBuffer("INSERT INTO T_Selection2 (Query_ID, T_Selection_ID) VALUES (0, " + p_Record_ID + ")"); + no = DB.executeUpdate(sql1.toString(), get_TrxName()); + // Table of root modes + sql1 = new StringBuffer("DELETE FROM T_Selection"); + no = DB.executeUpdate(sql1.toString(), get_TrxName()); + sql1 = new StringBuffer("INSERT INTO T_Selection (T_Selection_ID) VALUES (" + p_Record_ID + ")"); + no = DB.executeUpdate(sql1.toString(), get_TrxName()); + + while (true) { + + // Get count remaining on t_selection + int countno = 0; + try + { + PreparedStatement pstmt = DB.prepareStatement + ("SELECT COUNT(*) FROM T_Selection", get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + countno = rs.getInt(1); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + throw new Exception ("count t_selection", e); + } + log.fine("Count T_Selection =" + countno); + + if (countno == 0) + break; + + try + { + // if any command fails (no==-1) break and inform failure + // Insert BOM Nodes into "All" table + sql1 = new StringBuffer("INSERT INTO T_Selection2 (Query_ID, T_Selection_ID) SELECT 0, p.M_Product_ID FROM M_Product p WHERE IsBOM='Y' AND EXISTS (SELECT * FROM M_Product_BOM b WHERE p.M_Product_ID=b.M_ProductBOM_ID AND b.M_Product_ID IN (SELECT T_Selection_ID FROM T_Selection))"); + no = DB.executeUpdate(sql1.toString(), get_TrxName()); + if (no == -1) raiseError("InsertingRoot:ERROR", sql1.toString()); + // Insert BOM Nodes into temporary table + sql1 = new StringBuffer("DELETE FROM T_Selection2 WHERE Query_ID = 1"); + no = DB.executeUpdate(sql1.toString(), get_TrxName()); + if (no == -1) raiseError("InsertingRoot:ERROR", sql1.toString()); + sql1 = new StringBuffer("INSERT INTO T_Selection2 (Query_ID, T_Selection_ID) SELECT 1, p.M_Product_ID FROM M_Product p WHERE IsBOM='Y' AND EXISTS (SELECT * FROM M_Product_BOM b WHERE p.M_Product_ID=b.M_ProductBOM_ID AND b.M_Product_ID IN (SELECT T_Selection_ID FROM T_Selection))"); + no = DB.executeUpdate(sql1.toString(), get_TrxName()); + if (no == -1) raiseError("InsertingRoot:ERROR", sql1.toString()); + // Copy into root table + sql1 = new StringBuffer("DELETE FROM T_Selection"); + no = DB.executeUpdate(sql1.toString(), get_TrxName()); + if (no == -1) raiseError("InsertingRoot:ERROR", sql1.toString()); + sql1 = new StringBuffer("INSERT INTO T_Selection (T_Selection_ID) SELECT T_Selection_ID FROM T_Selection2 WHERE Query_ID = 1"); + no = DB.executeUpdate(sql1.toString(), get_TrxName()); + if (no == -1) raiseError("InsertingRoot:ERROR", sql1.toString()); + } + catch (Exception e) + { + throw new Exception ("root insert", e); + } + + } + + // Finish process + xp.setIsVerified(true); + xp.save(get_TrxName()); + return "OK"; + } // doIt + + private void raiseError(String string, String sql) throws Exception { + DB.rollback(false, get_TrxName()); + String msg = string; + ValueNamePair pp = CLogger.retrieveError(); + if (pp != null) + msg = pp.getName() + " - "; + msg += sql; + throw new AdempiereUserError (msg); + } + +} // M_Product_BOM_Check diff --git a/base/src/org/compiere/process/M_Product_Category_Acct_Copy.java b/base/src/org/compiere/process/M_Product_Category_Acct_Copy.java new file mode 100644 index 0000000000..6d531050a3 --- /dev/null +++ b/base/src/org/compiere/process/M_Product_Category_Acct_Copy.java @@ -0,0 +1,157 @@ +/****************************************************************************** + * The contents of this file are subject to the Compiere License Version 1.1 + * ("License"); You may not use this file except in compliance with the License + * You may obtain a copy of the License at http://www.compiere.org/license.html + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + * the specific language governing rights and limitations under the License. + * The Original Code is Compiere ERP & CRM Business Solution + * The Initial Developer of the Original Code is Jorg Janke and ComPiere, Inc. + * Portions created by Jorg Janke are Copyright (C) 1999-2005 Jorg Janke, parts + * created by ComPiere are Copyright (C) ComPiere, Inc.; All Rights Reserved. + * Portions created by Carlos Ruiz are Copyright (C) 2005 QSS Ltda. + * Contributor(s): Carlos Ruiz (globalqss) + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Copy and overwrite Accounts to products of this category + * + * @author Carlos Ruiz (globalqss) + * @version $Id: M_Product_Category_Acct_Copy.java,v 1.0 2005/09/15 22:19:00 globalqss Exp $ + */ +public class M_Product_Category_Acct_Copy extends SvrProcess +{ + + /* + * NOTE: The original oracle procedure M_Product_Category_Acct_Copy had a + * Product_Category_ID parameter for Direct Call not implemented in this class + */ + + /** The Product Category */ + private int m_Product_Category_ID = -1; + /** The Record */ + private int p_Record_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("M_Product_Category_ID")) + m_Product_Category_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_Record_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt() throws Exception + { + String sql; + String sqlupd; + String sqlins; + int cntu = 0; + int cnti = 0; + int totu = 0; + int toti = 0; + + log.info("Copy and overwrite Accounts to products of this category"); + + sql = "SELECT P_Revenue_Acct, P_Expense_Acct, P_Asset_Acct, P_CoGs_Acct, " + + "P_PurchasePriceVariance_Acct, P_InvoicePriceVariance_Acct, P_TradeDiscountRec_Acct, " + + "P_TradeDiscountGrant_Acct, C_AcctSchema_ID, M_Product_Category_ID " + + "FROM M_Product_Category_Acct " + + "WHERE M_Product_Category_ID = " + m_Product_Category_ID; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + // Update existing Products + sqlupd = "UPDATE M_Product_Acct " + + "SET P_Revenue_Acct= " + rs.getInt("P_REVENUE_ACCT") + ", " + + "P_Expense_Acct= " + rs.getInt("P_EXPENSE_ACCT") + ", " + + "P_Asset_Acct= " + rs.getInt("P_ASSET_ACCT") + ", " + + "P_CoGs_Acct= " + rs.getInt("P_COGS_ACCT") + ", " + + "P_PurchasePriceVariance_Acct= " + rs.getInt("P_PURCHASEPRICEVARIANCE_ACCT") + ", " + + "P_InvoicePriceVariance_Acct= " + rs.getInt("P_INVOICEPRICEVARIANCE_ACCT") + ", " + + "P_TradeDiscountRec_Acct= " + rs.getInt("P_TRADEDISCOUNTREC_ACCT") + ", " + + "P_TradeDiscountGrant_Acct= " + rs.getInt("P_TRADEDISCOUNTGRANT_ACCT") + ", " + + "Updated=SysDate, " + + "UpdatedBy=0 " + + "WHERE M_Product_Acct.C_AcctSchema_ID= " + rs.getInt("C_ACCTSCHEMA_ID") + " " + + "AND EXISTS (SELECT * FROM M_Product p " + + "WHERE p.M_Product_ID=M_Product_Acct.M_Product_ID " + + "AND p.M_Product_Category_ID= " + rs.getInt("M_PRODUCT_CATEGORY_ID") + ")"; + cntu = DB.executeUpdate(sqlupd); + totu += cntu; + // Insert new Products + sqlins = "INSERT INTO M_Product_Acct " + + "(M_Product_ID, C_AcctSchema_ID, " + + "AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, " + + "P_Revenue_Acct, P_Expense_Acct, P_Asset_Acct, P_CoGs_Acct, " + + "P_PurchasePriceVariance_Acct, P_InvoicePriceVariance_Acct, " + + "P_TradeDiscountRec_Acct, P_TradeDiscountGrant_Acct) " + + "SELECT p.M_Product_ID, " + rs.getInt("C_ACCTSCHEMA_ID") + ", " + + "p.AD_Client_ID, p.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0, " + + rs.getInt("P_REVENUE_ACCT") + ", " + + rs.getInt("P_EXPENSE_ACCT") + ", " + + rs.getInt("P_ASSET_ACCT") + ", " + + rs.getInt("P_COGS_ACCT") + ", " + + rs.getInt("P_PURCHASEPRICEVARIANCE_ACCT") + ", " + + rs.getInt("P_INVOICEPRICEVARIANCE_ACCT") + ", " + + rs.getInt("P_TRADEDISCOUNTREC_ACCT") + ", " + + rs.getInt("P_TRADEDISCOUNTGRANT_ACCT") + " " + + "FROM M_Product p " + + "WHERE p.M_Product_Category_ID=" + rs.getInt("M_PRODUCT_CATEGORY_ID") + " " + + "AND NOT EXISTS (SELECT * FROM M_Product_Acct pa " + + "WHERE pa.M_Product_ID=p.M_Product_ID " + + "AND pa.C_AcctSchema_ID=" + rs.getInt("C_ACCTSCHEMA_ID") + ")"; + cnti = DB.executeUpdate(sqlins); + toti += cnti; + log.info("Product = " + cntu + " / " + cnti); + } + rs.close(); + pstmt.close(); + pstmt = null; + log.fine("Committing ..."); + DB.commit(true, get_TrxName()); + } + catch (Exception e) + { + log.log(Level.SEVERE, "adding missing elements", e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + return "@Created@=" + cnti + ", @Updated@=" + cntu; + } // doIt + +} // M_Product_Category_Acct_Copy diff --git a/base/src/org/compiere/process/M_Product_CostingUpdate.java b/base/src/org/compiere/process/M_Product_CostingUpdate.java new file mode 100644 index 0000000000..0514559056 --- /dev/null +++ b/base/src/org/compiere/process/M_Product_CostingUpdate.java @@ -0,0 +1,290 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + * Portions created by Carlos Ruiz are Copyright (C) 2005 QSS Ltda. + * Contributor(s): Carlos Ruiz (globalqss) + *****************************************************************************/ +package org.compiere.process; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Title: Create the (new) costing information + * Description: + * - (optionally) update FutureCostPrice according to Parameter + * - (optionally) set CostStandard to FutureCostPrice + * - set CurrentCostPrice to cost depending on primary AcctSchema + * + * @author Carlos Ruiz (globalqss) + * @version $Id: M_Product_CostingUpdate.java,v 1.0 2005/09/26 22:28:00 globalqss Exp $ + */ +public class M_Product_CostingUpdate extends SvrProcess +{ + + /** The Record */ + private int p_Record_ID = 0; + private int p_AD_Client_ID = -1; + private int p_M_Product_Category_ID = -1; + private String p_SetFutureCostTo; + private int p_M_PriceList_Version_ID = -1; + private String p_SetStandardCost; + private String v_CostingMethod; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Client_ID")) + p_AD_Client_ID = para[i].getParameterAsInt(); + else if (name.equals("M_Product_Category_ID")) + p_M_Product_Category_ID = para[i].getParameterAsInt(); + else if (name.equals("SetFutureCostTo")) + p_SetFutureCostTo = (String) para[i].getParameter(); + else if (name.equals("M_PriceList_Version_ID")) + p_M_PriceList_Version_ID = para[i].getParameterAsInt(); + else if (name.equals("SetStandardCost")) + p_SetStandardCost = (String) para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_Record_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt() throws Exception + { + StringBuffer sql = null; + int no = 0; + int no1 = 0; + int no2 = 0; + + log.info("Create the (new) costing information"); + + // ========== (1) Set Future Cost To ========== + + if (p_SetFutureCostTo.equals("S")) { + // S - Standard Cost + log.info("Set to Standard Cost"); + sql = new StringBuffer( + "UPDATE M_Product_Costing " + + "SET FutureCostPrice = CostStandard " + + "WHERE AD_Client_ID=" + p_AD_Client_ID + " AND " + + "("+ p_M_Product_Category_ID + " = -1 OR " + + "EXISTS (SELECT * FROM M_Product p " + + "WHERE p.M_Product_Category_ID= " + p_M_Product_Category_ID + " " + + "AND p.M_Product_ID=M_Product_Costing.M_Product_ID))"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no == -1) raiseError("Set to Standard Cost:ERROR", sql.toString()); + + } else if (p_SetFutureCostTo.equals("DP")) { + // DP - Difference PO + log.info("Set to Difference PO"); + sql = new StringBuffer( + "UPDATE M_Product_Costing " + + "SET FutureCostPrice = CostStandard + (CostStandardPOAmt/CostStandardPOQty) " + + "WHERE CostStandardPOQty <> 0 AND " + + "CostStandardPOAmt <> 0 AND " + + "AD_Client_ID="+p_AD_Client_ID+" AND " + + "("+ p_M_Product_Category_ID + " = -1 OR " + + "EXISTS (SELECT * FROM M_Product p " + + "WHERE p.M_Product_Category_ID="+p_M_Product_Category_ID+" AND " + + "p.M_Product_ID=M_Product_Costing.M_Product_ID))"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no == -1) raiseError("Set to Difference PO:ERROR", sql.toString()); + + } else if (p_SetFutureCostTo.equals("DI")) { + // DI - Difference Invoice + log.info("Set to Difference Inv"); + sql = new StringBuffer( + "UPDATE M_Product_Costing " + + "SET FutureCostPrice = CostStandard + (CostStandardCumAmt/CostStandardCumQty) " + + "WHERE CostStandardCumQty <> 0 AND " + + "CostStandardCumAmt <> 0 AND " + + "AD_Client_ID="+p_AD_Client_ID+" AND " + + "("+ p_M_Product_Category_ID + " = -1 OR " + + "EXISTS (SELECT * FROM M_Product p " + + "WHERE p.M_Product_Category_ID="+p_M_Product_Category_ID+" AND " + + "p.M_Product_ID=M_Product_Costing.M_Product_ID))"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no == -1) raiseError("Set to Difference Inv:ERROR", sql.toString()); + + } else if (p_SetFutureCostTo.equals("P")) { + // P - Last PO Price + log.info("Set to PO Price"); + sql = new StringBuffer( + "UPDATE M_Product_Costing " + + "SET FutureCostPrice = PriceLastPO " + + "WHERE PriceLastPO <> 0 AND " + + "AD_Client_ID="+p_AD_Client_ID+" AND " + + "("+ p_M_Product_Category_ID + " = -1 OR " + + "EXISTS (SELECT * FROM M_Product p " + + "WHERE p.M_Product_Category_ID="+p_M_Product_Category_ID+" AND " + + "p.M_Product_ID=M_Product_Costing.M_Product_ID))"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no == -1) raiseError("Set to PO Price:ERROR", sql.toString()); + + } else if (p_SetFutureCostTo.equals("I")) { + // L - Last Inv Price + log.info("Set to Inv Price"); + sql = new StringBuffer( + "UPDATE M_Product_Costing " + + "SET FutureCostPrice = PriceLastInv " + + "WHERE PriceLastInv <> 0 AND " + + "AD_Client_ID="+p_AD_Client_ID+" AND " + + "("+ p_M_Product_Category_ID + " = -1 OR " + + "EXISTS (SELECT * FROM M_Product p " + + "WHERE p.M_Product_Category_ID="+p_M_Product_Category_ID+" AND " + + "p.M_Product_ID=M_Product_Costing.M_Product_ID))"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no == -1) raiseError("Set to Inv Price:ERROR", sql.toString()); + + } else if (p_SetFutureCostTo.equals("A")) { + // A - Average Cost + log.info("Set to Average Cost"); + sql = new StringBuffer( + "UPDATE M_Product_Costing " + + "SET FutureCostPrice = CostAverage " + + "WHERE CostAverage <> 0 AND " + + "AD_Client_ID="+p_AD_Client_ID+" AND " + + "("+ p_M_Product_Category_ID + " = -1 OR " + + "EXISTS (SELECT * FROM M_Product p " + + "WHERE p.M_Product_Category_ID="+p_M_Product_Category_ID+" AND " + + "p.M_Product_ID=M_Product_Costing.M_Product_ID))"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no == -1) raiseError("Set to Average Cost:ERROR", sql.toString()); + + } else if (p_SetFutureCostTo.equals("LL") && p_M_PriceList_Version_ID > 0) { + // A - Average Cost + log.info("Set to PriceList " + p_M_PriceList_Version_ID); + sql = new StringBuffer( + "UPDATE M_Product_Costing " + + "SET FutureCostPrice = " + + "(SELECT pp.PriceLimit " + + "FROM M_ProductPrice pp " + + "WHERE pp.M_PriceList_Version_ID="+p_M_PriceList_Version_ID+" AND " + + "pp.M_Product_ID=M_Product_Costing.M_Product_ID)" + +/** SET FutureCostPrice = C_Currency_Convert ( + -- Amount + (SELECT pp.PriceLimit FROM M_ProductPrice pp + WHERE pp.M_PriceList_Version_ID=11 + AND pp.M_Product_ID=M_Product_Costing.M_Product_ID), + -- Cur From + (SELECT C_Currency_ID FROM M_PriceList pl, M_PriceList_Version pv + WHERE pv.M_PriceList_ID=pl.M_PriceList_ID + AND pv.M_PriceList_Version_ID=11), + -- Cur To + (SELECT a.C_Currency_ID FROM C_AcctSchema a WHERE a.C_AcctSchema_ID=M_Product_Costing.C_AcctSchema_ID)) +**/ + "WHERE AD_Client_ID="+p_AD_Client_ID+ " " + + // we have a price + "AND EXISTS (SELECT * FROM M_ProductPrice pp " + + "WHERE pp.M_PriceList_Version_ID="+p_M_PriceList_Version_ID+" " + + "AND pp.M_Product_ID=M_Product_Costing.M_Product_ID) " + + // and the same currency + "AND EXISTS (SELECT * FROM C_AcctSchema a, M_PriceList pl, M_PriceList_Version pv " + + "WHERE a.C_AcctSchema_ID=M_Product_CostingUpdate.C_AcctSchema_ID " + + "AND pv.M_PriceList_Version_ID="+p_M_PriceList_Version_ID+" " + + "AND pv.M_PriceList_ID=pl.M_PriceList_ID " + + "AND pl.C_Currency_ID=a.C_Currency_ID) " + + "AND ("+p_M_Product_Category_ID+" = -1 OR " + + "EXISTS (SELECT * FROM M_Product p " + + "WHERE p.M_Product_Category_ID="+p_M_Product_Category_ID+" " + + "AND p.M_Product_ID=M_Product_Costing.M_Product_ID))"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no == -1) raiseError("Set to Average Cost:ERROR", sql.toString()); + + } else { + log.info("SetFutureCostTo=" + p_SetFutureCostTo + " ?"); + + } + log.info(" - Updated: " + no); + + // ========== (2) SetStandardCost ========== + if (p_SetStandardCost.equals("Y")) { + // A - Average Cost + log.info("Set Standard Cost"); + sql = new StringBuffer( + "UPDATE M_Product_Costing " + + "SET CostStandard = FutureCostPrice " + + "WHERE AD_Client_ID="+ p_AD_Client_ID + " AND " + + "(" + p_M_Product_Category_ID + " = -1 OR " + + "EXISTS (SELECT * FROM M_Product p " + + "WHERE p.M_Product_Category_ID="+p_M_Product_Category_ID+ " AND " + + "p.M_Product_ID=M_Product_Costing.M_Product_ID))"); + no1 = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no1 == -1) raiseError("Set Standard Cost", sql.toString()); + + } + + // ========== (3) Update CurrentCostPrice depending on Costing Method ========== + try + { + PreparedStatement pstmt = DB.prepareStatement + ("SELECT a.CostingMethod " + + "FROM C_AcctSchema a, AD_ClientInfo ci " + + "WHERE a.C_AcctSchema_ID=ci.C_AcctSchema1_ID AND " + + "ci.AD_Client_ID="+p_AD_Client_ID, get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + v_CostingMethod = rs.getString(1); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + throw new Exception ("select CostingMethod", e); + } + // (A)verage (S)tandard + log.info("Update Current Cost " + v_CostingMethod); + log.info("Set Standard Cost"); + sql = new StringBuffer( + "UPDATE M_Product_Costing " + + "SET CurrentCostPrice = " + + "DECODE ('"+ v_CostingMethod + "', 'A', CostAverage, CostStandard) " + + "WHERE AD_Client_ID="+p_AD_Client_ID); + no2 = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no2 == -1) raiseError("Set Standard Cost", sql.toString()); + log.info(" - Updated: " + no2); + + return "@Updated@: " + no + "/" + no1; + } // doIt + + private void raiseError(String string, String sql) throws Exception { + DB.rollback(false, get_TrxName()); + String msg = string; + ValueNamePair pp = CLogger.retrieveError(); + if (pp != null) + msg = pp.getName() + " - "; + msg += sql; + throw new AdempiereUserError (msg); + } + +} // M_Product_CostingUpdate diff --git a/base/src/org/compiere/process/M_Production_Run.java b/base/src/org/compiere/process/M_Production_Run.java new file mode 100644 index 0000000000..9b9ccda76c --- /dev/null +++ b/base/src/org/compiere/process/M_Production_Run.java @@ -0,0 +1,503 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + * Portions created by Layda Salas are Copyright (C) 2005 QSS Ltda. + * Contributor(s): Layda Salas (globalqss) + *****************************************************************************/ + +package org.compiere.process; + +import java.sql.*; +import java.util.logging.*; + +import org.compiere.model.MSequence; +import org.compiere.util.*; + +/** + * Copy and overwrite Accounts to products of this category + * + * @author Layda Salas (globalqss) + * @version $Id: M_Production_Run,v 1.0 2005/10/09 22:19:00 globalqss Exp $ + */ +public class M_Production_Run extends SvrProcess { + + /** The Record */ + private int p_Record_ID = 0; + + private String mustBeStocked; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("MustBeStocked")) + mustBeStocked = (String) para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_Record_ID = getRecord_ID(); + } //prepare + + /** + * Process + * + * @return message + * @throws Exception + */ + + protected String doIt() throws Exception { + String sql; + String sqlupd; + String sqlins; + String sqldel; + int cntu = 0; + int cntd = 0; + int cnti = 0; + int totu = 0; + int toti = 0; + int totd = 0; + int nextNo; + boolean isCreated = false; + boolean processed = false; + int ad_Client_ID = 0; + int ad_Org_ID = 0; + + log.info("Search fields in M_Production"); + + /** + * Get Info + Lock + */ + sql = " SELECT IsCreated " + ", Processed " + ", AD_Client_ID " + + ", AD_Org_ID " + " FROM M_Production " + + " WHERE M_Production_ID = " + p_Record_ID; + PreparedStatement pstmt = DB.prepareStatement(sql, get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + isCreated = rs.getString("IsCreated").equals("Y"); + processed = rs.getString("Processed").equals("Y"); + ad_Client_ID = rs.getInt("AD_Client_ID"); + ad_Org_ID = rs.getInt("AD_Org_ID"); + } + rs.close(); + pstmt.close(); + pstmt = null; + + /** + * No Action + */ + if (processed) { + log.info("Already Posted"); + return "@AlreadyPosted@"; + } + + /*********************************************************************** + * Create Lines + */ + if (!isCreated) { + // For every Production Plan + sql = "SELECT m_productionplan_id " + " ,ad_client_id " + + " ,ad_org_id " + " ,isactive " + " ,created " + + " ,createdby " + " ,updated " + " ,updatedby " + + " ,m_production_id " + " ,line " + " ,m_product_id " + + " ,productionqty " + " ,m_locator_id " + + " ,description " + " ,processed " + + " FROM M_ProductionPlan " + " WHERE M_Production_ID= " + + p_Record_ID + " ORDER BY Line, M_Product_ID"; + PreparedStatement curpp = null; + curpp = DB.prepareStatement(sql, get_TrxName()); + ResultSet pp = curpp.executeQuery(); + while (pp.next()) { + // Delete prior lines + sqldel = "DELETE M_ProductionLine " + + "WHERE M_ProductionPlan_ID =" + + pp.getInt("M_ProductionPlan_ID"); + + cntd = DB.executeUpdate(sqldel, get_TrxName()); + if (cntd == -1) + raiseError("Deleting Production Line:ERROR", sqldel); + totd += cntd; + + // OriginLine + int line = 100; + // Getsequenses + nextNo = MSequence.getNextID(ad_Client_ID, "M_ProductionLine", + get_TrxName()); + // INSERT IN M_ProductionLine + sqlins = "INSERT INTO M_ProductionLine " + + "(M_ProductionLine_ID " + ", M_ProductionPlan_ID" + + ", Line " + ", AD_Client_ID " + ", AD_Org_ID " + + ", IsActive " + ", Created " + ", CreatedBy " + + ", Updated " + ", UpdatedBy " + ", M_Product_ID " + + ", MovementQty " + ", M_Locator_ID " + + ", Description) " + " VALUES ( " + nextNo + ", " + + pp.getInt("M_ProductionPlan_ID") + ", " + line + ", " + + pp.getInt("ad_client_id") + ", " + + pp.getInt("AD_Org_ID") + ", 'Y' " + ", sysdate " + + ", 0 " + ", sysdate " + ", 0 " + ", " + + pp.getInt("M_Product_ID") + ", " + + pp.getInt("ProductionQty") + ", " + + pp.getInt("M_Locator_ID") + ", '" + + pp.getString("Description") + "')"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + if (cnti == -1) + raiseError("INSERT IN M_ProductionLine", sqlins); + toti += cnti; + // Create First Level + sql = " SELECT m_product_bom_id, " + "ad_client_id, " + + "ad_org_id, " + "isactive, " + "created, " + + "createdby, " + "updated, " + "updatedby, " + + "line, " + "m_product_id, " + "m_productbom_id, " + + "bomqty, " + "description, " + "bomtype " + + " FROM M_Product_BOM " + " WHERE M_Product_ID=" + + pp.getInt("M_product_id") + " ORDER BY Line"; + PreparedStatement curbom = null; + curbom = DB.prepareStatement(sql, get_TrxName()); + ResultSet bom = curbom.executeQuery(); + while (bom.next()) { + line = line + 100; + nextNo = MSequence.getNextID(pp.getInt("ad_client_id"), + "M_ProductionLine", get_TrxName()); + sqlins = "INSERT INTO M_ProductionLine " + + "(M_ProductionLine_ID, M_ProductionPlan_ID, Line, " + + "AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy, " + + "M_Product_ID, MovementQty, M_Locator_ID) " + + "VALUES " + + "(" + + nextNo + + "," + + pp.getInt("M_ProductionPlan_ID") + + "," + + line + + "," + + pp.getInt("AD_Client_ID") + + "," + + pp.getInt("AD_Org_ID") + + ",'Y',SysDate,0,SysDate,0" + + "," + + bom.getInt("M_ProductBOM_ID") + + "," + + (-pp.getInt("ProductionQty") * bom + .getInt("BOMQty")) + "," + + pp.getInt("M_Locator_ID") + ")"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + if (cnti == -1) + raiseError("INSERT IN M_ProductionLine First Level", + sqlins); + toti += cnti; + } + bom.close(); + curbom.close(); + curbom = null; + + // While we have BOMs + while (true) { + // Are there non-stored BOMs to list details? + sql = " SELECT COUNT(*) " + " FROM M_ProductionLine pl" + + " , M_Product p " + + " WHERE pl.M_Product_ID=p.M_Product_ID " + + " AND pl.M_ProductionPlan_ID=" + + pp.getInt("M_ProductionPlan_ID") + + " AND pl.Line<>100 " // Origin Line + + " AND p.IsBOM='Y' AND " + " p.IsStocked='N'"; + + PreparedStatement cntlp = null; + cntlp = DB.prepareStatement(sql, get_TrxName()); + ResultSet ct = cntlp.executeQuery(); + int countNo = 0; + if (ct.next()) + countNo = ct.getInt(1); + ct.close(); + cntlp.close(); + cntlp = null; + + // Nothing to do + if (countNo == 0) + break; + + // Resolve BOMs in ProductLine which are not stocked + sql = " SELECT pl.M_ProductionLine_ID, " + + " pl.Line, " + + " pl.M_Product_ID," + + " pl.MovementQty " + + " FROM M_ProductionLine pl, " + + " M_Product p " + + " WHERE pl.M_ProductionPlan_ID = " + + pp.getInt("M_ProductionPlan_ID") + + " AND pl.M_Product_ID = p.M_Product_ID " + + " AND pl.Line<>100 " // Origin Line + + " AND p.IsBOM='Y' AND p.IsStocked='N' "; + PreparedStatement curPLineBOM = null; + curPLineBOM = DB.prepareStatement(sql, get_TrxName()); + ResultSet pl = curPLineBOM.executeQuery(); + while (pl.next()) { + line = pl.getInt("line"); + + // Resolve BOM Line in product line + sql = " SELECT m_product_bom_id, " + "ad_client_id, " + + "ad_org_id, " + "isactive, " + "created, " + + "createdby, " + "updated, " + "updatedby, " + + "line, " + "m_product_id, " + + "m_productbom_id, " + "bomqty, " + + "description, " + "bomtype " + + " FROM M_Product_BOM " + + " WHERE M_Product_ID=" + + pl.getInt("M_Product_ID") + " ORDER BY Line"; + PreparedStatement curbom1 = null; + curbom1 = DB.prepareStatement(sql, get_TrxName()); + ResultSet bom1 = curbom1.executeQuery(); + while (bom1.next()) { + line = line + 10; + nextNo = MSequence.getNextID(pp + .getInt("ad_client_id"), + "M_ProductionLine", get_TrxName()); + sqlins = " INSERT INTO M_ProductionLine " + + " (M_ProductionLine_ID, M_ProductionPlan_ID, Line, " + + "AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy, " + + " M_Product_ID, MovementQty, M_Locator_ID) " + + " VALUES " + + "(" + + nextNo + + "," + + pp.getInt("M_ProductionPlan_ID") + + "," + + line + + "," + + pp.getInt("AD_Client_ID") + + "," + + pp.getInt("AD_Org_ID") + + ",'Y',SysDate,0,SysDate,0" + + "," + + bom1.getInt("M_ProductBOM_ID") + + "," + + (pl.getInt("MovementQty") * bom1 + .getInt("BOMQty")) + "," + + pp.getInt("M_Locator_ID") + ")"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + if (cnti == -1) + raiseError( + "INSERT IN M_ProductionLine For Resolve BOM Line in product line", + sqlins); + toti += cnti; + + } + bom1.close(); + curbom1.close(); + curbom1 = null; + + //Delete BOM line + sqldel = " DELETE M_ProductionLine " + + " WHERE M_ProductionLine_ID= " + + pl.getInt("M_ProductionLine_ID"); + + cntd = DB.executeUpdate(sqldel, get_TrxName()); + if (cntd == -1) + raiseError("Delete BOM line", sqldel); + totd += cntd; + } + pl.close(); + curPLineBOM.close(); + curPLineBOM = null; + } + } + pp.close(); + curpp.close(); + curpp = null; + + // Modifying locator to have sufficient stock + // Indicate that it is Created + sqlupd = " UPDATE M_Production " + " SET IsCreated='Y' " + + " WHERE M_Production_ID=" + p_Record_ID; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + if (cntu == -1) + raiseError("Modifying locator to have sufficient stock", sqlupd); + totu += cntu; + + /******************************************************************* + * Post Lines + */ + } else { + + // All Production Lines + sql = " SELECT pl.M_ProductionLine_ID, pl.AD_Client_ID, pl.AD_Org_ID,p.MovementDate, " + + " pl.M_Product_ID, pl.M_AttributeSetInstance_ID, pl.MovementQty,pl.M_Locator_ID " + + " FROM M_Production p, M_ProductionLine pl, M_ProductionPlan pp " + + " WHERE p.M_Production_ID=pp.M_Production_ID " + + " AND pp.M_ProductionPlan_ID=pl.M_ProductionPlan_ID " + + " AND pp.M_Production_ID= " + + p_Record_ID + + " ORDER BY pp.Line, pl.Line"; + + PreparedStatement CUR_PL_Post = null; + + CUR_PL_Post = DB.prepareStatement(sql, get_TrxName()); + ResultSet pl = CUR_PL_Post.executeQuery(); + while (pl.next()) { + sql = " select bomQtyOnHand (" + pl.getInt("M_Product_ID") + + ", null," + pl.getInt("M_Locator_ID") + ")"; + PreparedStatement cnsql = null; + cnsql = DB.prepareStatement(sql, get_TrxName()); + ResultSet cs = cnsql.executeQuery(); + int countTo = 0; + if (cs.next()) + countTo = cs.getInt(1); + cs.close(); + cnsql.close(); + cnsql = null; + + // Check Stock levels for reductions + if ((pl.getInt("MovementQty") < 0) + && ((countTo) + pl.getInt("MovementQty") < 0)) + + { + + DB.rollback(true, get_TrxName()); + + sql = " SELECT '@NotEnoughStocked@: ' || Name "//INTO + // Message + + " FROM M_Product WHERE M_Product_ID=" + + pl.getInt("M_Product_ID"); + PreparedStatement cnMess = null; + cnMess = DB.prepareStatement(sql, get_TrxName()); + ResultSet cm = cnMess.executeQuery(); + String varmess = null; + if (cm.next()) + varmess = cm.getString(1); + cm.close(); + cnMess.close(); + cnMess = null; + return varmess; + + } + + // Adjust Quantity at Location + sqlupd = " UPDATE M_Storage " + " SET QtyOnHand = QtyOnHand + " + + pl.getInt("MovementQty") + "," + + " Updated = SysDate " + " WHERE M_Locator_ID = " + + pl.getInt("M_Locator_ID") + + " AND M_AttributeSetInstance_ID = COALESCE(" + + pl.getInt("M_AttributeSetInstance_ID") + ",0)" + + " AND M_Product_ID =" + pl.getInt("M_Product_ID"); + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + if (cntu == -1) + raiseError("Adjust Quantity at Location", sqlupd); + totu += cntu; + + // Product not on Stock yet + if (cntu == 0) { + sqlins = "INSERT INTO M_Storage " + + " (M_Product_ID, M_Locator_ID, M_AttributeSetInstance_ID, " + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, " + + " QtyOnHand, QtyReserved, QtyOrdered) " + + " VALUES " + "(" + pl.getInt("M_Product_ID") + + "," + pl.getInt("M_Locator_ID") + ", COALESCE(" + + pl.getInt("M_AttributeSetInstance_ID") + ",0), " + + pl.getInt("AD_Client_ID") + "," + + pl.getInt("AD_Org_ID") + + ", 'Y', SysDate, 0, SysDate, 0, " + + pl.getInt("MovementQty") + ", 0, 0)"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + if (cnti == -1) + raiseError(" Product not on Stock yet", sqlins); + toti += cnti; + + } + + // Create Transaction Entry + nextNo = MSequence.getNextID(pl.getInt("AD_Org_ID"), + "M_Transaction", get_TrxName()); + sqlins = " INSERT INTO M_Transaction" + + " (M_Transaction_ID, M_ProductionLine_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " MovementType, M_Locator_ID, M_Product_ID, M_AttributeSetInstance_ID," + + " MovementDate, MovementQty)" + " VALUES " + + "(?,?,?,?,'Y',SysDate,0,SysDate,0," + + "'P+',?,?,COALESCE(?,0)," // not distinguishing + // between + // assemby/disassembly + + "?,?)"; + pstmt = DB.prepareStatement(sqlins, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_UPDATABLE, get_TrxName()); + pstmt.setInt(1, nextNo); + pstmt.setInt(2, pl.getInt("M_ProductionLine_ID")); + pstmt.setInt(3, pl.getInt("AD_Client_ID")); + pstmt.setInt(4, pl.getInt("AD_Org_ID")); + pstmt.setInt(5, pl.getInt("M_Locator_ID")); + pstmt.setInt(6, pl.getInt("M_Product_ID")); + pstmt.setInt(7, pl.getInt("M_AttributeSetInstance_ID")); + pstmt.setTimestamp(8, pl.getTimestamp("MovementDate")); + pstmt.setDouble(9, pl.getDouble("MovementQty")); + cnti = pstmt.executeUpdate(); + // + if (cnti == -1) + raiseError("Create Transaction Entry", sqlins); + toti += cnti; + + // Update M_ProductionLine + sqlupd = " UPDATE M_ProductionLine " + " SET Processed='Y' " + + " WHERE M_ProductionLine_ID=" + + pl.getInt("M_ProductionLine_ID"); + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + if (cntu == -1) + raiseError("Update M_ProductionLine ", sqlupd); + totu += cntu; + + } + pl.close(); + CUR_PL_Post.close(); + CUR_PL_Post = null; + + // Indicate that we are done + sqlupd = "UPDATE M_Production " + "SET Processed='Y' " + + "WHERE M_Production_ID=" + p_Record_ID; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + if (cntu == -1) + raiseError("Indicate that we are done ", sqlupd); + totu += cntu; + + sqlupd = " UPDATE M_ProductionPlan " + " SET Processed='Y' " + + " WHERE M_Production_ID=" + p_Record_ID; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + if (cntu == -1) + raiseError( + "Update the indicator of Processed in M_ProductionPlan", + sqlupd); + totu += cntu; + } + + // Only commit when entire job successful + log.fine("Committing ..."); + DB.commit(true, get_TrxName()); + + return "OK"; + + } // del doIt + + private void raiseError(String string, String sql) throws Exception { + DB.rollback(false, get_TrxName()); + String msg = string; + ValueNamePair pp = CLogger.retrieveError(); + if (pp != null) + msg = pp.getName() + " - "; + msg += sql; + throw new AdempiereUserError(msg); + } + +} // M_Production_Run diff --git a/base/src/org/compiere/process/MatchInvDelete.java b/base/src/org/compiere/process/MatchInvDelete.java new file mode 100644 index 0000000000..5dba3f93af --- /dev/null +++ b/base/src/org/compiere/process/MatchInvDelete.java @@ -0,0 +1,59 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Delete Inv Match + * + * @author Jorg Janke + * @version $Id: MatchInvDelete.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class MatchInvDelete extends SvrProcess +{ + /** ID */ + private int p_M_MatchInv_ID = 0; + + /** + * Prepare + */ + protected void prepare () + { + p_M_MatchInv_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info ("M_MatchInv_ID=" + p_M_MatchInv_ID); + MMatchInv inv = new MMatchInv (getCtx(), p_M_MatchInv_ID, get_TrxName()); + if (inv.get_ID() == 0) + throw new AdempiereUserError("@NotFound@ @M_MatchInv_ID@ " + p_M_MatchInv_ID); + if (inv.delete(true)) + return "@OK@"; + inv.save(); + return "@Error@"; + } // doIt + +} // MatchInvDelete diff --git a/base/src/org/compiere/process/MatchPODelete.java b/base/src/org/compiere/process/MatchPODelete.java new file mode 100644 index 0000000000..205b85e7ed --- /dev/null +++ b/base/src/org/compiere/process/MatchPODelete.java @@ -0,0 +1,59 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Delete PO Match + * + * @author Jorg Janke + * @version $Id: MatchPODelete.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class MatchPODelete extends SvrProcess +{ + /** ID */ + private int p_M_MatchPO_ID = 0; + + /** + * Prepare + */ + protected void prepare () + { + p_M_MatchPO_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info ("M_MatchPO_ID=" + p_M_MatchPO_ID); + MMatchPO po = new MMatchPO (getCtx(), p_M_MatchPO_ID, get_TrxName()); + if (po.get_ID() == 0) + throw new AdempiereUserError("@NotFound@ @M_MatchPO_ID@ " + p_M_MatchPO_ID); + if (po.delete(true)) + return "@OK@"; + po.save(); + return "@Error@"; + } // doIt + +} // MatchPODelete diff --git a/base/src/org/compiere/process/NoteDelete.java b/base/src/org/compiere/process/NoteDelete.java new file mode 100644 index 0000000000..2eea3f2e40 --- /dev/null +++ b/base/src/org/compiere/process/NoteDelete.java @@ -0,0 +1,69 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; + +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Delere Notes (Notice) + * + * @author Jorg Janke + * @version $Id: NoteDelete.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class NoteDelete extends SvrProcess +{ + private int p_AD_User_ID = -1; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_User_ID")) + p_AD_User_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("doIt - AD_User_ID=" + p_AD_User_ID); + + String sql = "DELETE FROM AD_Note WHERE AD_Client_ID=" + getAD_Client_ID(); + if (p_AD_User_ID > 0) + sql += " AND AD_User_ID=" + p_AD_User_ID; + // + int no = DB.executeUpdate(sql, get_TrxName()); + return "@Deleted@ = " + no; + } // doIt + +} // NoteDelete diff --git a/base/src/org/compiere/process/OrderBatchProcess.java b/base/src/org/compiere/process/OrderBatchProcess.java new file mode 100644 index 0000000000..fee4ed4256 --- /dev/null +++ b/base/src/org/compiere/process/OrderBatchProcess.java @@ -0,0 +1,160 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Order Batch Processing + * + * @author Jorg Janke + * @version $Id: OrderBatchProcess.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class OrderBatchProcess extends SvrProcess +{ + private int p_C_DocTypeTarget_ID = 0; + private String p_DocStatus = null; + private int p_C_BPartner_ID = 0; + private String p_IsSelfService = null; + private Timestamp p_DateOrdered_From = null; + private Timestamp p_DateOrdered_To = null; + private String p_DocAction = null; + + /** + * Prepare + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_DocTypeTarget_ID")) + p_C_DocTypeTarget_ID = para[i].getParameterAsInt(); + else if (name.equals("DocStatus")) + p_DocStatus = (String)para[i].getParameter(); + else if (name.equals("IsSelfService")) + p_IsSelfService = (String)para[i].getParameter(); + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = para[i].getParameterAsInt(); + else if (name.equals("DateOrdered")) + { + p_DateOrdered_From = (Timestamp)para[i].getParameter(); + p_DateOrdered_To = (Timestamp)para[i].getParameter_To(); + } + else if (name.equals("DocAction")) + p_DocAction = (String)para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Process + * @return msg + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("C_DocTypeTarget_ID=" + p_C_DocTypeTarget_ID + ", DocStatus=" + p_DocStatus + + ", IsSelfService=" + p_IsSelfService + ", C_BPartner_ID=" + p_C_BPartner_ID + + ", DateOrdered=" + p_DateOrdered_From + "->" + p_DateOrdered_To + + ", DocAction=" + p_DocAction); + + if (p_C_DocTypeTarget_ID == 0) + throw new AdempiereUserError("@NotFound@: @C_DocTypeTarget_ID@"); + if (p_DocStatus == null || p_DocStatus.length() != 2) + throw new AdempiereUserError("@NotFound@: @DocStatus@"); + if (p_DocAction == null || p_DocAction.length() != 2) + throw new AdempiereUserError("@NotFound@: @DocAction@"); + + // + StringBuffer sql = new StringBuffer("SELECT * FROM C_Order " + + "WHERE C_DocTypeTarget_ID=? AND DocStatus=?"); + if (p_IsSelfService != null && p_IsSelfService.length() == 1) + sql.append(" AND IsSelfService='").append(p_IsSelfService).append("'"); + if (p_C_BPartner_ID != 0) + sql.append(" AND C_BPartner_ID=").append(p_C_BPartner_ID); + if (p_DateOrdered_From != null) + sql.append(" AND TRUNC(DateOrdered) >= ").append(DB.TO_DATE(p_DateOrdered_From, true)); + if (p_DateOrdered_To != null) + sql.append(" AND TRUNC(DateOrdered) <= ").append(DB.TO_DATE(p_DateOrdered_To, true)); + + int counter = 0; + int errCounter = 0; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql.toString(), get_TrxName()); + pstmt.setInt(1, p_C_DocTypeTarget_ID); + pstmt.setString(2, p_DocStatus); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + if (process(new MOrder(getCtx(),rs, get_TrxName()))) + counter++; + else + errCounter++; + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return "@Updated@=" + counter + ", @Errors@=" + errCounter; + } // doIt + + /** + * Process Order + * @param order order + * @return true if ok + */ + private boolean process (MOrder order) + { + log.info(order.toString()); + // + order.setDocAction(p_DocAction); + if (order.processIt(p_DocAction)) + { + order.save(); + addLog(0, null, null, order.getDocumentNo() + ": OK"); + return true; + } + addLog (0, null, null, order.getDocumentNo() + ": Error " + order.getProcessMsg()); + return false; + } // process + +} // OrderBatchProcess diff --git a/base/src/org/compiere/process/OrderOpen.java b/base/src/org/compiere/process/OrderOpen.java new file mode 100644 index 0000000000..3abd24fbd3 --- /dev/null +++ b/base/src/org/compiere/process/OrderOpen.java @@ -0,0 +1,72 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import org.compiere.model.*; + +/** + * Re-Open Order Process (from Closed to Completed) + * + * @author Jorg Janke + * @version $Id: OrderOpen.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class OrderOpen extends SvrProcess +{ + /** The Order */ + private int p_C_Order_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_Order_ID")) + p_C_Order_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("doIt - Open C_Order_ID=" + p_C_Order_ID); + if (p_C_Order_ID == 0) + throw new IllegalArgumentException("C_Order_ID == 0"); + // + MOrder order = new MOrder (getCtx(), p_C_Order_ID, get_TrxName()); + if (MOrder.DOCSTATUS_Closed.equals(order.getDocStatus())) + { + order.setDocStatus(MOrder.DOCSTATUS_Completed); + return order.save() ? "@OK@" : "@Error@"; + } + else + throw new IllegalStateException("Order is not closed"); + } // doIt + +} // OrderOpen diff --git a/base/src/org/compiere/process/OrderPOCreate.java b/base/src/org/compiere/process/OrderPOCreate.java new file mode 100644 index 0000000000..fb9aeebea9 --- /dev/null +++ b/base/src/org/compiere/process/OrderPOCreate.java @@ -0,0 +1,297 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.awt.geom.*; +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Generate PO from Sales Order + * + * @author Jorg Janke + * @version $Id: OrderPOCreate.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class OrderPOCreate extends SvrProcess +{ + /** Order Date From */ + private Timestamp p_DateOrdered_From; + /** Order Date To */ + private Timestamp p_DateOrdered_To; + /** Customer */ + private int p_C_BPartner_ID; + /** Vendor */ + private int p_Vendor_ID; + /** Sales Order */ + private int p_C_Order_ID; + /** Drop Ship */ + private String p_IsDropShip; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("DateOrdered")) + { + p_DateOrdered_From = (Timestamp)para[i].getParameter(); + p_DateOrdered_To = (Timestamp)para[i].getParameter_To(); + } + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("Vendor_ID")) + p_Vendor_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_Order_ID")) + p_C_Order_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("IsDropShip")) + p_IsDropShip = (String)para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("DateOrdered=" + p_DateOrdered_From + " - " + p_DateOrdered_To + + " - C_BPartner_ID=" + p_C_BPartner_ID + " - Vendor_ID=" + p_Vendor_ID + + " - IsDropShip=" + p_IsDropShip + " - C_Order_ID=" + p_C_Order_ID); + if (p_C_Order_ID == 0 && p_IsDropShip == null + && p_DateOrdered_From == null && p_DateOrdered_To == null + && p_C_BPartner_ID == 0 && p_Vendor_ID == 0) + throw new IllegalPathStateException("You need to restrict selection"); + // + String sql = "SELECT * FROM C_Order o " + + "WHERE o.IsSOTrx='Y'" + // No Duplicates + // " AND o.Ref_Order_ID IS NULL" + + " AND NOT EXISTS (SELECT * FROM C_OrderLine ol WHERE o.C_Order_ID=ol.C_Order_ID AND ol.Ref_OrderLine_ID IS NOT NULL)" + ; + if (p_C_Order_ID != 0) + sql += " AND o.C_Order_ID=?"; + else + { + if (p_C_BPartner_ID != 0) + sql += " AND o.C_BPartner_ID=?"; + if (p_IsDropShip != null) + sql += " AND o.IsDropShip=?"; + if (p_Vendor_ID != 0) + sql += " AND EXISTS (SELECT * FROM C_OrderLine ol" + + " INNER JOIN M_Product_PO po ON (ol.M_Product_ID=po.M_Product_ID) " + + "WHERE o.C_Order_ID=ol.C_Order_ID AND po.C_BPartner_ID=?)"; + if (p_DateOrdered_From != null && p_DateOrdered_To != null) + sql += "AND TRUNC(o.DateOrdered) BETWEEN ? AND ?"; + else if (p_DateOrdered_From != null && p_DateOrdered_To == null) + sql += "AND TRUNC(o.DateOrdered) >= ?"; + else if (p_DateOrdered_From == null && p_DateOrdered_To != null) + sql += "AND TRUNC(o.DateOrdered) <= ?"; + } + PreparedStatement pstmt = null; + int counter = 0; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + if (p_C_Order_ID != 0) + pstmt.setInt (1, p_C_Order_ID); + else + { + int index = 1; + if (p_C_BPartner_ID != 0) + pstmt.setInt (index++, p_C_BPartner_ID); + if (p_IsDropShip != null) + pstmt.setString(index++, p_IsDropShip); + if (p_Vendor_ID != 0) + pstmt.setInt (index++, p_Vendor_ID); + if (p_DateOrdered_From != null && p_DateOrdered_To != null) + { + pstmt.setTimestamp(index++, p_DateOrdered_From); + pstmt.setTimestamp(index++, p_DateOrdered_To); + } + else if (p_DateOrdered_From != null && p_DateOrdered_To == null) + pstmt.setTimestamp(index++, p_DateOrdered_From); + else if (p_DateOrdered_From == null && p_DateOrdered_To != null) + pstmt.setTimestamp(index++, p_DateOrdered_To); + } + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + counter += createPOFromSO (new MOrder (getCtx(), rs, get_TrxName())); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + if (counter == 0) + log.fine(sql); + return "@Created@ " + counter; + } // doIt + + /** + * Create PO From SO + * @param so sales order + * @return number of POs created + */ + private int createPOFromSO (MOrder so) + { + log.info(so.toString()); + MOrderLine[] soLines = so.getLines(true, null); + if (soLines == null || soLines.length == 0) + { + log.warning("No Lines - " + so); + return 0; + } + // + int counter = 0; + // Order Lines with a Product which has a current vendor + String sql = "SELECT DISTINCT po.C_BPartner_ID, po.M_Product_ID " + + "FROM M_Product_PO po" + + " INNER JOIN C_OrderLine ol ON (po.M_Product_ID=ol.M_Product_ID) " + + "WHERE ol.C_Order_ID=? AND po.IsCurrentVendor='Y' " + + "ORDER BY 1"; + PreparedStatement pstmt = null; + MOrder po = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, so.getC_Order_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + // New Order + int C_BPartner_ID = rs.getInt(1); + if (po == null || po.getBill_BPartner_ID() != C_BPartner_ID) + { + po = createPOForVendor(rs.getInt(1), so); + addLog(0, null, null, po.getDocumentNo()); + counter++; + } + + // Line + int M_Product_ID = rs.getInt(2); + for (int i = 0; i < soLines.length; i++) + { + if (soLines[i].getM_Product_ID() == M_Product_ID) + { + MOrderLine poLine = new MOrderLine (po); + poLine.setRef_OrderLine_ID(soLines[i].getC_OrderLine_ID()); + poLine.setM_Product_ID(soLines[i].getM_Product_ID()); + poLine.setM_AttributeSetInstance_ID(soLines[i].getM_AttributeSetInstance_ID()); + poLine.setC_UOM_ID(soLines[i].getC_UOM_ID()); + poLine.setQtyEntered(soLines[i].getQtyEntered()); + poLine.setQtyOrdered(soLines[i].getQtyOrdered()); + poLine.setDescription(soLines[i].getDescription()); + poLine.setDatePromised(soLines[i].getDatePromised()); + poLine.setPrice(); + poLine.save(); + } + } + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // Set Reference to PO + if (counter == 1 && po != null) + { + so.setRef_Order_ID(po.getC_Order_ID()); + so.save(); + } + return counter; + } // createPOFromSO + + /** + * Create PO for Vendor + * @param C_BPartner_ID vendor + * @param so sales order + */ + public MOrder createPOForVendor(int C_BPartner_ID, MOrder so) + { + MOrder po = new MOrder (getCtx(), 0, get_TrxName()); + po.setClientOrg(so.getAD_Client_ID(), so.getAD_Org_ID()); + po.setRef_Order_ID(so.getC_Order_ID()); + po.setIsSOTrx(false); + po.setC_DocTypeTarget_ID(); + // + po.setDescription(so.getDescription()); + po.setPOReference(so.getDocumentNo()); + po.setPriorityRule(so.getPriorityRule()); + po.setSalesRep_ID(so.getSalesRep_ID()); + po.setM_Warehouse_ID(so.getM_Warehouse_ID()); + // Set Vendor + MBPartner vendor = new MBPartner (getCtx(), C_BPartner_ID, get_TrxName()); + po.setBPartner(vendor); + // Drop Ship + po.setIsDropShip(so.isDropShip()); + if (so.isDropShip()) + { + po.setShip_BPartner_ID(so.getC_BPartner_ID()); + po.setShip_Location_ID(so.getC_BPartner_Location_ID()); + po.setShip_User_ID(so.getAD_User_ID()); + } + // References + po.setC_Activity_ID(so.getC_Activity_ID()); + po.setC_Campaign_ID(so.getC_Campaign_ID()); + po.setC_Project_ID(so.getC_Project_ID()); + po.setUser1_ID(so.getUser1_ID()); + po.setUser2_ID(so.getUser2_ID()); + // + po.save(); + return po; + } // createPOForVendor + +} // doIt diff --git a/base/src/org/compiere/process/OrderRePrice.java b/base/src/org/compiere/process/OrderRePrice.java new file mode 100644 index 0000000000..6dc5bf78cb --- /dev/null +++ b/base/src/org/compiere/process/OrderRePrice.java @@ -0,0 +1,103 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Re-Price Order or Invoice + * + * @author Jorg Janke + * @version $Id: OrderRePrice.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class OrderRePrice extends SvrProcess +{ + /** Order to re-price */ + private int p_C_Order_ID = 0; + /** Invoice to re-price */ + private int p_C_Invoice_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_Order_ID")) + p_C_Order_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_Invoice_ID")) + p_C_Invoice_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("C_Order_ID=" + p_C_Order_ID + ", C_Invoice_ID=" + p_C_Invoice_ID); + if (p_C_Order_ID == 0 && p_C_Invoice_ID == 0) + throw new IllegalArgumentException("Nothing to do"); + + String retValue = ""; + if (p_C_Order_ID != 0) + { + MOrder order = new MOrder (getCtx(), p_C_Order_ID, get_TrxName()); + BigDecimal oldPrice = order.getGrandTotal(); + MOrderLine[] lines = order.getLines(); + for (int i = 0; i < lines.length; i++) + { + lines[i].setPrice(order.getM_PriceList_ID()); + lines[i].save(); + } + order = new MOrder (getCtx(), p_C_Order_ID, get_TrxName()); + BigDecimal newPrice = order.getGrandTotal(); + retValue = order.getDocumentNo() + ": " + oldPrice + " -> " + newPrice; + } + if (p_C_Invoice_ID != 0) + { + MInvoice invoice = new MInvoice (getCtx(), p_C_Invoice_ID, null); + BigDecimal oldPrice = invoice.getGrandTotal(); + MInvoiceLine[] lines = invoice.getLines(false); + for (int i = 0; i < lines.length; i++) + { + lines[i].setPrice(invoice.getM_PriceList_ID(), invoice.getC_BPartner_ID()); + lines[i].save(); + } + invoice = new MInvoice (getCtx(), p_C_Invoice_ID, null); + BigDecimal newPrice = invoice.getGrandTotal(); + if (retValue.length() > 0) + retValue += Env.NL; + retValue += invoice.getDocumentNo() + ": " + oldPrice + " -> " + newPrice; + } + // + return retValue; + } // doIt + +} // OrderRePrice diff --git a/base/src/org/compiere/process/OrgOwnership.java b/base/src/org/compiere/process/OrgOwnership.java new file mode 100644 index 0000000000..c0f37ae456 --- /dev/null +++ b/base/src/org/compiere/process/OrgOwnership.java @@ -0,0 +1,302 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; + +//import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Org Ownership Process + * + * @author Jorg Janke + * @version $Id: OrgOwnership.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class OrgOwnership extends SvrProcess +{ + /** Organization Parameter */ + private int p_AD_Org_ID = -1; + + private int p_M_Warehouse_ID = -1; + + private int p_M_Product_Category_ID = -1; + private int p_M_Product_ID = -1; + + private int p_C_BP_Group_ID = -1; + private int p_C_BPartner_ID = -1; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Org_ID")) + p_AD_Org_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("M_Warehouse_ID")) + p_M_Warehouse_ID = ((BigDecimal)para[i].getParameter()).intValue(); + + else if (name.equals("M_Product_Category_ID")) + p_M_Product_Category_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("M_Product_ID")) + p_M_Product_ID = ((BigDecimal)para[i].getParameter()).intValue(); + + else if (name.equals("C_BP_Group_ID")) + p_C_BP_Group_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = ((BigDecimal)para[i].getParameter()).intValue(); + + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Perform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info ("doIt - AD_Org_ID=" + p_AD_Org_ID); + if (p_AD_Org_ID < 0) + throw new IllegalArgumentException ("OrgOwnership - invalid AD_Org_ID=" + p_AD_Org_ID); + + generalOwnership(); + + if (p_M_Warehouse_ID > 0) + return warehouseOwnership(); + + if (p_M_Product_ID > 0 || p_M_Product_Category_ID > 0) + return productOwnership(); + + if (p_C_BPartner_ID > 0 || p_C_BP_Group_ID > 0) + return bPartnerOwnership(); + + + return "* Not supported * **"; + } // doIt + + /** + * Set Warehouse Ownership + * @return "" + */ + private String warehouseOwnership () + { + log.info ("warehouseOwnership - M_Warehouse_ID=" + p_M_Warehouse_ID); + if (p_AD_Org_ID == 0) + throw new IllegalArgumentException ("Warehouse - Org cannot be * (0)"); + + // Set Warehouse + StringBuffer sql = new StringBuffer(); + sql.append("UPDATE M_Warehouse " + + "SET AD_Org_ID=").append(p_AD_Org_ID) + .append(" WHERE M_Warehouse_ID=").append(p_M_Warehouse_ID) + .append(" AND AD_Client_ID=").append(getAD_Client_ID()) + .append(" AND AD_Org_ID<>").append(p_AD_Org_ID); + int no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog (0,null, new BigDecimal(no), Msg.translate(getCtx(), "M_Warehouse_ID")); + + // Set Accounts + sql = new StringBuffer(); + sql.append("UPDATE M_Warehouse_Acct " + + "SET AD_Org_ID=").append(p_AD_Org_ID) + .append(" WHERE M_Warehouse_ID=").append(p_M_Warehouse_ID) + .append(" AND AD_Client_ID=").append(getAD_Client_ID()) + .append(" AND AD_Org_ID<>").append(p_AD_Org_ID); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog (0,null, new BigDecimal(no), Msg.translate(getCtx(), "C_AcctSchema_ID")); + + // Set Locators + sql = new StringBuffer(); + sql.append("UPDATE M_Locator " + + "SET AD_Org_ID=").append(p_AD_Org_ID) + .append(" WHERE M_Warehouse_ID=").append(p_M_Warehouse_ID) + .append(" AND AD_Client_ID=").append(getAD_Client_ID()) + .append(" AND AD_Org_ID<>").append(p_AD_Org_ID); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog (0,null, new BigDecimal(no), Msg.translate(getCtx(), "M_Locator_ID")); + + // Set Storage + sql = new StringBuffer(); + sql.append("UPDATE M_Storage s " + + "SET AD_Org_ID=").append(p_AD_Org_ID) + .append(" WHERE EXISTS " + + "(SELECT * FROM M_Locator l WHERE l.M_Locator_ID=s.M_Locator_ID" + + " AND l.M_Warehouse_ID=").append(p_M_Warehouse_ID) + .append(") AND AD_Client_ID=").append(getAD_Client_ID()) + .append(" AND AD_Org_ID<>").append(p_AD_Org_ID); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog (0,null, new BigDecimal(no), Msg.translate(getCtx(), "Storage")); + + return ""; + } // warehouseOwnership + + /** + * Product Ownership + * @return "" + */ + private String productOwnership () + { + log.info ("productOwnership - M_Product_Category_ID=" + p_M_Product_Category_ID + + ", M_Product_ID=" + p_M_Product_ID); + + String set = " SET AD_Org_ID=" + p_AD_Org_ID; + if (p_M_Product_Category_ID > 0) + set += " WHERE EXISTS (SELECT * FROM M_Product p" + + " WHERE p.M_Product_ID=x.M_Product_ID AND p.M_Product_Category_ID=" + + p_M_Product_Category_ID + ")"; + else + set += " WHERE M_Product_ID=" + p_M_Product_ID; + set += " AND AD_Client_ID=" + getAD_Client_ID() + " AND AD_Org_ID<>" + p_AD_Org_ID; + log.fine("productOwnership - " + set); + + // Product + String sql = "UPDATE M_Product x " + set; + int no = DB.executeUpdate(sql, get_TrxName()); + addLog (0,null, new BigDecimal(no), Msg.translate(getCtx(), "M_Product_ID")); + + // Acct + sql = "UPDATE M_Product_Acct x " + set; + no = DB.executeUpdate(sql, get_TrxName()); + addLog (0,null, new BigDecimal(no), Msg.translate(getCtx(), "C_AcctSchema_ID")); + + // BOM + sql = "UPDATE M_Product_BOM x " + set; + no = DB.executeUpdate(sql, get_TrxName()); + addLog (0,null, new BigDecimal(no), Msg.translate(getCtx(), "M_Product_BOM_ID")); + + // PO + sql = "UPDATE M_Product_PO x " + set; + no = DB.executeUpdate(sql, get_TrxName()); + addLog (0,null, new BigDecimal(no), Msg.translate(getCtx(), "PO")); + + // Trl + sql = "UPDATE M_Product_Trl x " + set; + no = DB.executeUpdate(sql, get_TrxName()); + addLog (0,null, new BigDecimal(no), Msg.translate(getCtx(), "AD_Language")); + + return ""; + } // productOwnership + + /** + * Business Partner Ownership + * @return "" + */ + private String bPartnerOwnership () + { + log.info ("bPartnerOwnership - C_BP_Group_ID=" + p_C_BP_Group_ID + + ", C_BPartner_ID=" + p_C_BPartner_ID); + + String set = " SET AD_Org_ID=" + p_AD_Org_ID; + if (p_C_BP_Group_ID > 0) + set += " WHERE EXISTS (SELECT * FROM C_BPartner bp WHERE bp.C_BPartner_ID=x.C_BPartner_ID AND bp.C_BP_Group_ID=" + p_C_BP_Group_ID + ")"; + else + set += " WHERE C_BPartner_ID=" + p_C_BPartner_ID; + set += " AND AD_Client_ID=" + getAD_Client_ID() + " AND AD_Org_ID<>" + p_AD_Org_ID; + log.fine("bPartnerOwnership - " + set); + + // BPartner + String sql = "UPDATE C_BPartner x " + set; + int no = DB.executeUpdate(sql, get_TrxName()); + addLog (0,null, new BigDecimal(no), Msg.translate(getCtx(), "C_BPartner_ID")); + + // Acct xxx + sql = "UPDATE C_BP_Customer_Acct x " + set; + no = DB.executeUpdate(sql, get_TrxName()); + addLog (0,null, new BigDecimal(no), Msg.translate(getCtx(), "C_AcctSchema_ID")); + sql = "UPDATE C_BP_Employee_Acct x " + set; + no = DB.executeUpdate(sql, get_TrxName()); + addLog (0,null, new BigDecimal(no), Msg.translate(getCtx(), "C_AcctSchema_ID")); + sql = "UPDATE C_BP_Vendor_Acct x " + set; + no = DB.executeUpdate(sql, get_TrxName()); + addLog (0,null, new BigDecimal(no), Msg.translate(getCtx(), "C_AcctSchema_ID")); + + // Location + sql = "UPDATE C_BPartner_Location x " + set; + no = DB.executeUpdate(sql, get_TrxName()); + addLog (0,null, new BigDecimal(no), Msg.translate(getCtx(), "C_BPartner_Location_ID")); + + // Contcat/User + sql = "UPDATE AD_User x " + set; + no = DB.executeUpdate(sql, get_TrxName()); + addLog (0,null, new BigDecimal(no), Msg.translate(getCtx(), "AD_User_ID")); + + // BankAcct + sql = "UPDATE C_BP_BankAccount x " + set; + no = DB.executeUpdate(sql, get_TrxName()); + addLog (0,null, new BigDecimal(no), Msg.translate(getCtx(), "C_BP_BankAccount_ID")); + + return ""; + } // bPartnerOwnership + + /** + * Set General Ownership (i.e. Org to 0). + * In general for items with two parents + */ + private void generalOwnership () + { + String set = "SET AD_Org_ID=0 WHERE AD_Client_ID=" + getAD_Client_ID() + + " AND AD_Org_ID<>0"; + + // R_ContactInterest + String sql = "UPDATE R_ContactInterest " + set; + int no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("generalOwnership - R_ContactInterest=" + no); + + // AD_User_Roles + sql = "UPDATE AD_User_Roles " + set; + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("generalOwnership - AD_User_Roles=" + no); + + // C_BPartner_Product + sql = "UPDATE C_BPartner_Product " + set; + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("generalOwnership - C_BPartner_Product=" + no); + + // Withholding + sql = "UPDATE C_BP_Withholding x " + set; + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("generalOwnership - C_BP_Withholding=" + no); + + // Costing + sql = "UPDATE M_Product_Costing " + set; + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("generalOwnership - M_Product_Costing=" + no); + + // Replenish + sql = "UPDATE M_Replenish " + set; + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("generalOwnership - M_Replenish=" + no); + + } // generalOwnership + + +} // OrgOwnership diff --git a/base/src/org/compiere/process/PackageCreate.java b/base/src/org/compiere/process/PackageCreate.java new file mode 100644 index 0000000000..a34bdbc151 --- /dev/null +++ b/base/src/org/compiere/process/PackageCreate.java @@ -0,0 +1,83 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import org.compiere.model.*; + +/** + * Create Package from Shipment for Shipper + * + * @author Jorg Janke + * @version $Id: PackageCreate.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class PackageCreate extends SvrProcess +{ + /** Shipper */ + private int p_M_Shipper_ID = 0; + /** Parent */ + private int p_M_InOut_ID = 0; + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("M_Shipper_ID")) + p_M_Shipper_ID = para[i].getParameterAsInt(); + else if (name.equals("C_Invoice_ID")) + p_M_InOut_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + if (p_M_InOut_ID == 0) + p_M_InOut_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("doIt - M_InOut_ID=" + p_M_InOut_ID + ", M_Shipper_ID=" + p_M_Shipper_ID); + if (p_M_InOut_ID == 0) + throw new IllegalArgumentException("No Shipment"); + if (p_M_Shipper_ID == 0) + throw new IllegalArgumentException("No Shipper"); + MInOut shipment = new MInOut (getCtx(), p_M_InOut_ID, null); + if (shipment.get_ID() != p_M_InOut_ID) + throw new IllegalArgumentException("Cannot find Shipment ID=" + p_M_InOut_ID); + MShipper shipper = new MShipper (getCtx(), p_M_Shipper_ID, get_TrxName()); + if (shipper.get_ID() != p_M_Shipper_ID) + throw new IllegalArgumentException("Cannot find Shipper ID=" + p_M_InOut_ID); + // + + MPackage pack = MPackage.create (shipment, shipper, null); + + return pack.getDocumentNo(); + } // doIt + +} // PackageCreate diff --git a/base/src/org/compiere/process/PaySelectionCreateCheck.java b/base/src/org/compiere/process/PaySelectionCreateCheck.java new file mode 100644 index 0000000000..fe3fd8866e --- /dev/null +++ b/base/src/org/compiere/process/PaySelectionCreateCheck.java @@ -0,0 +1,125 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; + + +/** + * Create Checks from Payment Selection Line + * + * @author Jorg Janke + * @version $Id: PaySelectionCreateCheck.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class PaySelectionCreateCheck extends SvrProcess +{ + /** Target Payment Rule */ + private String p_PaymentRule = null; + /** Payment Selection */ + private int p_C_PaySelection_ID = 0; + /** The checks */ + private ArrayList m_list = new ArrayList(); + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("PaymentRule")) + p_PaymentRule = (String)para[i].getParameter(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + p_C_PaySelection_ID = getRecord_ID(); + } // prepare + + /** + * Perrform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt () throws Exception + { + log.info ("doIt - C_PaySelection_ID=" + p_C_PaySelection_ID + + ", PaymentRule=" + p_PaymentRule); + + MPaySelection psel = new MPaySelection (getCtx(), p_C_PaySelection_ID, get_TrxName()); + if (psel.get_ID() == 0) + throw new IllegalArgumentException("Not found C_PaySelection_ID=" + p_C_PaySelection_ID); + if (psel.isProcessed()) + throw new IllegalArgumentException("@Processed@"); + if (p_PaymentRule == null) + throw new IllegalArgumentException("No PaymentRule"); + // + MPaySelectionLine[] lines = psel.getLines(false); + for (int i = 0; i < lines.length; i++) + { + MPaySelectionLine line = lines[i]; + if (!line.isActive() || line.isProcessed()) + continue; + createCheck (line); + } + // + psel.setProcessed(true); + psel.save(); + + return "@C_PaySelectionCheck_ID@ - #" + m_list.size(); + } // doIt + + /** + * Create Check from line + * @param line + */ + private void createCheck (MPaySelectionLine line) + { + // Try to find one + for (int i = 0; i < m_list.size(); i++) + { + MPaySelectionCheck check = (MPaySelectionCheck)m_list.get(i); + // Add to existing + if (check.getC_BPartner_ID() == line.getInvoice().getC_BPartner_ID()) + { + check.addLine(line); + if (!check.save()) + throw new IllegalStateException("Cannot Save MPaySelectionCheck"); + line.setC_PaySelectionCheck_ID(check.getC_PaySelectionCheck_ID()); + line.setProcessed(true); + if (!line.save()) + throw new IllegalStateException("Cannot Save MPaySelectionLine"); + return; + } + } + // Create new + MPaySelectionCheck check = new MPaySelectionCheck(line, p_PaymentRule); + if (!check.save()) + throw new IllegalStateException("Cannot Save MPaySelectionCheck"); + line.setC_PaySelectionCheck_ID(check.getC_PaySelectionCheck_ID()); + line.setProcessed(true); + if (!line.save()) + throw new IllegalStateException("Cannot Save MPaySelectionLine"); + m_list.add(check); + } // createCheck + +} // PaySelectionCreateCheck diff --git a/base/src/org/compiere/process/PaySelectionCreateFrom.java b/base/src/org/compiere/process/PaySelectionCreateFrom.java new file mode 100644 index 0000000000..b20ce3bd25 --- /dev/null +++ b/base/src/org/compiere/process/PaySelectionCreateFrom.java @@ -0,0 +1,238 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Create Payment Selection Lines from AP Invoices + * + * @author Jorg Janke + * @version $Id: PaySelectionCreateFrom.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class PaySelectionCreateFrom extends SvrProcess +{ + /** Only When Discount */ + private boolean p_OnlyDiscount = false; + /** Only when Due */ + private boolean p_OnlyDue = false; + /** Include Disputed */ + private boolean p_IncludeInDispute = false; + /** Match Requirement */ + private String p_MatchRequirement = "N"; + /** Payment Rule */ + private String p_PaymentRule = null; + /** BPartner */ + private int p_C_BPartner_ID = 0; + /** BPartner Group */ + private int p_C_BP_Group_ID = 0; + /** Payment Selection */ + private int p_C_PaySelection_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("OnlyDiscount")) + p_OnlyDiscount = "Y".equals(para[i].getParameter()); + else if (name.equals("OnlyDue")) + p_OnlyDue = "Y".equals(para[i].getParameter()); + else if (name.equals("IncludeInDispute")) + p_IncludeInDispute = "Y".equals(para[i].getParameter()); + else if (name.equals("MatchRequirement")) + p_MatchRequirement = (String)para[i].getParameter(); + else if (name.equals("PaymentRule")) + p_PaymentRule = (String)para[i].getParameter(); + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = para[i].getParameterAsInt(); + else if (name.equals("C_BP_Group_ID")) + p_C_BP_Group_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_C_PaySelection_ID = getRecord_ID(); + } // prepare + + /** + * Perrform process. + * @return Message + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info ("C_PaySelection_ID=" + p_C_PaySelection_ID + + ", OnlyDiscount=" + p_OnlyDiscount + ", OnlyDue=" + p_OnlyDue + + ", IncludeInDispute=" + p_IncludeInDispute + + ", MatchRequirement=" + p_MatchRequirement + + ", PaymentRule=" + p_PaymentRule + + ", C_BP_Group_ID=" + p_C_BP_Group_ID + ", C_BPartner_ID=" + p_C_BPartner_ID); + + MPaySelection psel = new MPaySelection (getCtx(), p_C_PaySelection_ID, get_TrxName()); + if (psel.get_ID() == 0) + throw new IllegalArgumentException("Not found C_PaySelection_ID=" + p_C_PaySelection_ID); + if (psel.isProcessed()) + throw new IllegalArgumentException("@Processed@"); + // psel.getPayDate(); + + String sql = "SELECT C_Invoice_ID," + // Open + + " currencyConvert(invoiceOpen(i.C_Invoice_ID, 0)" + + ",i.C_Currency_ID, ?,?, i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID)," // ##1/2 Currency_To,PayDate + // Discount + + " currencyConvert(paymentTermDiscount(i.GrandTotal,i.C_Currency_ID,i.C_PaymentTerm_ID,i.DateInvoiced, ?)" // ##3 PayDate + + ",i.C_Currency_ID, ?,?,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID)," // ##4/5 Currency_To,PayDate + + " PaymentRule, IsSOTrx " + + "FROM C_Invoice i " + + "WHERE IsSOTrx='N' AND IsPaid='N' AND DocStatus IN ('CO','CL')" + + " AND AD_Client_ID=?" // ##6 + // Existing Payments - Will reselect Invoice if prepared but not paid + + " AND NOT EXISTS (SELECT * FROM C_PaySelectionLine psl " + + "WHERE i.C_Invoice_ID=psl.C_Invoice_ID AND psl.IsActive='Y'" + + " AND psl.C_PaySelectionCheck_ID IS NOT NULL)"; + // Disputed + if (!p_IncludeInDispute) + sql += " AND i.IsInDispute='N'"; + // PaymentRule (optional) + if (p_PaymentRule != null) + sql += " AND PaymentRule=?"; // ## + // OnlyDiscount + if (p_OnlyDiscount) + { + if (p_OnlyDue) + sql += " AND ("; + else + sql += " AND "; + sql += "paymentTermDiscount(invoiceOpen(C_Invoice_ID, 0), C_Currency_ID, C_PaymentTerm_ID, DateInvoiced, ?) > 0"; // ## + } + // OnlyDue + if (p_OnlyDue) + { + if (p_OnlyDiscount) + sql += " OR "; + else + sql += " AND "; + sql += "paymentTermDueDays(C_PaymentTerm_ID, DateInvoiced, ?) >= 0"; // ## + if (p_OnlyDiscount) + sql += ")"; + } + // Business Partner + if (p_C_BPartner_ID != 0) + sql += " AND C_BPartner_ID=?"; // ## + // Business Partner Group + else if (p_C_BP_Group_ID != 0) + sql += " AND EXISTS (SELECT * FROM C_BPartner bp " + + "WHERE bp.C_BPartner_ID=i.C_BPartner_ID AND bp.C_BP_Group_ID=?)"; // ## + // PO Matching Requiremnent + if (p_MatchRequirement.equals("P") || p_MatchRequirement.equals("B")) + { + sql += " AND EXISTS (SELECT * FROM C_InvoiceLine il " + + "WHERE i.C_Invoice_ID=il.C_Invoice_ID" + + " AND QtyInvoiced=(SELECT SUM(Qty) FROM M_MatchPO m " + + "WHERE il.C_InvoiceLine_ID=m.C_InvoiceLine_ID))"; + } + // Receipt Matching Requiremnent + if (p_MatchRequirement.equals("R") || p_MatchRequirement.equals("B")) + { + sql += " AND EXISTS (SELECT * FROM C_InvoiceLine il " + + "WHERE i.C_Invoice_ID=il.C_Invoice_ID" + + " AND QtyInvoiced=(SELECT SUM(Qty) FROM M_MatchInv m " + + "WHERE il.C_InvoiceLine_ID=m.C_InvoiceLine_ID))"; + } + + // + int lines = 0; + int C_CurrencyTo_ID = psel.getC_Currency_ID(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + int index = 1; + pstmt.setInt (index++, C_CurrencyTo_ID); + pstmt.setTimestamp(index++, psel.getPayDate()); + // + pstmt.setTimestamp(index++, psel.getPayDate()); + pstmt.setInt (index++, C_CurrencyTo_ID); + pstmt.setTimestamp(index++, psel.getPayDate()); + // + pstmt.setInt(index++, psel.getAD_Client_ID()); + if (p_PaymentRule != null) + pstmt.setString(index++, p_PaymentRule); + if (p_OnlyDiscount) + pstmt.setTimestamp(index++, psel.getPayDate()); + if (p_OnlyDue) + pstmt.setTimestamp(index++, psel.getPayDate()); + if (p_C_BPartner_ID != 0) + pstmt.setInt (index++, p_C_BPartner_ID); + else if (p_C_BP_Group_ID != 0) + pstmt.setInt (index++, p_C_BP_Group_ID); + // + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + int C_Invoice_ID = rs.getInt(1); + BigDecimal PayAmt = rs.getBigDecimal(2); + if (C_Invoice_ID == 0 || Env.ZERO.compareTo(PayAmt) == 0) + continue; + BigDecimal DiscountAmt = rs.getBigDecimal(3); + String PaymentRule = rs.getString(4); + boolean isSOTrx = "Y".equals(rs.getString(5)); + // + lines++; + MPaySelectionLine pselLine = new MPaySelectionLine (psel, lines*10, PaymentRule); + pselLine.setInvoice (C_Invoice_ID, isSOTrx, + PayAmt, PayAmt.subtract(DiscountAmt), DiscountAmt); + if (!pselLine.save()) + { + pstmt.close(); + throw new IllegalStateException ("Cannot save MPaySelectionLine"); + } + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "doIt - " + sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + return "@C_PaySelectionLine_ID@ - #" + lines; + } // doIt + +} // PaySelectionCreateFrom diff --git a/base/src/org/compiere/process/PaymentOnline.java b/base/src/org/compiere/process/PaymentOnline.java new file mode 100644 index 0000000000..344465b6b1 --- /dev/null +++ b/base/src/org/compiere/process/PaymentOnline.java @@ -0,0 +1,83 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +//import org.compiere.process.*; +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Online Payment Process + * + * @author Jorg Janke + * @version $Id: PaymentOnline.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class PaymentOnline extends SvrProcess +{ + private int m_C_Payment_ID = -1; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info("Record_ID=" + getRecord_ID()); + // get Payment + MPayment pp = new MPayment (getCtx(), getRecord_ID(), get_TrxName()); + // Validate Number + String msg = MPaymentValidate.validateCreditCardNumber(pp.getCreditCardNumber(), pp.getCreditCardType()); + if (msg != null && msg.length() > 0) + throw new IllegalArgumentException(Msg.getMsg(getCtx(), msg)); + msg = MPaymentValidate.validateCreditCardExp(pp.getCreditCardExpMM(), pp.getCreditCardExpYY()); + if (msg != null && msg.length() > 0) + throw new IllegalArgumentException(Msg.getMsg(getCtx(), msg)); + if (pp.getCreditCardVV().length() > 0) + { + msg = MPaymentValidate.validateCreditCardVV(pp.getCreditCardVV(), pp.getCreditCardType()); + if (msg != null && msg.length() > 0) + throw new IllegalArgumentException(Msg.getMsg(getCtx(), msg)); + } + + // Process it + boolean ok = pp.processOnline(); + pp.save(); + if (!ok) + throw new Exception(pp.getErrorMessage()); + return "OK"; + } // doIt + +} // PaymentOnline diff --git a/base/src/org/compiere/process/PaymentTermValidate.java b/base/src/org/compiere/process/PaymentTermValidate.java new file mode 100644 index 0000000000..377f508ba3 --- /dev/null +++ b/base/src/org/compiere/process/PaymentTermValidate.java @@ -0,0 +1,64 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Validate Payment Term and Schedule + * + * @author Jorg Janke + * @version $Id: PaymentTermValidate.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class PaymentTermValidate extends SvrProcess +{ + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info ("C_PaymentTerm_ID=" + getRecord_ID()); + MPaymentTerm pt = new MPaymentTerm (getCtx(), getRecord_ID(), get_TrxName()); + String msg = pt.validate(); + pt.save(); + // + if ("@OK@".equals(msg)) + return msg; + throw new AdempiereUserError (msg); + } // doIt + +} // PaymentTermValidate diff --git a/base/src/org/compiere/process/PeriodControlStatus.java b/base/src/org/compiere/process/PeriodControlStatus.java new file mode 100644 index 0000000000..cbb375b5f0 --- /dev/null +++ b/base/src/org/compiere/process/PeriodControlStatus.java @@ -0,0 +1,92 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Open/Close Period Control + * + * @author Jorg Janke + * @version $Id: PeriodControlStatus.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class PeriodControlStatus extends SvrProcess +{ + /** Period Control */ + private int p_C_PeriodControl_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_C_PeriodControl_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info ("C_PeriodControl_ID=" + p_C_PeriodControl_ID); + MPeriodControl pc = new MPeriodControl (getCtx(), p_C_PeriodControl_ID, get_TrxName()); + if (pc.get_ID() == 0) + throw new AdempiereUserError("@NotFound@ @C_PeriodControl_ID@=" + p_C_PeriodControl_ID); + // Permanently closed + if (MPeriodControl.PERIODACTION_PermanentlyClosePeriod.equals(pc.getPeriodStatus())) + throw new AdempiereUserError("@PeriodStatus@ = " + pc.getPeriodStatus()); + // No Action + if (MPeriodControl.PERIODACTION_NoAction.equals(pc.getPeriodAction())) + return "@OK@"; + + // Open + if (MPeriodControl.PERIODACTION_OpenPeriod.equals(pc.getPeriodAction())) + pc.setPeriodStatus(MPeriodControl.PERIODSTATUS_Open); + // Close + if (MPeriodControl.PERIODACTION_ClosePeriod.equals(pc.getPeriodAction())) + pc.setPeriodStatus(MPeriodControl.PERIODSTATUS_Closed); + // Close Permanently + if (MPeriodControl.PERIODACTION_PermanentlyClosePeriod.equals(pc.getPeriodAction())) + pc.setPeriodStatus(MPeriodControl.PERIODSTATUS_PermanentlyClosed); + pc.setPeriodAction(MPeriodControl.PERIODACTION_NoAction); + // + boolean ok = pc.save(); + + // Reset Cache + CacheMgt.get().reset("C_PeriodControl", 0); + CacheMgt.get().reset("C_Period", pc.getC_Period_ID()); + + if (!ok) + return "@Error@"; + return "@OK@"; + } // doIt + +} // PeriodControlStatus diff --git a/base/src/org/compiere/process/PeriodStatus.java b/base/src/org/compiere/process/PeriodStatus.java new file mode 100644 index 0000000000..e9813ac4ae --- /dev/null +++ b/base/src/org/compiere/process/PeriodStatus.java @@ -0,0 +1,95 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Open/Close all Period (Control) + * + * @author Jorg Janke + * @version $Id: PeriodStatus.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class PeriodStatus extends SvrProcess +{ + /** Period */ + private int p_C_Period_ID = 0; + /** Action */ + private String p_PeriodAction = null; + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("PeriodAction")) + p_PeriodAction = (String)para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_C_Period_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info ("C_Period_ID=" + p_C_Period_ID + ", PeriodAction=" + p_PeriodAction); + MPeriod period = new MPeriod (getCtx(), p_C_Period_ID, get_TrxName()); + if (period.get_ID() == 0) + throw new IllegalArgumentException("@NotFound@ @C_Period_ID@=" + p_C_Period_ID); + + StringBuffer sql = new StringBuffer ("UPDATE C_PeriodControl "); + sql.append("SET PeriodStatus='"); + // Open + if (MPeriodControl.PERIODACTION_OpenPeriod.equals(p_PeriodAction)) + sql.append (MPeriodControl.PERIODSTATUS_Open); + // Close + else if (MPeriodControl.PERIODACTION_ClosePeriod.equals(p_PeriodAction)) + sql.append (MPeriodControl.PERIODSTATUS_Closed); + // Close Permanently + else if (MPeriodControl.PERIODACTION_PermanentlyClosePeriod.equals(p_PeriodAction)) + sql.append (MPeriodControl.PERIODSTATUS_PermanentlyClosed); + else + return "-"; + // + sql.append("', PeriodAction='N', Updated=SysDate,UpdatedBy=").append(getAD_User_ID()); + // WHERE + sql.append(" WHERE C_Period_ID=").append(period.getC_Period_ID()) + .append(" AND PeriodStatus<>'P'") + .append(" AND PeriodStatus<>'").append(p_PeriodAction).append("'"); + + int no = DB.executeUpdate(sql.toString(), get_TrxName()); + + CacheMgt.get().reset("C_PeriodControl", 0); + CacheMgt.get().reset("C_Period", p_C_Period_ID); + return "@Updated@ #" + no; + } // doIt + +} // PeriodStatus diff --git a/base/src/org/compiere/process/ProductCategoryAcctCopy.java b/base/src/org/compiere/process/ProductCategoryAcctCopy.java new file mode 100644 index 0000000000..722d75a443 --- /dev/null +++ b/base/src/org/compiere/process/ProductCategoryAcctCopy.java @@ -0,0 +1,116 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Copy Product Catergory Default Accounts + * + * @author Jorg Janke + * @version $Id: ProductCategoryAcctCopy.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class ProductCategoryAcctCopy extends SvrProcess +{ + /** Product Categpory */ + private int p_M_Product_Category_ID = 0; + /** Acct Schema */ + private int p_C_AcctSchema_ID = 0; + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("M_Product_Category_ID")) + p_M_Product_Category_ID = para[i].getParameterAsInt(); + else if (name.equals("C_AcctSchema_ID")) + p_C_AcctSchema_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("C_AcctSchema_ID=" + p_C_AcctSchema_ID); + if (p_C_AcctSchema_ID == 0) + throw new AdempiereSystemError("C_AcctSchema_ID=0"); + MAcctSchema as = MAcctSchema.get(getCtx(), p_C_AcctSchema_ID); + if (as.get_ID() == 0) + throw new AdempiereSystemError("Not Found - C_AcctSchema_ID=" + p_C_AcctSchema_ID); + + // Update + String sql = "UPDATE M_Product_Acct pa " + + "SET (P_Revenue_Acct,P_Expense_Acct,P_CostAdjustment_Acct,P_InventoryClearing_Acct,P_Asset_Acct,P_COGS_Acct," + + " P_PurchasePriceVariance_Acct,P_InvoicePriceVariance_Acct," + + " P_TradeDiscountRec_Acct,P_TradeDiscountGrant_Acct)=" + + " (SELECT P_Revenue_Acct,P_Expense_Acct,P_CostAdjustment_Acct,P_InventoryClearing_Acct,P_Asset_Acct,P_COGS_Acct," + + " P_PurchasePriceVariance_Acct,P_InvoicePriceVariance_Acct," + + " P_TradeDiscountRec_Acct,P_TradeDiscountGrant_Acct" + + " FROM M_Product_Category_Acct pca" + + " WHERE pca.M_Product_Category_ID=" + p_M_Product_Category_ID + + " AND pca.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + "), Updated=SysDate, UpdatedBy=0 " + + "WHERE pa.C_AcctSchema_ID=" + p_C_AcctSchema_ID + + " AND EXISTS (SELECT * FROM M_Product p " + + "WHERE p.M_Product_ID=pa.M_Product_ID" + + " AND p.M_Product_Category_ID=" + p_M_Product_Category_ID + ")"; + int updated = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(updated), "@Updated@"); + + // Insert new Products + sql = "INSERT INTO M_Product_Acct " + + "(M_Product_ID, C_AcctSchema_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy," + + " P_Revenue_Acct, P_Expense_Acct, P_CostAdjustment_Acct, P_InventoryClearing_Acct, P_Asset_Acct, P_CoGs_Acct," + + " P_PurchasePriceVariance_Acct, P_InvoicePriceVariance_Acct," + + " P_TradeDiscountRec_Acct, P_TradeDiscountGrant_Acct) " + + "SELECT p.M_Product_ID, acct.C_AcctSchema_ID," + + " p.AD_Client_ID, p.AD_Org_ID, 'Y', SysDate, 0, SysDate, 0," + + " acct.P_Revenue_Acct, acct.P_Expense_Acct, acct.P_CostAdjustment_Acct, acct.P_InventoryClearing_Acct, acct.P_Asset_Acct, acct.P_CoGs_Acct," + + " acct.P_PurchasePriceVariance_Acct, acct.P_InvoicePriceVariance_Acct," + + " acct.P_TradeDiscountRec_Acct, acct.P_TradeDiscountGrant_Acct " + + "FROM M_Product p" + + " INNER JOIN M_Product_Category_Acct acct ON (acct.M_Product_Category_ID=p.M_Product_Category_ID)" + + "WHERE acct.C_AcctSchema_ID=" + p_C_AcctSchema_ID // # + + " AND p.M_Product_Category_ID=" + p_M_Product_Category_ID // # + + " AND NOT EXISTS (SELECT * FROM M_Product_Acct pa " + + "WHERE pa.M_Product_ID=p.M_Product_ID" + + " AND pa.C_AcctSchema_ID=acct.C_AcctSchema_ID)"; + int created = DB.executeUpdate(sql, get_TrxName()); + addLog(0, null, new BigDecimal(created), "@Created@"); + + return "@Created@=" + created + ", @Updated@=" + updated; + } // doIt + +} // ProductCategoryAcctCopy diff --git a/base/src/org/compiere/process/ProductUOMConvert.java b/base/src/org/compiere/process/ProductUOMConvert.java new file mode 100644 index 0000000000..a83a59007b --- /dev/null +++ b/base/src/org/compiere/process/ProductUOMConvert.java @@ -0,0 +1,106 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Product UOM Conversion + * + * @author Jorg Janke + * @version $Id: ProductUOMConvert.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ProductUOMConvert extends SvrProcess +{ + /** Product From */ + private int p_M_Product_ID = 0; + /** Product To */ + private int p_M_Product_To_ID = 0; + /** Locator */ + private int p_M_Locator_ID = 0; + /** Quantity */ + private BigDecimal p_Qty = null; + + /** + * Prepare + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("M_Product_ID")) + p_M_Product_ID = para[i].getParameterAsInt(); + else if (name.equals("M_Product_To_ID")) + p_M_Product_To_ID = para[i].getParameterAsInt(); + else if (name.equals("M_Locator_ID")) + p_M_Locator_ID = para[i].getParameterAsInt(); + else if (name.equals("Qty")) + p_Qty = (BigDecimal)para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt () throws Exception + { + if (p_M_Product_ID == 0 || p_M_Product_To_ID == 0 + || p_M_Locator_ID == 0 + || p_Qty == null || Env.ZERO.compareTo(p_Qty) == 0) + throw new AdempiereUserError("Invalid Parameter"); + // + MProduct product = MProduct.get(getCtx(), p_M_Product_ID); + MProduct productTo = MProduct.get(getCtx(), p_M_Product_To_ID); + log.info("Product=" + product + ", ProductTo=" + productTo + + ", M_Locator_ID=" + p_M_Locator_ID + ", Qty=" + p_Qty); + + MUOMConversion[] conversions = MUOMConversion.getProductConversions(getCtx(), product.getM_Product_ID()); + MUOMConversion conversion = null; + for (int i = 0; i < conversions.length; i++) + { + if (conversions[i].getC_UOM_To_ID() == productTo.getC_UOM_ID()) + conversion = conversions[i]; + } + if (conversion == null) + throw new AdempiereUserError("@NotFound@: @C_UOM_Conversion_ID@"); + + MUOM uomTo = MUOM.get(getCtx(), productTo.getC_UOM_ID()); + BigDecimal qtyTo = p_Qty.divide(conversion.getDivideRate(), uomTo.getStdPrecision(), BigDecimal.ROUND_HALF_UP); + BigDecimal qtyTo6 = p_Qty.divide(conversion.getDivideRate(), 6, BigDecimal.ROUND_HALF_UP); + if (qtyTo.compareTo(qtyTo6) != 0) + throw new AdempiereUserError("@StdPrecision@: " + qtyTo + " <> " + qtyTo6 + + " (" + p_Qty + "/" + conversion.getDivideRate() + ")"); + log.info(conversion + " -> " + qtyTo); + + + // Set to Beta + return "Not completed yet"; + } // doIt + +} // ProductUOMConvert diff --git a/base/src/org/compiere/process/ProjectClose.java b/base/src/org/compiere/process/ProjectClose.java new file mode 100644 index 0000000000..8936b2727e --- /dev/null +++ b/base/src/org/compiere/process/ProjectClose.java @@ -0,0 +1,81 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + + +import java.util.logging.*; +import org.compiere.model.*; + +/** + * Close Project. + * + * @author Jorg Janke + * @version $Id: ProjectClose.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ProjectClose extends SvrProcess +{ + /** Project from Record */ + private int m_C_Project_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + m_C_Project_ID = getRecord_ID(); + } // prepare + + /** + * Perrform process. + * @return Message (translated text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + MProject project = new MProject (getCtx(), m_C_Project_ID, get_TrxName()); + log.info("doIt - " + project); + + MProjectLine[] projectLines = project.getLines(); + if (MProject.PROJECTCATEGORY_WorkOrderJob.equals(project.getProjectCategory()) + || MProject.PROJECTCATEGORY_AssetProject.equals(project.getProjectCategory())) + { + /** @todo Check if we should close it */ + } + + // Close lines + for (int line = 0; line < projectLines.length; line++) + { + projectLines[line].setProcessed(true); + projectLines[line].save(); + } + + project.setProcessed(true); + project.save(); + + return ""; + } // doIt + +} // ProjectClose diff --git a/base/src/org/compiere/process/ProjectGenOrder.java b/base/src/org/compiere/process/ProjectGenOrder.java new file mode 100644 index 0000000000..8c79c69333 --- /dev/null +++ b/base/src/org/compiere/process/ProjectGenOrder.java @@ -0,0 +1,129 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.*; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Generate Sales Order from Project. + * + * @author Jorg Janke + * @version $Id: ProjectGenOrder.java,v 1.3 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ProjectGenOrder extends SvrProcess +{ + /** Project ID from project directly */ + private int m_C_Project_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + m_C_Project_ID = getRecord_ID(); + } // prepare + + /** + * Perrform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("C_Project_ID=" + m_C_Project_ID); + if (m_C_Project_ID == 0) + throw new IllegalArgumentException("C_Project_ID == 0"); + MProject fromProject = getProject (getCtx(), m_C_Project_ID, get_TrxName()); + Env.setSOTrx(getCtx(), true); // Set SO context + + /** @todo duplicate invoice prevention */ + + MOrder order = new MOrder (fromProject, true, MOrder.DocSubTypeSO_OnCredit); + if (!order.save()) + throw new Exception("Could not create Order"); + + // *** Lines *** + int count = 0; + + // Service Project + if (MProject.PROJECTCATEGORY_ServiceChargeProject.equals(fromProject.getProjectCategory())) + { + /** @todo service project invoicing */ + throw new Exception("Service Charge Projects are on the TODO List"); + } // Service Lines + + else // Order Lines + { + MProjectLine[] lines = fromProject.getLines (); + for (int i = 0; i < lines.length; i++) + { + MOrderLine ol = new MOrderLine(order); + ol.setLine(lines[i].getLine()); + ol.setDescription(lines[i].getDescription()); + // + ol.setM_Product_ID(lines[i].getM_Product_ID(), true); + ol.setQty(lines[i].getPlannedQty().subtract(lines[i].getInvoicedQty())); + ol.setPrice(); + if (lines[i].getPlannedPrice() != null && lines[i].getPlannedPrice().compareTo(Env.ZERO) != 0) + ol.setPrice(lines[i].getPlannedPrice()); + ol.setDiscount(); + ol.setTax(); + if (ol.save()) + count++; + } // for all lines + if (lines.length != count) + log.log(Level.SEVERE, "Lines difference - ProjectLines=" + lines.length + " <> Saved=" + count); + } // Order Lines + + return "@C_Order_ID@ " + order.getDocumentNo() + " (" + count + ")"; + } // doIt + + /** + * Get and validate Project + * @param ctx context + * @param C_Project_ID id + * @return valid project + * @param trxName transaction + */ + static protected MProject getProject (Properties ctx, int C_Project_ID, String trxName) + { + MProject fromProject = new MProject (ctx, C_Project_ID, trxName); + if (fromProject.getC_Project_ID() == 0) + throw new IllegalArgumentException("Project not found C_Project_ID=" + C_Project_ID); + if (fromProject.getM_PriceList_Version_ID() == 0) + throw new IllegalArgumentException("Project has no Price List"); + if (fromProject.getM_Warehouse_ID() == 0) + throw new IllegalArgumentException("Project has no Warehouse"); + if (fromProject.getC_BPartner_ID() == 0 || fromProject.getC_BPartner_Location_ID() == 0) + throw new IllegalArgumentException("Project has no Business Partner/Location"); + return fromProject; + } // getProject + +} // ProjectGenOrder diff --git a/base/src/org/compiere/process/ProjectGenPO.java b/base/src/org/compiere/process/ProjectGenPO.java new file mode 100644 index 0000000000..57bf40ee70 --- /dev/null +++ b/base/src/org/compiere/process/ProjectGenPO.java @@ -0,0 +1,187 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.util.*; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Generate Purchase Order from Project. + * + * @author Jorg Janke + * @version $Id: ProjectGenPO.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ProjectGenPO extends SvrProcess +{ + /** Project Parameter */ + private int m_C_Project_ID = 0; + /** Opt Project Line Parameter */ + private int m_C_ProjectLine_ID = 0; + /** Consolidate Document */ + private boolean m_ConsolidateDocument = true; + /** List of POs for Consolidation */ + private ArrayList m_pos = new ArrayList(); + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_Project_ID")) + m_C_Project_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_ProjectLine_ID")) + m_C_ProjectLine_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("ConsolidateDocument")) + m_ConsolidateDocument = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("doIt - C_Project_ID=" + m_C_Project_ID + " - C_ProjectLine_ID=" + m_C_ProjectLine_ID + " - Consolidate=" + m_ConsolidateDocument); + if (m_C_ProjectLine_ID != 0) + { + MProjectLine projectLine = new MProjectLine(getCtx(), m_C_ProjectLine_ID, get_TrxName()); + MProject project = new MProject (getCtx(), projectLine.getC_Project_ID(), get_TrxName()); + createPO (project, projectLine); + } + else + { + MProject project = new MProject (getCtx(), m_C_Project_ID, get_TrxName()); + MProjectLine[] lines = project.getLines(); + for (int i = 0; i < lines.length; i++) + createPO (project, lines[i]); + } + return ""; + } // doIt + + /** + * Create PO from Planned Amt/Qty + * @param projectLine project line + */ + private void createPO (MProject project, MProjectLine projectLine) + { + if (projectLine.getM_Product_ID() == 0) + { + addLog (projectLine.getLine() ,null,null, "Line has no Product"); + return; + } + if (projectLine.getC_OrderPO_ID() != 0) + { + addLog (projectLine.getLine() ,null,null, "Line was ordered previously"); + return; + } + + // PO Record + MProductPO[] pos = MProductPO.getOfProduct(getCtx(), projectLine.getM_Product_ID(), get_TrxName()); + if (pos == null || pos.length == 0) + { + addLog (projectLine.getLine() ,null,null, "Product has no PO record"); + return; + } + + // Create to Order + MOrder order = null; + // try to find PO to C_BPartner + for (int i = 0; i < m_pos.size(); i++) + { + MOrder test = (MOrder)m_pos.get(i); + if (test.getC_BPartner_ID() == pos[0].getC_BPartner_ID()) + { + order = test; + break; + } + } + if (order == null) // create new Order + { + // Vendor + MBPartner bp = new MBPartner (getCtx(), pos[0].getC_BPartner_ID(), get_TrxName()); + // New Order + order = new MOrder (project, false, null); + int AD_Org_ID = projectLine.getAD_Org_ID(); + if (AD_Org_ID == 0) + { + log.warning("createPOfromProjectLine - AD_Org_ID=0"); + AD_Org_ID = Env.getAD_Org_ID(getCtx()); + if (AD_Org_ID != 0) + projectLine.setAD_Org_ID(AD_Org_ID); + } + order.setClientOrg (projectLine.getAD_Client_ID (), AD_Org_ID); + order.setBPartner (bp); + order.save (); + // optionally save for consolidation + if (m_ConsolidateDocument) + m_pos.add(order); + } + + // Create Line + MOrderLine orderLine = new MOrderLine (order); + orderLine.setM_Product_ID(projectLine.getM_Product_ID(), true); + orderLine.setQty(projectLine.getPlannedQty()); + orderLine.setDescription(projectLine.getDescription()); + + // (Vendor) PriceList Price + orderLine.setPrice(); + if (orderLine.getPriceActual().signum() == 0) + { + // Try to find purchase price + BigDecimal poPrice = pos[0].getPricePO(); + int C_Currency_ID = pos[0].getC_Currency_ID(); + // + if (poPrice == null || poPrice.signum() == 0) + poPrice = pos[0].getPriceLastPO(); + if (poPrice == null || poPrice.signum() == 0) + poPrice = pos[0].getPriceList(); + // We have a price + if (poPrice != null && poPrice.signum() != 0) + { + if (order.getC_Currency_ID() != C_Currency_ID) + poPrice = MConversionRate.convert(getCtx(), poPrice, + C_Currency_ID, order.getC_Currency_ID(), + order.getDateAcct(), order.getC_ConversionType_ID(), + order.getAD_Client_ID(), order.getAD_Org_ID()); + orderLine.setPrice(poPrice); + } + } + + orderLine.setTax(); + orderLine.save(); + + // update ProjectLine + projectLine.setC_OrderPO_ID(order.getC_Order_ID()); + projectLine.save(); + addLog (projectLine.getLine(), null, projectLine.getPlannedQty(), order.getDocumentNo()); + } // createPOfromProjectLine + +} // ProjectGenPO diff --git a/base/src/org/compiere/process/ProjectIssue.java b/base/src/org/compiere/process/ProjectIssue.java new file mode 100644 index 0000000000..5c224c76e1 --- /dev/null +++ b/base/src/org/compiere/process/ProjectIssue.java @@ -0,0 +1,356 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Issue to Project. + * + * @author Jorg Janke + * @version $Id: ProjectIssue.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class ProjectIssue extends SvrProcess +{ + /** Project - Mandatory Parameter */ + private int m_C_Project_ID = 0; + /** Receipt - Option 1 */ + private int m_M_InOut_ID = 0; + /** Expenses - Option 2 */ + private int m_S_TimeExpense_ID = 0; + /** Locator - Option 3,4 */ + private int m_M_Locator_ID = 0; + /** Project Line - Option 3 */ + private int m_C_ProjectLine_ID = 0; + /** Product - Option 4 */ + private int m_M_Product_ID = 0; + /** Attribute - Option 4 */ + private int m_M_AttributeSetInstance_ID = 0; + /** Qty - Option 4 */ + private BigDecimal m_MovementQty = null; + /** Date - Option */ + private Timestamp m_MovementDate = null; + /** Description - Option */ + private String m_Description = null; + + /** The Project to be received */ + private MProject m_project = null; + /** The Project to be received */ + private MProjectIssue[] m_projectIssues = null; + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_Project_ID")) + m_C_Project_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("M_InOut_ID")) + m_M_InOut_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("S_TimeExpense_ID")) + m_S_TimeExpense_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("M_Locator_ID")) + m_M_Locator_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_ProjectLine_ID")) + m_C_ProjectLine_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("M_Product_ID")) + m_M_Product_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("M_AttributeSetInstance_ID")) + m_M_AttributeSetInstance_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("MovementQty")) + m_MovementQty = (BigDecimal)para[i].getParameter(); + else if (name.equals("MovementDate")) + m_MovementDate = (Timestamp)para[i].getParameter(); + else if (name.equals("Description")) + m_Description = (String)para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + // Check Parameter + m_project = new MProject (getCtx(), m_C_Project_ID, get_TrxName()); + if (!(MProject.PROJECTCATEGORY_WorkOrderJob.equals(m_project.getProjectCategory()) + || MProject.PROJECTCATEGORY_AssetProject.equals(m_project.getProjectCategory()))) + throw new IllegalArgumentException("Project not Work Order or Asset =" + m_project.getProjectCategory()); + log.info(m_project.toString()); + // + if (m_M_InOut_ID != 0) + return issueReceipt(); + if (m_S_TimeExpense_ID != 0) + return issueExpense(); + if (m_M_Locator_ID == 0) + throw new IllegalArgumentException("Locator missing"); + if (m_C_ProjectLine_ID != 0) + return issueProjectLine(); + return issueInventory(); + } // doIt + + /** + * Issue Receipt + * @return Message (clear text) + */ + private String issueReceipt() + { + MInOut inOut = new MInOut (getCtx(), m_M_InOut_ID, null); + if (inOut.isSOTrx() || !inOut.isProcessed() + || !(MInOut.DOCSTATUS_Completed.equals(inOut.getDocStatus()) || MInOut.DOCSTATUS_Closed.equals(inOut.getDocStatus()))) + throw new IllegalArgumentException ("Receipt not valid - " + inOut); + log.info(inOut.toString()); + // Set Project of Receipt + if (inOut.getC_Project_ID() == 0) + { + inOut.setC_Project_ID(m_project.getC_Project_ID()); + inOut.save(); + } + else if (inOut.getC_Project_ID() != m_project.getC_Project_ID()) + throw new IllegalArgumentException ("Receipt for other Project (" + + inOut.getC_Project_ID() + ")"); + + MInOutLine[] inOutLines = inOut.getLines(false); + int counter = 0; + for (int i = 0; i < inOutLines.length; i++) + { + // Need to have a Product + if (inOutLines[i].getM_Product_ID() == 0) + continue; + // Need to have Quantity + if (inOutLines[i].getMovementQty() == null || inOutLines[i].getMovementQty().signum() == 0) + continue; + // not issued yet + if (projectIssueHasReceipt(inOutLines[i].getM_InOutLine_ID())) + continue; + // Create Issue + MProjectIssue pi = new MProjectIssue (m_project); + pi.setMandatory (inOutLines[i].getM_Locator_ID(), inOutLines[i].getM_Product_ID(), inOutLines[i].getMovementQty()); + if (m_MovementDate != null) // default today + pi.setMovementDate(m_MovementDate); + if (m_Description != null && m_Description.length() > 0) + pi.setDescription(m_Description); + else if (inOutLines[i].getDescription() != null) + pi.setDescription(inOutLines[i].getDescription()); + else if (inOut.getDescription() != null) + pi.setDescription(inOut.getDescription()); + pi.setM_InOutLine_ID(inOutLines[i].getM_InOutLine_ID()); + pi.process(); + + // Find/Create Project Line + MProjectLine pl = null; + MProjectLine[] pls = m_project.getLines(); + for (int ii = 0; ii < pls.length; ii++) + { + // The Order we generated is the same as the Order of the receipt + if (pls[ii].getC_OrderPO_ID() == inOut.getC_Order_ID() + && pls[ii].getM_Product_ID() == inOutLines[i].getM_Product_ID() + && pls[ii].getC_ProjectIssue_ID() == 0) // not issued + { + pl = pls[ii]; + break; + } + } + if (pl == null) + pl = new MProjectLine(m_project); + pl.setMProjectIssue(pi); // setIssue + pl.save(); + addLog(pi.getLine(), pi.getMovementDate(), pi.getMovementQty(), null); + counter++; + } // all InOutLines + + return "@Created@ " + counter; + } // issueReceipt + + + /** + * Issue Expense Report + * @return Message (clear text) + */ + private String issueExpense() + { + // Get Expense Report + MTimeExpense expense = new MTimeExpense (getCtx(), m_S_TimeExpense_ID, get_TrxName()); + if (!expense.isProcessed()) + throw new IllegalArgumentException ("Time+Expense not processed - " + expense); + + // for all expense lines + MTimeExpenseLine[] expenseLines = expense.getLines(false); + int counter = 0; + for (int i = 0; i < expenseLines.length; i++) + { + // Need to have a Product + if (expenseLines[i].getM_Product_ID() == 0) + continue; + // Need to have Quantity + if (expenseLines[i].getQty() == null || expenseLines[i].getQty().signum() == 0) + continue; + // Need to the same project + if (expenseLines[i].getC_Project_ID() != m_project.getC_Project_ID()) + continue; + // not issued yet + if (projectIssueHasExpense(expenseLines[i].getS_TimeExpenseLine_ID())) + continue; + + // Find Location + int M_Locator_ID = 0; + // MProduct product = new MProduct (getCtx(), expenseLines[i].getM_Product_ID()); + // if (product.isStocked()) + M_Locator_ID = MStorage.getM_Locator_ID(expense.getM_Warehouse_ID(), + expenseLines[i].getM_Product_ID(), 0, // no ASI + expenseLines[i].getQty(), null); + if (M_Locator_ID == 0) // Service/Expense - get default (and fallback) + M_Locator_ID = expense.getM_Locator_ID(); + + // Create Issue + MProjectIssue pi = new MProjectIssue (m_project); + pi.setMandatory (M_Locator_ID, expenseLines[i].getM_Product_ID(), expenseLines[i].getQty()); + if (m_MovementDate != null) // default today + pi.setMovementDate(m_MovementDate); + if (m_Description != null && m_Description.length() > 0) + pi.setDescription(m_Description); + else if (expenseLines[i].getDescription() != null) + pi.setDescription(expenseLines[i].getDescription()); + pi.setS_TimeExpenseLine_ID(expenseLines[i].getS_TimeExpenseLine_ID()); + pi.process(); + // Find/Create Project Line + MProjectLine pl = new MProjectLine(m_project); + pl.setMProjectIssue(pi); // setIssue + pl.save(); + addLog(pi.getLine(), pi.getMovementDate(), pi.getMovementQty(), null); + counter++; + } // allExpenseLines + + return "@Created@ " + counter; + } // issueExpense + + + /** + * Issue Project Line + * @return Message (clear text) + */ + private String issueProjectLine() + { + MProjectLine pl = new MProjectLine(getCtx(), m_C_ProjectLine_ID, get_TrxName()); + if (pl.getM_Product_ID() == 0) + throw new IllegalArgumentException("Projet Line has no Product"); + if (pl.getC_ProjectIssue_ID() != 0) + throw new IllegalArgumentException("Projet Line already been issued"); + if (m_M_Locator_ID == 0) + throw new IllegalArgumentException("No Locator"); + // Set to Qty 1 + if (pl.getPlannedQty() == null || pl.getPlannedQty().signum() == 0) + pl.setPlannedQty(Env.ONE); + // + MProjectIssue pi = new MProjectIssue (m_project); + pi.setMandatory (m_M_Locator_ID, pl.getM_Product_ID(), pl.getPlannedQty()); + if (m_MovementDate != null) // default today + pi.setMovementDate(m_MovementDate); + if (m_Description != null && m_Description.length() > 0) + pi.setDescription(m_Description); + else if (pl.getDescription() != null) + pi.setDescription(pl.getDescription()); + pi.process(); + + // Update Line + pl.setMProjectIssue(pi); + pl.save(); + addLog(pi.getLine(), pi.getMovementDate(), pi.getMovementQty(), null); + return "@Created@ 1"; + } // issueProjectLine + + + /** + * Issue from Inventory + * @return Message (clear text) + */ + private String issueInventory() + { + if (m_M_Locator_ID == 0) + throw new IllegalArgumentException("No Locator"); + if (m_M_Product_ID == 0) + throw new IllegalArgumentException("No Product"); + // Set to Qty 1 + if (m_MovementQty == null || m_MovementQty.signum() == 0) + m_MovementQty = Env.ONE; + // + MProjectIssue pi = new MProjectIssue (m_project); + pi.setMandatory (m_M_Locator_ID, m_M_Product_ID, m_MovementQty); + if (m_MovementDate != null) // default today + pi.setMovementDate(m_MovementDate); + if (m_Description != null && m_Description.length() > 0) + pi.setDescription(m_Description); + pi.process(); + + // Create Project Line + MProjectLine pl = new MProjectLine(m_project); + pl.setMProjectIssue(pi); + pl.save(); + addLog(pi.getLine(), pi.getMovementDate(), pi.getMovementQty(), null); + return "@Created@ 1"; + } // issueInventory + + /** + * Check if Project Issue already has Expense + * @param S_TimeExpenseLine_ID line + * @return true if exists + */ + private boolean projectIssueHasExpense (int S_TimeExpenseLine_ID) + { + if (m_projectIssues == null) + m_projectIssues = m_project.getIssues(); + for (int i = 0; i < m_projectIssues.length; i++) + { + if (m_projectIssues[i].getS_TimeExpenseLine_ID() == S_TimeExpenseLine_ID) + return true; + } + return false; + } // projectIssueHasExpense + + /** + * Check if Project Isssye already has Receipt + * @param M_InOutLine_ID line + * @return true if exists + */ + private boolean projectIssueHasReceipt (int M_InOutLine_ID) + { + if (m_projectIssues == null) + m_projectIssues = m_project.getIssues(); + for (int i = 0; i < m_projectIssues.length; i++) + { + if (m_projectIssues[i].getM_InOutLine_ID() == M_InOutLine_ID) + return true; + } + return false; + } // projectIssueHasReceipt + +} // ProjectIssue diff --git a/base/src/org/compiere/process/ProjectLinePricing.java b/base/src/org/compiere/process/ProjectLinePricing.java new file mode 100644 index 0000000000..ca8347bf9d --- /dev/null +++ b/base/src/org/compiere/process/ProjectLinePricing.java @@ -0,0 +1,86 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + + +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Price Project Line. + * + * @author Jorg Janke + * @version $Id: ProjectLinePricing.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class ProjectLinePricing extends SvrProcess +{ + /** Project Line from Record */ + private int m_C_ProjectLine_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + m_C_ProjectLine_ID = getRecord_ID(); + } // prepare + + /** + * Perform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + if (m_C_ProjectLine_ID == 0) + throw new IllegalArgumentException("No Project Line"); + MProjectLine projectLine = new MProjectLine (getCtx(), m_C_ProjectLine_ID, get_TrxName()); + log.info("doIt - " + projectLine); + if (projectLine.getM_Product_ID() == 0) + throw new IllegalArgumentException("No Product"); + // + MProject project = new MProject (getCtx(), projectLine.getC_Project_ID(), get_TrxName()); + if (project.getM_PriceList_ID() == 0) + throw new IllegalArgumentException("No PriceList"); + // + boolean isSOTrx = true; + MProductPricing pp = new MProductPricing (projectLine.getM_Product_ID(), + project.getC_BPartner_ID(), projectLine.getPlannedQty(), isSOTrx); + pp.setM_PriceList_ID(project.getM_PriceList_ID()); + pp.setPriceDate(project.getDateContract()); + // + projectLine.setPlannedPrice(pp.getPriceStd()); + projectLine.setPlannedMarginAmt(pp.getPriceStd().subtract(pp.getPriceLimit())); + projectLine.save(); + // + String retValue = Msg.getElement(getCtx(), "PriceList") + pp.getPriceList() + " - " + + Msg.getElement(getCtx(), "PriceStd") + pp.getPriceStd() + " - " + + Msg.getElement(getCtx(), "PriceLimit") + pp.getPriceLimit(); + return retValue; + } // doIt + +} // ProjectLinePricing diff --git a/base/src/org/compiere/process/ProjectPhaseGenOrder.java b/base/src/org/compiere/process/ProjectPhaseGenOrder.java new file mode 100644 index 0000000000..21d32e6bc9 --- /dev/null +++ b/base/src/org/compiere/process/ProjectPhaseGenOrder.java @@ -0,0 +1,115 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Generate Order from Project Phase + * + * @author Jorg Janke + * @version $Id: ProjectPhaseGenOrder.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ProjectPhaseGenOrder extends SvrProcess +{ + private int m_C_ProjectPhase_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + m_C_ProjectPhase_ID = getRecord_ID(); + log.info("doIt - C_ProjectPhase_ID=" + m_C_ProjectPhase_ID); + if (m_C_ProjectPhase_ID == 0) + throw new IllegalArgumentException("C_ProjectPhase_ID == 0"); + MProjectPhase fromPhase = new MProjectPhase (getCtx(), m_C_ProjectPhase_ID, get_TrxName()); + MProject fromProject = ProjectGenOrder.getProject (getCtx(), fromPhase.getC_Project_ID(), get_TrxName()); + MOrder order = new MOrder (fromProject, true, MOrder.DocSubTypeSO_OnCredit); + order.setDescription(order.getDescription() + " - " + fromPhase.getName()); + if (!order.save()) + throw new Exception("Could not create Order"); + + // Create an order on Phase Level + if (fromPhase.getM_Product_ID() != 0) + { + MOrderLine ol = new MOrderLine(order); + ol.setLine(fromPhase.getSeqNo()); + StringBuffer sb = new StringBuffer (fromPhase.getName()); + if (fromPhase.getDescription() != null && fromPhase.getDescription().length() > 0) + sb.append(" - ").append(fromPhase.getDescription()); + ol.setDescription(sb.toString()); + // + ol.setM_Product_ID(fromPhase.getM_Product_ID(), true); + ol.setQty(fromPhase.getQty()); + ol.setPrice(); + if (fromPhase.getPriceActual() != null && fromPhase.getPriceActual().compareTo(Env.ZERO) != 0) + ol.setPrice(fromPhase.getPriceActual()); + ol.setTax(); + if (!ol.save()) + log.log(Level.SEVERE, "doIt - Lines not generated"); + return "@C_Order_ID@ " + order.getDocumentNo() + " (1)"; + } + + // Project Tasks + int count = 0; + MProjectTask[] tasks = fromPhase.getTasks (); + for (int i = 0; i < tasks.length; i++) + { + MOrderLine ol = new MOrderLine(order); + ol.setLine(tasks[i].getSeqNo()); + StringBuffer sb = new StringBuffer (tasks[i].getName()); + if (tasks[i].getDescription() != null && tasks[i].getDescription().length() > 0) + sb.append(" - ").append(tasks[i].getDescription()); + ol.setDescription(sb.toString()); + // + ol.setM_Product_ID(tasks[i].getM_Product_ID(), true); + ol.setQty(tasks[i].getQty()); + ol.setPrice(); + ol.setTax(); + if (ol.save()) + count++; + } // for all lines + if (tasks.length != count) + log.log(Level.SEVERE, "doIt - Lines difference - ProjectTasks=" + tasks.length + " <> Saved=" + count); + + return "@C_Order_ID@ " + order.getDocumentNo() + " (" + count + ")"; + } // doIt + +} // ProjectPhaseGenOrder diff --git a/base/src/org/compiere/process/ProjectSetType.java b/base/src/org/compiere/process/ProjectSetType.java new file mode 100644 index 0000000000..58681d81f9 --- /dev/null +++ b/base/src/org/compiere/process/ProjectSetType.java @@ -0,0 +1,82 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.util.logging.*; +import org.compiere.model.*; + +/** + * Set Project Type + * + * @author Jorg Janke + * @version $Id: ProjectSetType.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class ProjectSetType extends SvrProcess +{ + /** Project directly from Project */ + private int m_C_Project_ID = 0; + /** Project Type Parameter */ + private int m_C_ProjectType_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + continue; + else if (name.equals("C_ProjectType_ID")) + m_C_ProjectType_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + m_C_Project_ID = getRecord_ID(); + log.info("doIt - C_Project_ID=" + m_C_Project_ID + ", C_ProjectType_ID=" + m_C_ProjectType_ID); + // + MProject project = new MProject (getCtx(), m_C_Project_ID, get_TrxName()); + if (project.getC_Project_ID() == 0 || project.getC_Project_ID() != m_C_Project_ID) + throw new IllegalArgumentException("Project not found C_Project_ID=" + m_C_Project_ID); + if (project.getC_ProjectType_ID_Int() > 0) + throw new IllegalArgumentException("Project already has Type (Cannot overwrite) " + project.getC_ProjectType_ID()); + // + MProjectType type = new MProjectType (getCtx(), m_C_ProjectType_ID, get_TrxName()); + if (type.getC_ProjectType_ID() == 0 || type.getC_ProjectType_ID() != m_C_ProjectType_ID) + throw new IllegalArgumentException("Project Type not found C_ProjectType_ID=" + m_C_ProjectType_ID); + + // Set & Copy if Service + project.setProjectType(type); + if (!project.save()) + throw new Exception ("@Error@"); + // + return "@OK@"; + } // doIt + +} // ProjectSetType diff --git a/base/src/org/compiere/process/Recurring.java b/base/src/org/compiere/process/Recurring.java new file mode 100644 index 0000000000..4788a7e55e --- /dev/null +++ b/base/src/org/compiere/process/Recurring.java @@ -0,0 +1,58 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import org.compiere.model.*; + +/** + * Recurring Process + * + * @author Jorg Janke + * @version $Id: Recurring.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class Recurring extends SvrProcess +{ + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + MRecurring rec = new MRecurring (getCtx(), getRecord_ID(), get_TrxName()); + log.info(rec.toString()); + return rec.executeRun(); + } // doIt + +} // Recurring diff --git a/base/src/org/compiere/process/RegisterSystem.java b/base/src/org/compiere/process/RegisterSystem.java new file mode 100644 index 0000000000..5838f6f6d4 --- /dev/null +++ b/base/src/org/compiere/process/RegisterSystem.java @@ -0,0 +1,167 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.io.*; +import java.net.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * System Registration + * + * @author Jorg Janke + * @version $Id: RegisterSystem.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class RegisterSystem extends SvrProcess +{ + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * DoIt + * @return Message + * @throws Exception + */ + protected String doIt() throws Exception + { + int AD_Registration_ID = getRecord_ID(); + log.info("doIt - AD_Registration_ID=" + AD_Registration_ID); + // Check Ststem + MSystem sys = MSystem.get(getCtx()); + if (sys.getName().equals("?") || sys.getName().length()<2) + throw new AdempiereUserError("Set System Name in System Record"); + if (sys.getUserName().equals("?") || sys.getUserName().length()<2) + throw new AdempiereUserError("Set User Name (as in Web Store) in System Record"); + if (sys.getPassword().equals("?") || sys.getPassword().length()<2) + throw new AdempiereUserError("Set Password (as in Web Store) in System Record"); + // Registration + M_Registration reg = new M_Registration (getCtx(), AD_Registration_ID, get_TrxName()); + // Location + MLocation loc = null; + if (reg.getC_Location_ID() > 0) + { + loc = new MLocation (getCtx(), reg.getC_Location_ID(), get_TrxName()); + if (loc.getCity() == null || loc.getCity().length() < 2) + throw new AdempiereUserError("No City in Address"); + } + if (loc == null) + throw new AdempiereUserError("Please enter Address with City"); + + // Create Query String + String enc = WebEnv.ENCODING; + // Send GET Request + StringBuffer urlString = new StringBuffer ("http://www.adempiere.com") + .append("/wstore/registrationServlet?"); + // System Info + urlString.append("Name=").append(URLEncoder.encode(sys.getName(), enc)) + .append("&UserName=").append(URLEncoder.encode(sys.getUserName(), enc)) + .append("&Password=").append(URLEncoder.encode(sys.getPassword(), enc)); + // Registration Info + if (reg.getDescription() != null && reg.getDescription().length() > 0) + urlString.append("&Description=").append(URLEncoder.encode(reg.getDescription(), enc)); + urlString.append("&IsInProduction=").append(reg.isInProduction() ? "Y" : "N"); + if (reg.getStartProductionDate() != null) + urlString.append("&StartProductionDate=").append(URLEncoder.encode(String.valueOf(reg.getStartProductionDate()), enc)); + urlString.append("&IsAllowPublish=").append(reg.isAllowPublish() ? "Y" : "N") + .append("&NumberEmployees=").append(URLEncoder.encode(String.valueOf(reg.getNumberEmployees()), enc)) + .append("&C_Currency_ID=").append(URLEncoder.encode(String.valueOf(reg.getC_Currency_ID()), enc)) + .append("&SalesVolume=").append(URLEncoder.encode(String.valueOf(reg.getSalesVolume()), enc)); + if (reg.getIndustryInfo() != null && reg.getIndustryInfo().length() > 0) + urlString.append("&IndustryInfo=").append(URLEncoder.encode(reg.getIndustryInfo(), enc)); + if (reg.getPlatformInfo() != null && reg.getPlatformInfo().length() > 0) + urlString.append("&PlatformInfo=").append(URLEncoder.encode(reg.getPlatformInfo(), enc)); + urlString.append("&IsRegistered=").append(reg.isRegistered() ? "Y" : "N") + .append("&Record_ID=").append(URLEncoder.encode(String.valueOf(reg.getRecord_ID()), enc)); + // Address + urlString.append("&City=").append(URLEncoder.encode(loc.getCity(), enc)) + .append("&C_Country_ID=").append(URLEncoder.encode(String.valueOf(loc.getC_Country_ID()), enc)); + // Statistics + if (reg.isAllowStatistics()) + { + urlString.append("&NumClient=").append(URLEncoder.encode(String.valueOf( + DB.getSQLValue(null, "SELECT Count(*) FROM AD_Client")), enc)) + .append("&NumOrg=").append(URLEncoder.encode(String.valueOf( + DB.getSQLValue(null, "SELECT Count(*) FROM AD_Org")), enc)) + .append("&NumBPartner=").append(URLEncoder.encode(String.valueOf( + DB.getSQLValue(null, "SELECT Count(*) FROM C_BPartner")), enc)) + .append("&NumUser=").append(URLEncoder.encode(String.valueOf( + DB.getSQLValue(null, "SELECT Count(*) FROM AD_User")), enc)) + .append("&NumProduct=").append(URLEncoder.encode(String.valueOf( + DB.getSQLValue(null, "SELECT Count(*) FROM M_Product")), enc)) + .append("&NumInvoice=").append(URLEncoder.encode(String.valueOf( + DB.getSQLValue(null, "SELECT Count(*) FROM C_Invoice")), enc)); + } + log.fine(urlString.toString()); + + // Send it + URL url = new URL (urlString.toString()); + StringBuffer sb = new StringBuffer(); + try + { + URLConnection uc = url.openConnection(); + InputStreamReader in = new InputStreamReader(uc.getInputStream()); + int c; + while ((c = in.read()) != -1) + sb.append((char)c); + in.close(); + } + catch (Exception e) + { + log.log(Level.SEVERE, "Connect - " + e.toString()); + throw new IllegalStateException("Cannot connect to Server - Please try later"); + } + // + String info = sb.toString(); + log.info("Response=" + info); + // Record at the end + int index = sb.indexOf("Record_ID="); + if (index != -1) + { + try + { + int Record_ID = Integer.parseInt(sb.substring(index+10)); + reg.setRecord_ID(Record_ID); + reg.setIsRegistered(true); + reg.save(); + // + info = info.substring(0, index); + } + catch (Exception e) + { + log.log(Level.SEVERE, "Record - ", e); + } + } + + return info; + } // doIt + +} // RegisterSystem diff --git a/base/src/org/compiere/process/RemoteMergeDataVO.java b/base/src/org/compiere/process/RemoteMergeDataVO.java new file mode 100644 index 0000000000..38206ab19a --- /dev/null +++ b/base/src/org/compiere/process/RemoteMergeDataVO.java @@ -0,0 +1,50 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.io.*; +import javax.sql.*; + +/** + * Merge New Data To/From Remote + * + * @author Jorg Janke + * @version $Id: RemoteMergeDataVO.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class RemoteMergeDataVO implements Serializable +{ + + public Boolean Test = Boolean.FALSE; + public String TableName = null; + public String Sql = null; + public String[] KeyColumns = null; + public RowSet CentralData = null; + + /** + * String Representation + * @return info + */ + public String toString() + { + return "RemoteNewDataVO[test=" + Test + + "-" + TableName + // + "," + Sql + + "]"; + } // toString + + +} // RemoteNewDataVO diff --git a/base/src/org/compiere/process/RemoteSetupVO.java b/base/src/org/compiere/process/RemoteSetupVO.java new file mode 100644 index 0000000000..b1e8d108cf --- /dev/null +++ b/base/src/org/compiere/process/RemoteSetupVO.java @@ -0,0 +1,54 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.io.*; +import java.math.BigDecimal; +import javax.sql.RowSet; + +/** + * Remote Setup VO + * + * @author Jorg Janke + * @version $Id: RemoteSetupVO.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class RemoteSetupVO implements Serializable +{ + + public Boolean Test = Boolean.FALSE; + public RowSet ReplicationTable = null; + public BigDecimal IDRangeStart = null; + public BigDecimal IDRangeEnd = null; + public int AD_Client_ID = -1; + public int AD_Org_ID = -1; + public String Prefix = null; + public String Suffix = null; + + /** + * String Representation + * @return info + */ + public String toString() + { + return "RemoteSetupVO[test=" + Test + + ",IDRange=" + IDRangeStart + "-" + IDRangeEnd + + ",AD_Client_ID=" + AD_Client_ID + ",AD_Org_ID=" + AD_Org_ID + + ",Prefix=" + Prefix + ",Suffix=" + Suffix + + "]"; + } // toString + +} // RemoteSetupVO diff --git a/base/src/org/compiere/process/RemoteUpdateVO.java b/base/src/org/compiere/process/RemoteUpdateVO.java new file mode 100644 index 0000000000..024fd25c46 --- /dev/null +++ b/base/src/org/compiere/process/RemoteUpdateVO.java @@ -0,0 +1,51 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.io.*; +import javax.sql.*; + +/** + * Send New Data To Remote for Update + * + * @author Jorg Janke + * @version $Id: RemoteUpdateVO.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class RemoteUpdateVO implements Serializable +{ + + public Boolean Test = Boolean.FALSE; +// public Integer AD_Table_ID = null; + public String TableName = null; + public String Sql = null; + public String[] KeyColumns = null; + public RowSet CentralData = null; + + /** + * String Representation + * @return info + */ + public String toString() + { + return "RemoteUpdateVO[test=" + Test + + "-" + TableName + // + "," + Sql + + "]"; + } // toString + + +} // RemoteUpdateVO diff --git a/base/src/org/compiere/process/ReplenishReport.java b/base/src/org/compiere/process/ReplenishReport.java new file mode 100644 index 0000000000..0484be9d05 --- /dev/null +++ b/base/src/org/compiere/process/ReplenishReport.java @@ -0,0 +1,589 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.*; +import java.math.*; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Replenishment Report + * + * @author Jorg Janke + * @version $Id: ReplenishReport.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ReplenishReport extends SvrProcess +{ + /** Warehouse */ + private int p_M_Warehouse_ID = 0; + /** Optional BPartner */ + private int p_C_BPartner_ID = 0; + /** Create (POO)Purchse Order or (POR)Requisition or (MMM)Movements */ + private String p_ReplenishmentCreate = null; + /** Document Type */ + private int p_C_DocType_ID = 0; + /** Return Info */ + private String m_info = ""; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("M_Warehouse_ID")) + p_M_Warehouse_ID = para[i].getParameterAsInt(); + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = para[i].getParameterAsInt(); + else if (name.equals("ReplenishmentCreate")) + p_ReplenishmentCreate = (String)para[i].getParameter(); + else if (name.equals("C_DocType_ID")) + p_C_DocType_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("M_Warehouse_ID=" + p_M_Warehouse_ID + + ", C_BPartner_ID=" + p_C_BPartner_ID + + " - ReplenishmentCreate=" + p_ReplenishmentCreate + + ", C_DocType_ID=" + p_C_DocType_ID); + if (p_ReplenishmentCreate != null && p_C_DocType_ID == 0) + throw new AdempiereUserError("@FillMandatory@ @C_DocType_ID@"); + + MWarehouse wh = MWarehouse.get(getCtx(), p_M_Warehouse_ID); + if (wh.get_ID() == 0) + throw new AdempiereSystemError("@FillMandatory@ @M_Warehouse_ID@"); + // + prepareTable(); + fillTable(wh); + // + if (p_ReplenishmentCreate == null) + return "OK"; + // + MDocType dt = MDocType.get(getCtx(), p_C_DocType_ID); + if (!dt.getDocBaseType().equals(p_ReplenishmentCreate)) + throw new AdempiereSystemError("@C_DocType_ID@=" + dt.getName() + " <> " + p_ReplenishmentCreate); + // + if (p_ReplenishmentCreate.equals("POO")) + createPO(); + else if (p_ReplenishmentCreate.equals("POR")) + createRequisition(); + else if (p_ReplenishmentCreate.equals("MMM")) + createMovements(); + return m_info; + } // doIt + + /** + * Prepare/Check Replenishment Table + */ + private void prepareTable() + { + // Level_Max must be >= Level_Max + String sql = "UPDATE M_Replenish" + + " SET Level_Max = Level_Min " + + "WHERE Level_Max < Level_Min"; + int no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Corrected Max_Level=" + no); + + // Minimum Order should be 1 + sql = "UPDATE M_Product_PO" + + " SET Order_Min = 1 " + + "WHERE Order_Min IS NULL OR Order_Min < 1"; + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Corrected Order Min=" + no); + + // Pack should be 1 + sql = "UPDATE M_Product_PO" + + " SET Order_Pack = 1 " + + "WHERE Order_Pack IS NULL OR Order_Pack < 1"; + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Corrected Order Pack=" + no); + + // Set Current Vendor where only one vendor + sql = "UPDATE M_Product_PO p" + + " SET IsCurrentVendor='Y' " + + "WHERE IsCurrentVendor<>'Y'" + + " AND EXISTS (SELECT * FROM M_Product_PO pp " + + "WHERE p.M_Product_ID=pp.M_Product_ID " + + "GROUP BY pp.M_Product_ID " + + "HAVING COUNT(*) = 1)"; + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Corrected CurrentVendor(Y)=" + no); + + // More then one current vendor + sql = "UPDATE M_Product_PO p" + + " SET IsCurrentVendor='N' " + + "WHERE IsCurrentVendor = 'Y'" + + " AND EXISTS (SELECT * FROM M_Product_PO pp " + + "WHERE p.M_Product_ID=pp.M_Product_ID AND pp.IsCurrentVendor='Y' " + + "GROUP BY pp.M_Product_ID " + + "HAVING COUNT(*) > 1)"; + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Corrected CurrentVendor(N)=" + no); + + // Just to be sure + sql = "DELETE T_Replenish WHERE AD_PInstance_ID=" + getAD_PInstance_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Delete Existing Temp=" + no); + } // prepareTable + + /** + * Fill Table + * @param wh warehouse + */ + private void fillTable (MWarehouse wh) throws Exception + { + String sql = "INSERT INTO T_Replenish " + + "(AD_PInstance_ID, M_Warehouse_ID, M_Product_ID, AD_Client_ID, AD_Org_ID," + + " ReplenishType, Level_Min, Level_Max," + + " C_BPartner_ID, Order_Min, Order_Pack, QtyToOrder, ReplenishmentCreate) " + + "SELECT " + getAD_PInstance_ID() + + ", r.M_Warehouse_ID, r.M_Product_ID, r.AD_Client_ID, r.AD_Org_ID," + + " r.ReplenishType, r.Level_Min, r.Level_Max," + + " po.C_BPartner_ID, po.Order_Min, po.Order_Pack, 0, "; + if (p_ReplenishmentCreate == null) + sql += "null"; + else + sql += "'" + p_ReplenishmentCreate + "'"; + sql += " FROM M_Replenish r" + + " INNER JOIN M_Product_PO po ON (r.M_Product_ID=po.M_Product_ID) " + + "WHERE po.IsCurrentVendor='Y'" // Only Current Vendor + + " AND r.ReplenishType<>'0'" + + " AND po.IsActive='Y' AND r.IsActive='Y'" + + " AND r.M_Warehouse_ID=" + p_M_Warehouse_ID; + if (p_C_BPartner_ID != 0) + sql += " AND po.C_BPartner_ID=" + p_C_BPartner_ID; + int no = DB.executeUpdate(sql, get_TrxName()); + log.finest(sql); + log.fine("Insert (1) #" + no); + + if (p_C_BPartner_ID == 0) + { + sql = "INSERT INTO T_Replenish " + + "(AD_PInstance_ID, M_Warehouse_ID, M_Product_ID, AD_Client_ID, AD_Org_ID," + + " ReplenishType, Level_Min, Level_Max," + + " C_BPartner_ID, Order_Min, Order_Pack, QtyToOrder, ReplenishmentCreate) " + + "SELECT " + getAD_PInstance_ID() + + ", r.M_Warehouse_ID, r.M_Product_ID, r.AD_Client_ID, r.AD_Org_ID," + + " r.ReplenishType, r.Level_Min, r.Level_Max," + + " null, 1, 1, 0, "; + if (p_ReplenishmentCreate == null) + sql += "null"; + else + sql += "'" + p_ReplenishmentCreate + "'"; + sql += " FROM M_Replenish r " + + "WHERE r.ReplenishType<>'0' AND r.IsActive='Y'" + + " AND r.M_Warehouse_ID=" + p_M_Warehouse_ID + + " AND NOT EXISTS (SELECT * FROM T_Replenish t " + + "WHERE r.M_Product_ID=t.M_Product_ID" + + " AND AD_PInstance_ID=" + getAD_PInstance_ID() + ")"; + no = DB.executeUpdate(sql, get_TrxName()); + log.fine("Insert (BP) #" + no); + } + + sql = "UPDATE T_Replenish t SET " + + "QtyOnHand = (SELECT SUM(QtyOnHand) FROM M_Storage s, M_Locator l WHERE t.M_Product_ID=s.M_Product_ID" + + " AND l.M_Locator_ID=s.M_Locator_ID AND l.M_Warehouse_ID=t.M_Warehouse_ID)," + + "QtyReserved = (SELECT SUM(QtyReserved) FROM M_Storage s, M_Locator l WHERE t.M_Product_ID=s.M_Product_ID" + + " AND l.M_Locator_ID=s.M_Locator_ID AND l.M_Warehouse_ID=t.M_Warehouse_ID)," + + "QtyOrdered = (SELECT SUM(QtyOrdered) FROM M_Storage s, M_Locator l WHERE t.M_Product_ID=s.M_Product_ID" + + " AND l.M_Locator_ID=s.M_Locator_ID AND l.M_Warehouse_ID=t.M_Warehouse_ID)"; + if (p_C_DocType_ID != 0) + sql += ", C_DocType_ID=" + p_C_DocType_ID; + sql += " WHERE AD_PInstance_ID=" + getAD_PInstance_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Update #" + no); + + // Delete inactive products and replenishments + sql = "DELETE T_Replenish r " + + "WHERE (EXISTS (SELECT * FROM M_Product p " + + "WHERE p.M_Product_ID=r.M_Product_ID AND p.IsActive='N')" + + " OR EXISTS (SELECT * FROM M_Replenish rr " + + " WHERE rr.M_Product_ID=r.M_Product_ID AND rr.IsActive='N'))" + + " AND AD_PInstance_ID=" + getAD_PInstance_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Delete Inactive=" + no); + + // Ensure Data consistency + sql = "UPDATE T_Replenish SET QtyOnHand = 0 WHERE QtyOnHand IS NULL"; + no = DB.executeUpdate(sql, get_TrxName()); + sql = "UPDATE T_Replenish SET QtyReserved = 0 WHERE QtyReserved IS NULL"; + no = DB.executeUpdate(sql, get_TrxName()); + sql = "UPDATE T_Replenish SET QtyOrdered = 0 WHERE QtyOrdered IS NULL"; + no = DB.executeUpdate(sql, get_TrxName()); + + // Set Minimum / Maximum Maintain Level + // X_M_Replenish.REPLENISHTYPE_ReorderBelowMinimumLevel + sql = "UPDATE T_Replenish" + + " SET QtyToOrder = Level_Min - QtyOnHand + QtyReserved - QtyOrdered " + + "WHERE ReplenishType='1'" + + " AND AD_PInstance_ID=" + getAD_PInstance_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Update Type-1=" + no); + // + // X_M_Replenish.REPLENISHTYPE_MaintainMaximumLevel + sql = "UPDATE T_Replenish" + + " SET QtyToOrder = Level_Max - QtyOnHand + QtyReserved - QtyOrdered " + + "WHERE ReplenishType='2'" + + " AND AD_PInstance_ID=" + getAD_PInstance_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Update Type-2=" + no); + + // Delete rows where nothing to order + sql = "DELETE T_Replenish " + + "WHERE QtyToOrder < 1" + + " AND AD_PInstance_ID=" + getAD_PInstance_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Delete No QtyToOrder=" + no); + + // Minimum Order Quantity + sql = "UPDATE T_Replenish" + + " SET QtyToOrder = Order_Min " + + "WHERE QtyToOrder < Order_Min" + + " AND AD_PInstance_ID=" + getAD_PInstance_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Set MinOrderQty=" + no); + + // Even dividable by Pack + sql = "UPDATE T_Replenish" + + " SET QtyToOrder = QtyToOrder - MOD(QtyToOrder, Order_Pack) + Order_Pack " + + "WHERE MOD(QtyToOrder, Order_Pack) <> 0" + + " AND AD_PInstance_ID=" + getAD_PInstance_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Set OrderPackQty=" + no); + + // Source from other warehouse + if (wh.getM_WarehouseSource_ID() != 0) + { + sql = "UPDATE T_Replenish" + + " SET M_WarehouseSource_ID=" + wh.getM_WarehouseSource_ID() + + " WHERE AD_PInstance_ID=" + getAD_PInstance_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Set Source Warehouse=" + no); + } + // Check Source Warehouse + sql = "UPDATE T_Replenish" + + " SET M_WarehouseSource_ID = NULL " + + "WHERE M_Warehouse_ID=M_WarehouseSource_ID" + + " AND AD_PInstance_ID=" + getAD_PInstance_ID(); + no = DB.executeUpdate(sql, get_TrxName()); + if (no != 0) + log.fine("Set same Source Warehouse=" + no); + + // Custom Replenishment + String className = wh.getReplenishmentClass(); + if (className == null || className.length() == 0) + return; + // Get Replenishment Class + ReplenishInterface custom = null; + try + { + Class clazz = Class.forName(className); + custom = (ReplenishInterface)clazz.newInstance(); + } + catch (Exception e) + { + throw new AdempiereUserError("No custom Replenishment class " + + className + " - " + e.toString()); + } + + X_T_Replenish[] replenishs = getReplenish("ReplenishType='9'"); + for (int i = 0; i < replenishs.length; i++) + { + X_T_Replenish replenish = replenishs[i]; + if (replenish.getReplenishType().equals(X_T_Replenish.REPLENISHTYPE_Custom)) + { + BigDecimal qto = null; + try + { + qto = custom.getQtyToOrder(wh, replenish); + } + catch (Exception e) + { + log.log(Level.SEVERE, custom.toString(), e); + } + if (qto == null) + qto = Env.ZERO; + replenish.setQtyToOrder(qto); + replenish.save(); + } + } + } // fillTable + + /** + * Create PO's + */ + private void createPO() + { + int noOrders = 0; + String info = ""; + // + MOrder order = null; + MWarehouse wh = null; + X_T_Replenish[] replenishs = getReplenish("M_WarehouseSource_ID IS NULL"); + for (int i = 0; i < replenishs.length; i++) + { + X_T_Replenish replenish = replenishs[i]; + if (wh == null || wh.getM_Warehouse_ID() != replenish.getM_Warehouse_ID()) + wh = MWarehouse.get(getCtx(), replenish.getM_Warehouse_ID()); + // + if (order == null + || order.getC_BPartner_ID() != replenish.getC_BPartner_ID() + || order.getM_Warehouse_ID() != replenish.getM_Warehouse_ID()) + { + order = new MOrder(getCtx(), 0, get_TrxName()); + order.setIsSOTrx(false); + order.setC_DocTypeTarget_ID(p_C_DocType_ID); + MBPartner bp = new MBPartner(getCtx(), replenish.getC_BPartner_ID(), get_TrxName()); + order.setBPartner(bp); + order.setSalesRep_ID(getAD_User_ID()); + order.setDescription(Msg.getMsg(getCtx(), "Replenishment")); + // Set Org/WH + order.setAD_Org_ID(wh.getAD_Org_ID()); + order.setM_Warehouse_ID(wh.getM_Warehouse_ID()); + if (!order.save()) + return; + log.fine(order.toString()); + noOrders++; + info += " - " + order.getDocumentNo(); + } + MOrderLine line = new MOrderLine (order); + line.setM_Product_ID(replenish.getM_Product_ID()); + line.setQty(replenish.getQtyToOrder()); + line.setPrice(); + line.save(); + } + m_info = "#" + noOrders + info; + log.info(m_info); + } // createPO + + /** + * Create Requisition + */ + private void createRequisition() + { + int noReqs = 0; + String info = ""; + // + MRequisition requisition = null; + MWarehouse wh = null; + X_T_Replenish[] replenishs = getReplenish("M_WarehouseSource_ID IS NULL"); + for (int i = 0; i < replenishs.length; i++) + { + X_T_Replenish replenish = replenishs[i]; + if (wh == null || wh.getM_Warehouse_ID() != replenish.getM_Warehouse_ID()) + wh = MWarehouse.get(getCtx(), replenish.getM_Warehouse_ID()); + // + if (requisition == null + || requisition.getM_Warehouse_ID() != replenish.getM_Warehouse_ID()) + { + requisition = new MRequisition (getCtx(), 0, get_TrxName()); + requisition.setAD_User_ID (getAD_User_ID()); + requisition.setC_DocType_ID(p_C_DocType_ID); + requisition.setDescription(Msg.getMsg(getCtx(), "Replenishment")); + // Set Org/WH + requisition.setAD_Org_ID(wh.getAD_Org_ID()); + requisition.setM_Warehouse_ID(wh.getM_Warehouse_ID()); + if (!requisition.save()) + return; + log.fine(requisition.toString()); + noReqs++; + info += " - " + requisition.getDocumentNo(); + } + // + MRequisitionLine line = new MRequisitionLine(requisition); + line.setM_Product_ID(replenish.getM_Product_ID()); + line.setC_BPartner_ID(replenish.getC_BPartner_ID()); + line.setQty(replenish.getQtyToOrder()); + line.setPrice(); + line.save(); + } + m_info = "#" + noReqs + info; + log.info(m_info); + } // createRequisition + + /** + * Create Inventory Movements + */ + private void createMovements() + { + int noMoves = 0; + String info = ""; + // + MClient client = null; + MMovement move = null; + int M_Warehouse_ID = 0; + int M_WarehouseSource_ID = 0; + MWarehouse whSource = null; + MWarehouse wh = null; + X_T_Replenish[] replenishs = getReplenish("M_WarehouseSource_ID IS NOT NULL"); + for (int i = 0; i < replenishs.length; i++) + { + X_T_Replenish replenish = replenishs[i]; + if (whSource == null || whSource.getM_WarehouseSource_ID() != replenish.getM_WarehouseSource_ID()) + whSource = MWarehouse.get(getCtx(), replenish.getM_WarehouseSource_ID()); + if (wh == null || wh.getM_Warehouse_ID() != replenish.getM_Warehouse_ID()) + wh = MWarehouse.get(getCtx(), replenish.getM_Warehouse_ID()); + if (client == null || client.getAD_Client_ID() != whSource.getAD_Client_ID()) + client = MClient.get(getCtx(), whSource.getAD_Client_ID()); + // + if (move == null + || M_WarehouseSource_ID != replenish.getM_WarehouseSource_ID() + || M_Warehouse_ID != replenish.getM_Warehouse_ID()) + { + M_WarehouseSource_ID = replenish.getM_WarehouseSource_ID(); + M_Warehouse_ID = replenish.getM_Warehouse_ID(); + + move = new MMovement (getCtx(), 0, get_TrxName()); + move.setC_DocType_ID(p_C_DocType_ID); + move.setDescription(Msg.getMsg(getCtx(), "Replenishment") + + ": " + whSource.getName() + "->" + wh.getName()); + // Set Org + move.setAD_Org_ID(whSource.getAD_Org_ID()); + if (!move.save()) + return; + log.fine(move.toString()); + noMoves++; + info += " - " + move.getDocumentNo(); + } + // To + int M_LocatorTo_ID = wh.getDefaultLocator().getM_Locator_ID(); + // From: Look-up Storage + MProduct product = MProduct.get(getCtx(), replenish.getM_Product_ID()); + MProductCategory pc = MProductCategory.get(getCtx(), product.getM_Product_Category_ID()); + String MMPolicy = pc.getMMPolicy(); + if (MMPolicy == null || MMPolicy.length() == 0) + MMPolicy = client.getMMPolicy(); + // + MStorage[] storages = MStorage.getWarehouse(getCtx(), + whSource.getM_Warehouse_ID(), replenish.getM_Product_ID(), 0, 0, + true, null, + MClient.MMPOLICY_FiFo.equals(MMPolicy), get_TrxName()); + // + BigDecimal target = replenish.getQtyToOrder(); + for (int j = 0; j < storages.length; j++) + { + MStorage storage = storages[j]; + if (storage.getQtyOnHand().signum() <= 0) + continue; + BigDecimal moveQty = target; + if (storage.getQtyOnHand().compareTo(moveQty) < 0) + moveQty = storage.getQtyOnHand(); + // + MMovementLine line = new MMovementLine(move); + line.setM_Product_ID(replenish.getM_Product_ID()); + line.setMovementQty(moveQty); + if (replenish.getQtyToOrder().compareTo(moveQty) != 0) + line.setDescription("Total: " + replenish.getQtyToOrder()); + line.setM_Locator_ID(storage.getM_Locator_ID()); // from + line.setM_AttributeSetInstance_ID(storage.getM_AttributeSetInstance_ID()); + line.setM_LocatorTo_ID(M_LocatorTo_ID); // to + line.setM_AttributeSetInstanceTo_ID(storage.getM_AttributeSetInstance_ID()); + line.save(); + // + target = target.subtract(moveQty); + if (target.signum() == 0) + break; + } + } + if (replenishs.length == 0) + { + m_info = "No Source Warehouse"; + log.warning(m_info); + } + else + { + m_info = "#" + noMoves + info; + log.info(m_info); + } + } // createRequisition + + /** + * Get Replenish Records + * @return replenish + */ + private X_T_Replenish[] getReplenish (String where) + { + String sql = "SELECT * FROM T_Replenish " + + "WHERE AD_PInstance_ID=? AND C_BPartner_ID > 0 "; + if (where != null && where.length() > 0) + sql += " AND " + where; + sql += " ORDER BY M_Warehouse_ID, M_WarehouseSource_ID, C_BPartner_ID"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getAD_PInstance_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new X_T_Replenish (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + X_T_Replenish[] retValue = new X_T_Replenish[list.size ()]; + list.toArray (retValue); + return retValue; + } // getReplenish + +} // Replenish diff --git a/base/src/org/compiere/process/ReplicationLocal.java b/base/src/org/compiere/process/ReplicationLocal.java new file mode 100644 index 0000000000..f4ba0bd8b8 --- /dev/null +++ b/base/src/org/compiere/process/ReplicationLocal.java @@ -0,0 +1,590 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import javax.naming.*; +import javax.sql.*; +import org.compiere.db.*; +import org.compiere.interfaces.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Local (Central) Data Replication. + * Note: requires migration technology + * + * @author Jorg Janke + * @version $Id: ReplicationLocal.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ReplicationLocal extends SvrProcess +{ + /** System Record */ + private MSystem m_system = null; + /** Replication Info */ + private MReplication m_replication = null; + /** Replication Run */ + private MReplicationRun m_replicationRun = null; + /** Test Flag */ + private Boolean m_test = Boolean.FALSE; + /** Replication Flag */ + private boolean m_replicated = true; + /** Remote Server */ + private Server m_serverRemote = null; + private long m_start = System.currentTimeMillis(); + /** Date Run on Remote */ + private Timestamp m_replicationStart = new Timestamp (m_start); + + /** Logger */ + private static CLogger s_log = CLogger.getCLogger(ReplicationLocal.class); + + /** Remote class */ + private static String REMOTE = "org.compiere.process.ReplicationRemote"; + protected static String START = "com.adempiere.client.StartReplication"; + + /** + * Prepare - e.g., get Parameters. + */ + public void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("IsTest")) + m_test = Boolean.valueOf("Y".equals (para[i].getParameter())); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + m_system = MSystem.get (getCtx()); + } // prepare + + /** + * Perrform process. + * @return Message + * @throws Exception if not successful + */ + public String doIt() throws Exception + { + if (m_system == null || !m_system.isValid()) + return ("SystemNotSetupForReplication"); + // + log.info("doIt - Record_ID=" + getRecord_ID() + ", test=" + m_test); + connectRemote(); + // + setupRemote(); + mergeData(); + sendUpdates(); + + // Save Info + log.info("doIt - Replicated=" + m_replicated + " - " + m_replicationStart); + m_replicationRun.setIsReplicated(m_replicated); + double sec = (System.currentTimeMillis() - m_start); + sec /= 1000; + m_replicationRun.setDescription(sec + " s"); + m_replicationRun.save(); + if (m_replicated) + { + m_replication.setDateLastRun (m_replicationStart); + m_replication.save(); + } + // + exit(); + return m_replicated ? "Replicated" : "Replication Error"; + } // doIt + + + /** + * Connect to Remote Server + * @throws java.lang.Exception + */ + private void connectRemote() throws Exception + { + // Replication Info + m_replication = new MReplication (getCtx(), getRecord_ID(), get_TrxName()); + // + String AppsHost = m_replication.getHostAddress(); + int AppsPort = m_replication.getHostPort(); + boolean RMIoverHTTP = m_replication.isRMIoverHTTP(); + log.info (AppsHost + ":" + AppsPort + " - HTTP Tunnel=" + RMIoverHTTP); + InitialContext ic = CConnection.getInitialContext( + CConnection.getInitialEnvironment(AppsHost, AppsPort, RMIoverHTTP)); + if (ic == null) + throw new Exception ("NoInitialContext"); + + try + { + ServerHome serverHome = (ServerHome)ic.lookup (ServerHome.JNDI_NAME); + // log.fine("- ServerHome: " + serverHome); + if (serverHome == null) + throw new Exception ("NoServer"); + m_serverRemote = serverHome.create(); + // log.fine("- Server: " + m_serverRemote); + // log.fine("- Remote Status = " + m_serverRemote.getStatus()); + } + catch (Exception ex) + { + log.log(Level.SEVERE, "connectRemote", ex); + throw new Exception (ex); + } + } // connectRemote + + + /** + * Setup Remote AD_System/AD_Table/AD_Sequence for Remote Management. + * @throws Exception + */ + private void setupRemote() throws Exception + { + log.info("setupRemote"); + // + String sql = "SELECT rt.AD_Table_ID, rt.ReplicationType, t.TableName " + + "FROM AD_ReplicationTable rt" + + " INNER JOIN AD_Table t ON (rt.AD_Table_ID=t.AD_Table_ID) " + + "WHERE rt.IsActive='Y' AND t.IsActive='Y'" + + " AND AD_ReplicationStrategy_ID=? " // #1 + + "ORDER BY t.LoadSeq"; + RowSet rowset = getRowSet(sql, new Object[]{new Integer(m_replication.getAD_ReplicationStrategy_ID())}); + if (rowset == null) + throw new Exception("setupRemote - No RowSet Data"); + + // Data Info + RemoteSetupVO data = new RemoteSetupVO(); + data.Test = m_test; + data.ReplicationTable = rowset; // RowSet + data.IDRangeStart = m_replication.getIDRangeStart(); + data.IDRangeEnd = m_replication.getIDRangeEnd(); + data.AD_Client_ID = m_replication.getRemote_Client_ID(); + data.AD_Org_ID = m_replication.getRemote_Org_ID(); + data.Prefix = m_replication.getPrefix(); + data.Suffix = m_replication.getSuffix(); + // Process Info + ProcessInfo pi = new ProcessInfo(data.toString(), 0); + pi.setClassName (REMOTE); + pi.setSerializableObject(data); + Object result = doIt(START, "init", new Object[]{m_system}); + if (result == null || !Boolean.TRUE.equals(result)) + throw new Exception("setupRemote - Init Error - " + result); + // send it + pi = m_serverRemote.process (new Properties (), pi); + ProcessInfoLog[] logs = pi.getLogs(); + Timestamp dateRun = null; + if (logs != null && logs.length > 0) + dateRun = logs[0].getP_Date(); // User Remote Timestamp! + // + log.info ("setupRemote - " + pi + " - Remote Timestamp = " + dateRun); + if (dateRun != null) + m_replicationStart = dateRun; + m_replicationRun = new MReplicationRun (getCtx(), m_replication.getAD_Replication_ID(), m_replicationStart, get_TrxName()); + m_replicationRun.save(); + } // setupRemote + + /*************************************************************************/ + + /** + * Receive new Data from Remote. + * @throws Exception + */ + private void mergeData() throws Exception + { + log.info("mergeData"); + // + String sql = "SELECT rt.AD_Table_ID, rt.ReplicationType, t.TableName, rt.AD_ReplicationTable_ID " + + "FROM AD_ReplicationTable rt" + + " INNER JOIN AD_Table t ON (rt.AD_Table_ID=t.AD_Table_ID) " + + "WHERE rt.IsActive='Y' AND t.IsActive='Y'" + + " AND AD_ReplicationStrategy_ID=?" // #1 + + " AND rt.ReplicationType='M' " // Merge + + "ORDER BY t.LoadSeq"; + RowSet rowset = getRowSet(sql, new Object[]{new Integer(m_replication.getAD_ReplicationStrategy_ID())}); + try + { + while (rowset.next()) + mergeDataTable (rowset.getInt(1), rowset.getString(3), rowset.getInt(4)); + rowset.close(); + rowset = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, "mergeData", ex); + m_replicated = false; + } + } // mergeData + + /** + * Receive New Data from Remote (and send local updates) + * @param AD_Table_ID table id + * @param TableName table name + * @param AD_ReplicationTable_ID id + * @return true if success + * @throws java.lang.Exception + */ + private boolean mergeDataTable (int AD_Table_ID, String TableName, int AD_ReplicationTable_ID) throws Exception + { + RemoteMergeDataVO data = new RemoteMergeDataVO(); + data.Test = m_test; + data.TableName = TableName; + // Create SQL + StringBuffer sql = new StringBuffer("SELECT * FROM ") + .append(TableName) + .append(" WHERE AD_Client_ID=").append(m_replication.getRemote_Client_ID()); + if (m_replication.getRemote_Org_ID() != 0) + sql.append(" AND AD_Org_ID IN (0,").append(m_replication.getRemote_Org_ID()).append(")"); + if (m_replication.getDateLastRun() != null) + sql.append(" AND Updated >= ").append(DB.TO_DATE(m_replication.getDateLastRun(), false)); + sql.append(" ORDER BY "); + data.KeyColumns = getKeyColumns(AD_Table_ID); + if (data.KeyColumns == null || data.KeyColumns.length == 0) + { + log.log(Level.SEVERE, "mergeDataTable - No KeyColumns for " + TableName); + m_replicated = false; + return false; + } + for (int i = 0; i < data.KeyColumns.length; i++) + { + if (i > 0) + sql.append(","); + sql.append(data.KeyColumns[i]); + } + data.Sql = sql.toString(); + // New Central Data + data.CentralData = getRowSet(data.Sql, null); + if (data.CentralData == null) + { + log.fine("mergeDataTable - CentralData is Null - " + TableName); + m_replicated = false; + return false; + } + + // Process Info + ProcessInfo pi = new ProcessInfo("MergeData", 0); + pi.setClassName (REMOTE); + pi.setSerializableObject(data); + // send it + pi = m_serverRemote.process (new Properties (), pi); + ProcessInfoLog[] logs = pi.getLogs(); + String msg = "< "; + if (logs != null && logs.length > 0) + msg += logs[0].getP_Msg(); // Remote Message + log.info("mergeDataTable - " + pi); + // + MReplicationLog rLog = new MReplicationLog (getCtx(), m_replicationRun.getAD_Replication_Run_ID(), AD_ReplicationTable_ID, msg, get_TrxName()); + if (pi.isError()) + { + log.severe ("mergeDataTable Error - " + pi); + m_replicated = false; + rLog.setIsReplicated(false); + } + else // import data fom remote + { + RowSet sourceRS = (RowSet)pi.getSerializableObject(); + RowSet targetRS = getRowSet(data.Sql, null); + Object result = doIt (START, "sync", new Object[] // Merge + {data.TableName, data.KeyColumns, sourceRS, targetRS, m_test, Boolean.TRUE}); + boolean replicated = isReplicated(result); + if (replicated) + log.fine("mergeDataTable -> " + TableName + " - " + result); + else + { + m_replicated = false; + log.severe ("mergeDataTable -> " + TableName + " - " + result); + } + rLog.setIsReplicated(replicated); + if (result != null) + rLog.setP_Msg("< " + result.toString()); + sourceRS.close(); + sourceRS = null; + targetRS.close(); + targetRS = null; + } + rLog.save(); + return !pi.isError(); + } // mergeDataTable + + /** + * Get Key Columns (PK or FK) of Table + * @param AD_Table_ID id + * @return Key Columns + */ + public String[] getKeyColumns (int AD_Table_ID) + { + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + // Get Keys + String sql = "SELECT ColumnName FROM AD_Column " + + "WHERE AD_Table_ID=?" + + " AND IsKey='Y'"; + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, AD_Table_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(rs.getString(1)); + rs.close(); + + // no keys - search for parents + if (list.size() == 0) + { + sql = "SELECT ColumnName FROM AD_Column " + + "WHERE AD_Table_ID=?" + + " AND IsParent='Y'"; + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, AD_Table_ID); + rs = pstmt.executeQuery(); + while (rs.next()) + list.add(rs.getString(1)); + rs.close(); + } + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getKeyColumns", e); + } + try + { + if (pstmt != null) + pstmt.close(); + } + catch (Exception e) + { + } + + // Convert to Array + String[] retValue = new String[list.size()]; + list.toArray(retValue); + return retValue; + } // getKeyColumns + + /*************************************************************************/ + + /** + * Send Updates to Remote (i.e. r/o on remote) + * @throws Exception + */ + private void sendUpdates() throws Exception + { + log.info("sendUpdates"); + // + String sql = "SELECT rt.AD_Table_ID, rt.ReplicationType, t.TableName, rt.AD_ReplicationTable_ID " + + "FROM AD_ReplicationTable rt" + + " INNER JOIN AD_Table t ON (rt.AD_Table_ID=t.AD_Table_ID) " + + "WHERE rt.IsActive='Y' AND t.IsActive='Y'" + + " AND AD_ReplicationStrategy_ID=?" // #1 + + " AND rt.ReplicationType='R' " // Reference + + "ORDER BY t.LoadSeq"; + RowSet rowset = getRowSet(sql, new Object[]{new Integer(m_replication.getAD_ReplicationStrategy_ID())}); + try + { + while (rowset.next()) + sendUpdatesTable (rowset.getInt(1), rowset.getString(3), rowset.getInt(4)); + rowset.close(); + } + catch (SQLException ex) + { + log.log(Level.SEVERE, "sendUpdates", ex); + m_replicated = false; + } + } // sendUpdates + + /** + * Send UPdates to Remote + * @param AD_Table_ID table id + * @param TableName table + * @param AD_ReplicationTable_ID id + * @return true if success + * @throws Exception + */ + private boolean sendUpdatesTable (int AD_Table_ID, String TableName, int AD_ReplicationTable_ID) throws Exception + { + RemoteUpdateVO data = new RemoteUpdateVO(); + data.Test = m_test; + data.TableName = TableName; + // Create SQL + StringBuffer sql = new StringBuffer ("SELECT * FROM ") + .append(TableName) + .append(" WHERE AD_Client_ID=").append(m_replication.getRemote_Client_ID()); + if (m_replication.getRemote_Org_ID() != 0) + sql.append(" AND AD_Org_ID IN (0,").append(m_replication.getRemote_Org_ID()).append(")"); + if (m_replication.getDateLastRun() != null) + sql.append(" AND Updated >= ").append(DB.TO_DATE(m_replication.getDateLastRun(), false)); + sql.append(" ORDER BY "); + data.KeyColumns = getKeyColumns(AD_Table_ID); + if (data.KeyColumns == null || data.KeyColumns.length == 0) + { + log.log(Level.SEVERE, "sendUpdatesTable - No KeyColumns for " + TableName); + m_replicated = false; + return false; + } + for (int i = 0; i < data.KeyColumns.length; i++) + { + if (i > 0) + sql.append(","); + sql.append(data.KeyColumns[i]); + } + data.Sql = sql.toString(); + // New Data + data.CentralData = getRowSet(data.Sql, null); + if (data.CentralData == null) + { + log.fine("sendUpdatesTable - Null - " + TableName); + m_replicated = false; + return false; + } + int rows = 0; + try + { + if (data.CentralData.last()) + rows = data.CentralData.getRow(); + data.CentralData.beforeFirst(); // rewind + } + catch (SQLException ex) + { + log.fine("RowCheck " + ex); + m_replicated = false; + return false; + } + if (rows == 0) + { + log.fine("No Rows - " + TableName); + return true; + } + else + log.fine(TableName + " #" + rows); + + // Process Info + ProcessInfo pi = new ProcessInfo("SendUpdates", 0); + pi.setClassName (REMOTE); + pi.setSerializableObject(data); + // send it + pi = m_serverRemote.process (new Properties (), pi); + log.info("sendUpdatesTable - " + pi); + ProcessInfoLog[] logs = pi.getLogs(); + String msg = "> "; + if (logs != null && logs.length > 0) + msg += logs[0].getP_Msg(); // Remote Message + // + MReplicationLog rLog = new MReplicationLog (getCtx(), m_replicationRun.getAD_Replication_Run_ID(), AD_ReplicationTable_ID, msg, get_TrxName()); + if (pi.isError()) + m_replicated = false; + rLog.setIsReplicated(!pi.isError()); + rLog.save(); + return !pi.isError(); + } // sendUpdatesTable + + /** + * Clean up resources (connections) + */ + private void exit() + { + log.info ("exit"); + Object result = doIt(START, "exit", null); + ProcessInfo pi = new ProcessInfo("Exit", 0); + pi.setClassName (REMOTE); + pi.setSerializableObject(m_replicationStart); + // send it + try + { + m_serverRemote.process (new Properties (), pi); + } + catch (Exception ex) + { + } + } // exit + + + /************************************************************************** + * Get RowSet of Local Connection + * @param sql sql + * @param args optional argument array - supported: Integer, Timestamp, BigDecimal - rest is concerted to String + * @return row set + */ + public static RowSet getRowSet (String sql, Object[] args) + { + // shared connection + Connection conn = DB.getConnectionRO(); + PreparedStatement pstmt = null; + RowSet rowSet = null; + // + try + { + pstmt = conn.prepareStatement(sql, + ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + // Set Parameters + if (args != null) + { + for (int i = 0; i < args.length; i++) + { + if (args[i] == null) + s_log.log(Level.SEVERE, "NULL Argument " + i); + else if (args[i] instanceof Integer) + pstmt.setInt(i+1, ((Integer)args[i]).intValue()); + else if (args[i] instanceof Timestamp) + pstmt.setTimestamp(i+1, (Timestamp)args[i]); + else if (args[i] instanceof BigDecimal) + pstmt.setBigDecimal(i+1, (BigDecimal)args[i]); + else + pstmt.setString(i+1, args[i].toString()); + } + } + // + ResultSet rs = pstmt.executeQuery(); + rowSet = CCachedRowSet.getRowSet(rs); + pstmt.close(); + pstmt = null; + } + catch (Exception ex) + { + s_log.log(Level.SEVERE, sql, ex); + throw new RuntimeException (ex); + } + // Close Cursor + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "close pstmt", e); + } + + return rowSet; + } // getRowSet + + /** + * Is data successful replicated + * @param result sync return value + * @return true if replicated + */ + public static boolean isReplicated (Object result) + { + boolean replicated = result != null && !Boolean.FALSE.equals(result); + if (replicated) + replicated = result.toString().endsWith("Errors=0"); + return replicated; + } // isReplicated + +} // ReplicationLocal diff --git a/base/src/org/compiere/process/ReplicationRemote.java b/base/src/org/compiere/process/ReplicationRemote.java new file mode 100644 index 0000000000..09edce88f7 --- /dev/null +++ b/base/src/org/compiere/process/ReplicationRemote.java @@ -0,0 +1,313 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import javax.sql.*; +import java.math.*; +import java.io.*; +import java.sql.*; + +import java.util.logging.*; +import org.compiere.util.*; +import org.compiere.model.*; + +/** + * Remote Data Replication. + * Note: requires migration technology + * + * @author Jorg Janke + * @version $Id: ReplicationRemote.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ReplicationRemote extends SvrProcess +{ + /** System Record */ + private MSystem m_system = null; + /** Local Timestamp */ + private Timestamp m_startDate = new Timestamp(System.currentTimeMillis()); + + /** + * Prepare - e.g., get Parameters. + */ + public void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + m_system = MSystem.get (getCtx()); + } // prepare + + /** + * Perrform process. + * @return Message + * @throws Exception if not successful + */ + public String doIt() throws Exception + { + ProcessInfo pi = getProcessInfo(); + log.info("doIt - " + pi.getTitle()); + if (pi.getSerializableObject() instanceof RemoteSetupVO) + return setupRemote(); + else if (pi.getSerializableObject() instanceof RemoteMergeDataVO) + return mergeDataWithCentral(); + else if (pi.getSerializableObject() instanceof RemoteUpdateVO) + return receiveUpdateFromCentral(); + else if (pi.getSerializableObject() instanceof Timestamp) + return exit(); + else + throw new Exception ("ReplicationRemote - unknown VO - " + pi.getSerializableObject()); + } // doIt + + /************************************************************************* + + /** + * Setup Remote AD_System/AD_Table/AD_Sequence for Remote Management. + * @return "" or error message + * @throws Exception + */ + private String setupRemote() throws Exception + { + ProcessInfo pi = getProcessInfo(); + RemoteSetupVO data = (RemoteSetupVO)pi.getSerializableObject(); + log.info("setupRemote Start (" + pi + ") " + data); + + RowSet rs = data.ReplicationTable; + try + { + // Update AD_System **** + if (data.IDRangeStart == null || data.IDRangeEnd == null) + throw new Exception ("setupRemote - IDRange cannot be null"); + if (!data.Test.booleanValue()) + { + setupRemoteAD_System (data.IDRangeStart, data.IDRangeEnd); + // Update AD_Sequence **** + setupRemoteAD_Sequence (data.IDRangeStart); + // Update DocNo Prefix/Suffix **** + setupRemoteC_DocType (data.AD_Client_ID, data.Prefix, data.Suffix); + } + // Update Tables **** + while (rs.next ()) + { + int AD_Table_ID = rs.getInt(1); + String ReplicationType = rs.getString(2); + String TableName = rs.getString(3); + log.fine("setupRemote - " + TableName + " - " + ReplicationType); + if (!data.Test.booleanValue()) + setupRemoteAD_Table(TableName, ReplicationType); + } + pi.setSummary("OK - Test=" + data.Test, false); + } + catch (Exception ex) + { + log.log(Level.SEVERE, "setupRemote", ex); + pi.setSummary(ex.toString(), true); + } + Object result = doIt(ReplicationLocal.START, "init", new Object[]{m_system}); + if (result == null || !Boolean.TRUE.equals(result)) + throw new Exception("setupRemote - Init Error - " + result); + pi.setSerializableObject(null); + pi.addLog(0,0, m_startDate, null, null); + log.info("setupRemote End (" + pi + ") " + data); + return "Remote SetupRemote OK"; + } // setupRemote + + /** + * Update Replication Type and ID Range of AD_System + * @param IDRangeStart start + * @param IDRangeEnd end + * @throws Exception if sql error + */ + private void setupRemoteAD_System (BigDecimal IDRangeStart, BigDecimal IDRangeEnd) throws Exception + { + m_system.setIDRangeStart(IDRangeStart); + m_system.setIDRangeEnd(IDRangeEnd); + m_system.setReplicationType(MSystem.REPLICATIONTYPE_Merge); + m_system.save(); + } // setupRemoteAD_System + + /** + * Update StartNo/CurrentNext/CurrentNextSys in AD_Sequence + * @param IDRangeStart start + * @throws Exception if sql error + */ + private void setupRemoteAD_Sequence (BigDecimal IDRangeStart) throws Exception + { + String sql = "UPDATE AD_Sequence SET StartNo = " + IDRangeStart + + " WHERE IsTableID='Y' AND StartNo < " + IDRangeStart; + int no = DB.executeUpdate(sql, get_TrxName()); + if (no == -1) + throw new Exception("setupRemoteAD_Sequence_Start"); + // + sql = "UPDATE AD_Sequence SET CurrentNext = " + IDRangeStart + + " WHERE IsTableID='Y' AND CurrentNext < " + IDRangeStart; + no = DB.executeUpdate(sql, get_TrxName()); + if (no == -1) + throw new Exception("setupRemoteAD_Sequence_Next"); + // + sql = "UPDATE AD_Sequence SET CurrentNextSys = -1" + + " WHERE IsTableID='Y' AND CurrentNextSys <> -1"; + no = DB.executeUpdate(sql, get_TrxName()); + if (no == -1) + throw new Exception("setupRemoteAD_Sequence_Sys"); + } // setupRemoteAD_Sequence + + /** + * Update Document Prefix/Suffix + * @param AD_Client_ID client + * @param Prefix prefix + * @param Suffix suffix + * @throws Exception if sql error + */ + private void setupRemoteC_DocType (int AD_Client_ID, String Prefix, String Suffix) throws Exception + { + if (Prefix == null) + Prefix = ""; + if (Suffix == null) + Suffix = ""; + // DocNoSequence_ID + String sql = "UPDATE AD_Sequence SET Prefix=" + DB.TO_STRING(Prefix) + ", Suffix=" + DB.TO_STRING(Suffix) + + " WHERE AD_Sequence_ID IN (SELECT DocNoSequence_ID FROM C_DocType" + + " WHERE AD_Client_ID=" + AD_Client_ID + " AND DocNoSequence_ID IS NOT NULL)"; + int no = DB.executeUpdate(sql, get_TrxName()); + if (no == -1) + throw new Exception("setupRemoteC_DocType_DocNo"); + // BatchNoSequence_ID + sql = "UPDATE AD_Sequence SET Prefix=" + DB.TO_STRING(Prefix) + ", Suffix=" + DB.TO_STRING(Suffix) + + " WHERE AD_Sequence_ID IN (SELECT BatchNoSequence_ID FROM C_DocType" + + " WHERE AD_Client_ID=" + AD_Client_ID + " AND BatchNoSequence_ID IS NOT NULL)"; + no = DB.executeUpdate(sql, get_TrxName()); + if (no == -1) + throw new Exception("setupRemoteC_DocType_Batch"); + } // setupRemoteC_DocType + + /** + * Set ReplicationType of AD_Table + * @param TableName table name + * @param ReplicationType replication type + * @throws Exception if sql error + */ + private void setupRemoteAD_Table(String TableName, String ReplicationType) throws Exception + { + String sql = "UPDATE AD_Table SET ReplicationType = '" + ReplicationType + + "' WHERE TableName='" + TableName + "' AND ReplicationType <> '" + ReplicationType + "'"; + int no = DB.executeUpdate(sql, get_TrxName()); + if (no == -1) + throw new Exception("setupRemoteAD_Table"); + } // setupRemoteAD_Table + + /************************************************************************* + + /** + * Send new Data from Remote. + * Transcation Data changed + * @return info + * @throws Exception + */ + private String mergeDataWithCentral() throws Exception + { + ProcessInfo pi = getProcessInfo(); + RemoteMergeDataVO data = (RemoteMergeDataVO)pi.getSerializableObject(); + log.info("mergeDataWithCentral Start (" + pi + ") " + data); + // Merge Data from Central + RowSet sourceRS = data.CentralData; + if (sourceRS == null) + log.log(Level.SEVERE, "mergeDataWithCentral - No Data - " + data); + else if (!data.Test.booleanValue()) + { + RowSet targetRS = ReplicationLocal.getRowSet(data.Sql, null); + Object result = doIt (ReplicationLocal.START, "sync", new Object[] // Merge + {data.TableName, data.KeyColumns, sourceRS, targetRS, data.Test, Boolean.TRUE}); + log.fine("receiveUpdateFromCentral - " + data.TableName + " - " + result); + pi.setSerializableObject(null); + boolean replicated = ReplicationLocal.isReplicated(result); + if (!replicated) + pi.setError(true); + if (result != null) + pi.addLog(0,null,null, result.toString()); + if (Boolean.FALSE.equals(result)) + throw new Exception ("receiveUpdateFromCentral - " + data.TableName + " - " + result); + } + + // Local Remote Data + RowSet rowset = ReplicationLocal.getRowSet(data.Sql, null); + // Result + pi.setSerializableObject((Serializable)rowset); + log.info("mergeDataWithCentral End (" + pi + ") " + data); + return "Remote MergeDataWithCentral - " + data.TableName; + } // sendNewDataToCentral + + /************************************************************************* + + /** + * Receive Update from Central + * @return info + * @throws Exception + */ + private String receiveUpdateFromCentral() throws Exception + { + ProcessInfo pi = getProcessInfo(); + RemoteUpdateVO data = (RemoteUpdateVO)pi.getSerializableObject(); + log.info("receiveUpdateFromCentral Start (" + pi + ") - " + data); + // + RowSet sourceRS = data.CentralData; + if (sourceRS == null) + { + log.log(Level.SEVERE, "receiveUpdateFromCentral - No Data - " + data); + pi.setSummary("NoData", true); + } + else if (!data.Test.booleanValue()) + { + RowSet targetRS = ReplicationLocal.getRowSet(data.Sql, null); + Object result = doIt (ReplicationLocal.START, "sync", new Object[] // Sync + {data.TableName, data.KeyColumns, sourceRS, targetRS, data.Test, Boolean.FALSE}); + log.fine("receiveUpdateFromCentral - " + data.TableName + " - " + result); + pi.setSerializableObject(null); + boolean replicated = ReplicationLocal.isReplicated(result); + if (!replicated) + pi.setError(true); + if (result != null) + pi.addLog(0,null,null, result.toString()); + if (Boolean.FALSE.equals(result)) + throw new Exception ("receiveUpdateFromCentral - " + data.TableName + " - " + result); + } + // + pi.setSerializableObject(null); + log.info("receiveUpdateFromCentral End (" + pi + ") - " + data); + return "Remote Receive Update from Central OK"; + } // receiveUpdateFromCentral + + /*************************************************************************/ + + /** + * Clean up resources (connections) + * @return exit + * @throws Exception + */ + private String exit() throws Exception + { + log.info ("exit"); + ProcessInfo pi = getProcessInfo(); + Object result = doIt(ReplicationLocal.START, "exit", null); + return "exit"; + } // exit + +} // ReplicationRemote diff --git a/base/src/org/compiere/process/ReportColumnSet_Copy.java b/base/src/org/compiere/process/ReportColumnSet_Copy.java new file mode 100644 index 0000000000..3adbc23597 --- /dev/null +++ b/base/src/org/compiere/process/ReportColumnSet_Copy.java @@ -0,0 +1,84 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.util.logging.*; +import org.compiere.report.*; + +/** + * Copy Column Set at the end of the Column Set + * + * @author Jorg Janke + * @version $Id: ReportColumnSet_Copy.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class ReportColumnSet_Copy extends SvrProcess +{ + /** + * Constructor + */ + public ReportColumnSet_Copy() + { + super(); + } // ReportColumnSet_Copy + + /** Source Line Set */ + private int m_PA_ReportColumnSet_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("PA_ReportColumnSet_ID")) + m_PA_ReportColumnSet_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message + * @throws Exception + */ + protected String doIt() throws Exception + { + int to_ID = super.getRecord_ID(); + log.info("From PA_ReportColumnSet_ID=" + m_PA_ReportColumnSet_ID + ", To=" + to_ID); + if (to_ID < 1) + throw new Exception(MSG_SaveErrorRowNotFound); + // + MReportColumnSet to = new MReportColumnSet(getCtx(), to_ID, get_TrxName()); + MReportColumnSet rcSet = new MReportColumnSet(getCtx(), m_PA_ReportColumnSet_ID, get_TrxName()); + MReportColumn[] rcs = rcSet.getColumns(); + for (int i = 0; i < rcs.length; i++) + { + MReportColumn rc = MReportColumn.copy (getCtx(), to.getAD_Client_ID(), to.getAD_Org_ID(), to_ID, rcs[i], get_TrxName()); + rc.save(); + } + // Oper 1/2 were set to Null ! + return "@Copied@=" + rcs.length; + } // doIt + +} // ReportColumnSet_Copy diff --git a/base/src/org/compiere/process/ReportLineSet_Copy.java b/base/src/org/compiere/process/ReportLineSet_Copy.java new file mode 100644 index 0000000000..0510fd8444 --- /dev/null +++ b/base/src/org/compiere/process/ReportLineSet_Copy.java @@ -0,0 +1,93 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.util.logging.*; +import org.compiere.report.*; + +/** + * Copy Line Set at the end of the Line Set + * + * @author Jorg Janke + * @version $Id: ReportLineSet_Copy.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class ReportLineSet_Copy extends SvrProcess +{ + /** + * Constructor + */ + public ReportLineSet_Copy() + { + super(); + } // ReportLineSet_Copy + + /** Source Line Set */ + private int m_PA_ReportLineSet_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("PA_ReportLineSet_ID")) + m_PA_ReportLineSet_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message + * @throws Exception + */ + protected String doIt() throws Exception + { + int to_ID = super.getRecord_ID(); + log.info("From PA_ReportLineSet_ID=" + m_PA_ReportLineSet_ID + ", To=" + to_ID); + if (to_ID < 1) + throw new Exception(MSG_SaveErrorRowNotFound); + // + MReportLineSet to = new MReportLineSet(getCtx(), to_ID, get_TrxName()); + MReportLineSet rlSet = new MReportLineSet(getCtx(), m_PA_ReportLineSet_ID, get_TrxName()); + MReportLine[] rls = rlSet.getLiness(); + for (int i = 0; i < rls.length; i++) + { + MReportLine rl = MReportLine.copy (getCtx(), to.getAD_Client_ID(), to.getAD_Org_ID(), to_ID, rls[i], get_TrxName()); + rl.save(); + MReportSource[] rss = rls[i].getSources(); + if (rss != null) + { + for (int ii = 0; ii < rss.length; ii++) + { + MReportSource rs = MReportSource.copy (getCtx(), to.getAD_Client_ID(), to.getAD_Org_ID(), rl.get_ID(), rss[ii], get_TrxName()); + rs.save(); + } + } + // Oper 1/2 were set to Null ! + } + return "@Copied@=" + rls.length; + } // doIt + +} // ReportLineSet_Copy diff --git a/base/src/org/compiere/process/RequestInvoice.java b/base/src/org/compiere/process/RequestInvoice.java new file mode 100644 index 0000000000..a35ac2a305 --- /dev/null +++ b/base/src/org/compiere/process/RequestInvoice.java @@ -0,0 +1,224 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.math.*; +import java.util.logging.*; + +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Create Invoices for Requests + * + * + * @author Jorg Janke + * @version $Id: RequestInvoice.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class RequestInvoice extends SvrProcess +{ + /** Request Type */ + private int p_R_RequestType_ID = 0; + /** Request Group (opt) */ + private int p_R_Group_ID = 0; + /** Request Categpry (opt) */ + private int p_R_Category_ID = 0; + /** Business Partner (opt) */ + private int p_C_BPartner_ID = 0; + /** Default product */ + private int p_M_Product_ID = 0; + + /** The invoice */ + private MInvoice m_invoice = null; + /** Line Count */ + private int m_linecount = 0; + + /** + * Prepare + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("R_RequestType_ID")) + p_R_RequestType_ID = para[i].getParameterAsInt(); + else if (name.equals("R_Group_ID")) + p_R_Group_ID = para[i].getParameterAsInt(); + else if (name.equals("R_Category_ID")) + p_R_Category_ID = para[i].getParameterAsInt(); + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = para[i].getParameterAsInt(); + else if (name.equals("M_Product_ID")) + p_M_Product_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("R_RequestType_ID=" + p_R_RequestType_ID + ", R_Group_ID=" + p_R_Group_ID + + ", R_Category_ID=" + p_R_Category_ID + ", C_BPartner_ID=" + p_C_BPartner_ID + + ", p_M_Product_ID=" + p_M_Product_ID); + + MRequestType type = MRequestType.get (getCtx(), p_R_RequestType_ID); + if (type.get_ID() == 0) + throw new AdempiereSystemError("@R_RequestType_ID@ @NotFound@ " + p_R_RequestType_ID); + if (!type.isInvoiced()) + throw new AdempiereSystemError("@R_RequestType_ID@ <> @IsInvoiced@"); + + String sql = "SELECT * FROM R_Request r" + + " INNER JOIN R_Status s ON (r.R_Status_ID=s.R_Status_ID) " + + "WHERE s.IsClosed='Y'" + + " AND r.R_RequestType_ID=?"; + if (p_R_Group_ID != 0) + sql += " AND r.R_Group_ID=?"; + if (p_R_Category_ID != 0) + sql += " AND r.R_Category_ID=?"; + if (p_C_BPartner_ID != 0) + sql += " AND r.C_BPartner_ID=?"; + sql += " AND r.IsInvoiced='Y' " + + "ORDER BY C_BPartner_ID"; + + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + int index = 1; + pstmt.setInt (index++, p_R_RequestType_ID); + if (p_R_Group_ID != 0) + pstmt.setInt (index++, p_R_Group_ID); + if (p_R_Category_ID != 0) + pstmt.setInt (index++, p_R_Category_ID); + if (p_C_BPartner_ID != 0) + pstmt.setInt (index++, p_C_BPartner_ID); + ResultSet rs = pstmt.executeQuery (); + int oldC_BPartner_ID = 0; + while (rs.next ()) + { + MRequest request = new MRequest (getCtx(), rs, get_TrxName()); + if (!request.isInvoiced()) + continue; + if (oldC_BPartner_ID != request.getC_BPartner_ID()) + invoiceDone(); + if (m_invoice == null) + { + invoiceNew(request); + oldC_BPartner_ID = request.getC_BPartner_ID(); + } + invoiceLine(request); + } + invoiceDone(); + // + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // R_Category_ID + return null; + } // doIt + + /** + * Done with Invoice + */ + private void invoiceDone() + { + // Close Old + if (m_invoice != null) + { + if (m_linecount == 0) + m_invoice.delete(false); + else + { + m_invoice.processIt(MInvoice.ACTION_Prepare); + m_invoice.save(); + addLog(0, null, m_invoice.getGrandTotal(), m_invoice.getDocumentNo()); + } + } + m_invoice = null; + } // invoiceDone + + /** + * New Invoice + * @param request request + */ + private void invoiceNew (MRequest request) + { + m_invoice = new MInvoice (getCtx(), 0, get_TrxName()); + m_invoice.setIsSOTrx(true); + + MBPartner partner = new MBPartner (getCtx(), request.getC_BPartner_ID(), null); + m_invoice.setBPartner(partner); + + m_invoice.save(); + m_linecount = 0; + } // invoiceNew + + /** + * Invoice Line + * @param request request + */ + private void invoiceLine (MRequest request) + { + MRequestUpdate[] updates = request.getUpdates(null); + for (int i = 0; i < updates.length; i++) + { + BigDecimal qty = updates[i].getQtyInvoiced(); + if (qty == null || qty.signum() == 0) + continue; + + MInvoiceLine il = new MInvoiceLine(m_invoice); + m_linecount++; + il.setLine(m_linecount*10); + // + il.setQty(qty); + // Product + int M_Product_ID = updates[i].getM_ProductSpent_ID(); + if (M_Product_ID == 0) + M_Product_ID = p_M_Product_ID; + il.setM_Product_ID(M_Product_ID); + // + il.setPrice(); + il.save(); + } + } // invoiceLine + +} // RequestInvoice diff --git a/base/src/org/compiere/process/RequestReOpen.java b/base/src/org/compiere/process/RequestReOpen.java new file mode 100644 index 0000000000..9f72fcedc0 --- /dev/null +++ b/base/src/org/compiere/process/RequestReOpen.java @@ -0,0 +1,72 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Re-Open Request + * + * @author Jorg Janke + * @version $Id: RequestReOpen.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class RequestReOpen extends SvrProcess +{ + /** Request */ + private int p_R_Request_ID = 0; + + /** + * Prepare + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("R_Request_ID")) + p_R_Request_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Process It + * @return message + * @throws Exception + */ + protected String doIt () throws Exception + { + MRequest request = new MRequest (getCtx(), p_R_Request_ID, get_TrxName()); + log.info(request.toString()); + if (request.get_ID() == 0) + throw new AdempiereUserError("@NotFound@ @R_Request_ID@ " + p_R_Request_ID); + + request.setR_Status_ID(); // set default status + request.setProcessed(false); + if (request.save() && !request.isProcessed()) + return "@OK@"; + return "@Error@"; + } // doUt + +} // RequestReOpen diff --git a/base/src/org/compiere/process/RequisitionPOCreate.java b/base/src/org/compiere/process/RequisitionPOCreate.java new file mode 100644 index 0000000000..019a820707 --- /dev/null +++ b/base/src/org/compiere/process/RequisitionPOCreate.java @@ -0,0 +1,393 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.logging.*; + +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Create PO from Requisition + * + * + * @author Jorg Janke + * @version $Id: RequisitionPOCreate.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class RequisitionPOCreate extends SvrProcess +{ + /** Org */ + private int p_AD_Org_ID = 0; + /** Warehouse */ + private int p_M_Warehouse_ID = 0; + /** Doc Date From */ + private Timestamp p_DateDoc_From; + /** Doc Date To */ + private Timestamp p_DateDoc_To; + /** Doc Date From */ + private Timestamp p_DateRequired_From; + /** Doc Date To */ + private Timestamp p_DateRequired_To; + /** Priority */ + private String p_PriorityRule = null; + /** User */ + private int p_AD_User_ID = 0; + /** Product */ + private int p_M_Product_ID = 0; + /** Requisition */ + private int p_M_Requisition_ID = 0; + + /** Consolidate */ + private boolean p_ConsolidateDocument = false; + + /** Order */ + private MOrder m_order = null; + /** Order Line */ + private MOrderLine m_orderLine = null; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Org_ID")) + p_AD_Org_ID = para[i].getParameterAsInt(); + else if (name.equals("M_Warehouse_ID")) + p_M_Warehouse_ID = para[i].getParameterAsInt(); + else if (name.equals("DateDoc")) + { + p_DateDoc_From = (Timestamp)para[i].getParameter(); + p_DateDoc_To = (Timestamp)para[i].getParameter_To(); + } + else if (name.equals("DateRequired")) + { + p_DateRequired_From = (Timestamp)para[i].getParameter(); + p_DateRequired_To = (Timestamp)para[i].getParameter_To(); + } + else if (name.equals("PriorityRule")) + p_PriorityRule = (String)para[i].getParameter(); + else if (name.equals("AD_User_ID")) + p_AD_User_ID = para[i].getParameterAsInt(); + else if (name.equals("M_Product_ID")) + p_M_Product_ID = para[i].getParameterAsInt(); + else if (name.equals("M_Requisition_ID")) + p_M_Requisition_ID = para[i].getParameterAsInt(); + else if (name.equals("ConsolidateDocument")) + p_ConsolidateDocument = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt() throws Exception + { + // Specific + if (p_M_Requisition_ID != 0) + { + log.info("M_Requisition_ID=" + p_M_Requisition_ID); + MRequisition req = new MRequisition(getCtx(), p_M_Requisition_ID, get_TrxName()); + if (!MRequisition.DOCSTATUS_Completed.equals(req.getDocStatus())) + throw new AdempiereUserError("@DocStatus@ = " + req.getDocStatus()); + MRequisitionLine[] lines = req.getLines(); + for (int i = 0; i < lines.length; i++) + { + if (lines[i].getC_OrderLine_ID() == 0) + process (lines[i]); + } + closeOrder(); + return ""; + } // single Requisition + + // + log.info("AD_Org_ID=" + p_AD_Org_ID + + ", M_Warehouse_ID=" + p_M_Warehouse_ID + + ", DateDoc=" + p_DateDoc_From + "/" + p_DateDoc_To + + ", DateRequired=" + p_DateRequired_From + "/" + p_DateRequired_To + + ", PriorityRule=" + p_PriorityRule + + ", AD_User_ID=" + p_AD_User_ID + + ", M_Product_ID=" + p_M_Product_ID + + ", ConsolidateDocument" + p_ConsolidateDocument); + + StringBuffer sql = new StringBuffer("SELECT * FROM M_RequisitionLine rl ") + .append("WHERE rl.C_OrderLine_ID IS NULL"); + if (p_AD_Org_ID != 0) + sql.append(" AND AD_Org_ID=?"); + if (p_M_Product_ID != 0) + sql.append(" AND M_Product_ID=?"); + // Requisition Header + sql.append(" AND EXISTS (SELECT * FROM M_Requisition r WHERE rl.M_Requisition_ID=r.M_Requisition_ID") + .append(" AND r.DocStatus='CO'"); + if (p_M_Warehouse_ID != 0) + sql.append(" AND r.M_Warehouse_ID=?"); + // + if (p_DateDoc_From != null && p_DateDoc_To != null) + sql.append(" AND r.DateDoc BETWEEN ? AND ?"); + else if (p_DateDoc_From != null) + sql.append(" AND r.DateDoc => ?"); + else if (p_DateDoc_To != null) + sql.append(" AND r.DateDoc <= ?"); + // + if (p_DateRequired_From != null && p_DateRequired_To != null) + sql.append(" AND r.DateRequired BETWEEN ? AND ?"); + else if (p_DateRequired_From != null) + sql.append(" AND r.DateRequired => ?"); + else if (p_DateRequired_To != null) + sql.append(" AND r.DateRequired <= ?"); + // + if (p_PriorityRule != null) + sql.append(" AND r.PriorityRule => ?"); + if (p_AD_User_ID != 0) + sql.append(" AND r.AD_User_ID=?"); + // + sql.append(") ORDER BY "); + if (!p_ConsolidateDocument) + sql.append("M_Requisition_ID, "); + sql.append("M_Product_ID, C_Charge_ID, M_AttributeSetInstance_ID"); + + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql.toString(), get_TrxName()); + int index = 1; + if (p_AD_Org_ID != 0) + pstmt.setInt (index++, p_AD_Org_ID); + if (p_M_Product_ID != 0) + pstmt.setInt (index++, p_M_Product_ID); + if (p_M_Warehouse_ID != 0) + pstmt.setInt (index++, p_M_Warehouse_ID); + if (p_DateDoc_From != null && p_DateDoc_To != null) + { + pstmt.setTimestamp(index++, p_DateDoc_From); + pstmt.setTimestamp(index++, p_DateDoc_To); + } + else if (p_DateDoc_From != null) + pstmt.setTimestamp(index++, p_DateDoc_From); + else if (p_DateDoc_To != null) + pstmt.setTimestamp(index++, p_DateDoc_To); + if (p_DateRequired_From != null && p_DateRequired_To != null) + { + pstmt.setTimestamp(index++, p_DateRequired_From); + pstmt.setTimestamp(index++, p_DateRequired_To); + } + else if (p_DateRequired_From != null) + pstmt.setTimestamp(index++, p_DateRequired_From); + else if (p_DateRequired_To != null) + pstmt.setTimestamp(index++, p_DateRequired_To); + if (p_PriorityRule != null) + pstmt.setString(index++, p_PriorityRule); + if (p_AD_User_ID != 0) + pstmt.setInt (index++, p_AD_User_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + process (new MRequisitionLine (getCtx(), rs, get_TrxName())); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql.toString(), e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + closeOrder(); + return ""; + } // doit + + private int m_M_Requisition_ID = 0; + private int m_M_Product_ID = 0; + private int m_M_AttributeSetInstance_ID = 0; + /** BPartner */ + private MBPartner m_bpartner = null; + + /** + * Process Line + * @param rLine request line + * @throws Exception + */ + private void process (MRequisitionLine rLine) throws Exception + { + if (rLine.getM_Product_ID() == 0 && rLine.getC_Charge_ID() == 0) + { + log.warning("Ignored Line" + rLine.getLine() + + " " + rLine.getDescription() + + " - " + rLine.getLineNetAmt()); + return; + } + + if (!p_ConsolidateDocument + && rLine.getM_Requisition_ID() != m_M_Requisition_ID) + closeOrder(); + if (m_orderLine == null + || rLine.getM_Product_ID() != m_M_Product_ID + || rLine.getM_AttributeSetInstance_ID() != m_M_AttributeSetInstance_ID + || rLine.getC_Charge_ID() != 0) // single line per charge + newLine(rLine); + + // Update Order Line + m_orderLine.setQty(m_orderLine.getQtyOrdered().add(rLine.getQty())); + // Update Requisition Line + rLine.setC_OrderLine_ID(m_orderLine.getC_OrderLine_ID()); + if (!rLine.save()) + throw new AdempiereSystemError("Cannot update Request Line"); + } // process + + /** + * Create new Order + * @param rLine request line + * @param C_BPartner_ID b.partner + * @throws Exception + */ + private void newOrder(MRequisitionLine rLine, int C_BPartner_ID) throws Exception + { + if (m_order != null) + closeOrder(); + // BPartner + if (m_bpartner == null || C_BPartner_ID != m_bpartner.getC_BPartner_ID()) + m_bpartner = new MBPartner (getCtx(), C_BPartner_ID, null); + + // Order + m_order = new MOrder(getCtx(), 0, get_TrxName()); + m_order.setIsSOTrx(false); + m_order.setC_DocTypeTarget_ID(); + m_order.setBPartner(m_bpartner); + // default po document type + if (!p_ConsolidateDocument) + m_order.setDescription(Msg.getElement(getCtx(), "M_Requisition_ID") + + ": " + rLine.getParent().getDocumentNo()); + + // Prepare Save + m_M_Requisition_ID = rLine.getM_Requisition_ID(); + if (!m_order.save()) + throw new AdempiereSystemError("Cannot save Order"); + } // newOrder + + /** + * Close Order + * @throws Exception + */ + private void closeOrder() throws Exception + { + if (m_orderLine != null) + { + if (!m_orderLine.save()) + throw new AdempiereSystemError("Cannot update Order Line"); + } + if (m_order != null) + { + m_order.load(get_TrxName()); + addLog(0, null, m_order.getGrandTotal(), m_order.getDocumentNo()); + } + m_order = null; + m_orderLine = null; + } // closeOrder + + + /** + * New Order Line (different Product) + * @param rLine request line + * @throws Exception + */ + private void newLine(MRequisitionLine rLine) throws Exception + { + if (m_orderLine != null) + if (!m_orderLine.save()) + throw new AdempiereSystemError("Cannot update Order Line"); + m_orderLine = null; + MProduct product = null; + + // Get Business Partner + int C_BPartner_ID = rLine.getC_BPartner_ID(); + if (C_BPartner_ID != 0) + ; + else if (rLine.getC_Charge_ID() != 0) + { + MCharge charge = MCharge.get(getCtx(), rLine.getC_Charge_ID()); + C_BPartner_ID = charge.getC_BPartner_ID(); + if (C_BPartner_ID == 0) + throw new AdempiereUserError("No Vendor for Charge " + charge.getName()); + } + else + { + // Find Vendor from Produt + product = MProduct.get(getCtx(), rLine.getM_Product_ID()); + MProductPO[] ppos = MProductPO.getOfProduct(getCtx(), product.getM_Product_ID(), null); + for (int i = 0; i < ppos.length; i++) + { + if (ppos[i].isCurrentVendor() && ppos[i].getC_BPartner_ID() != 0) + { + C_BPartner_ID = ppos[i].getC_BPartner_ID(); + break; + } + } + if (C_BPartner_ID == 0 && ppos.length > 0) + C_BPartner_ID = ppos[0].getC_BPartner_ID(); + if (C_BPartner_ID == 0) + throw new AdempiereUserError("No Vendor for " + product.getName()); + } + + // New Order - Different Vendor + if (m_order == null + || m_order.getC_BPartner_ID() != C_BPartner_ID) + newOrder(rLine, C_BPartner_ID); + + + // No Order Line + m_orderLine = new MOrderLine(m_order); + if (product != null) + { + m_orderLine.setProduct(product); + m_orderLine.setM_AttributeSetInstance_ID(rLine.getM_AttributeSetInstance_ID()); + } + else + { + m_orderLine.setC_Charge_ID(rLine.getC_Charge_ID()); + m_orderLine.setPriceActual(rLine.getPriceActual()); + } + m_orderLine.setAD_Org_ID(rLine.getAD_Org_ID()); + + + // Prepare Save + m_M_Product_ID = rLine.getM_Product_ID(); + m_M_AttributeSetInstance_ID = rLine.getM_AttributeSetInstance_ID(); + if (!m_orderLine.save()) + throw new AdempiereSystemError("Cannot save Order Line"); + } // newLine + +} // RequisitionPOCreate diff --git a/base/src/org/compiere/process/RfQClose.java b/base/src/org/compiere/process/RfQClose.java new file mode 100644 index 0000000000..505f1647a0 --- /dev/null +++ b/base/src/org/compiere/process/RfQClose.java @@ -0,0 +1,78 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import org.compiere.model.*; + + +/** + * Close RfQ and Responses + * + * @author Jorg Janke + * @version $Id: RfQClose.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class RfQClose extends SvrProcess +{ + /** RfQ */ + private int p_C_RfQ_ID = 0; + + /** + * Prepare + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + p_C_RfQ_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @see org.compiere.process.SvrProcess#doIt() + * @return message + */ + protected String doIt () throws Exception + { + MRfQ rfq = new MRfQ (getCtx(), p_C_RfQ_ID, get_TrxName()); + if (rfq.get_ID() == 0) + throw new IllegalArgumentException("No RfQ found"); + log.info("doIt - " + rfq); + // + rfq.setProcessed(true); + rfq.save(); + // + int counter = 0; + MRfQResponse[] responses = rfq.getResponses (false, false); + for (int i = 0; i < responses.length; i++) + { + responses[i].setProcessed(false); + responses[i].save(); + counter++; + } + // + return "# " + counter; + } // doIt + +} // RfQClose diff --git a/base/src/org/compiere/process/RfQCopyLines.java b/base/src/org/compiere/process/RfQCopyLines.java new file mode 100644 index 0000000000..0d337e11e9 --- /dev/null +++ b/base/src/org/compiere/process/RfQCopyLines.java @@ -0,0 +1,105 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.util.logging.*; +import org.compiere.model.*; + + +/** + * Copy Lines + * + * @author Jorg Janke + * @version $Id: RfQCopyLines.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class RfQCopyLines extends SvrProcess +{ + /** From RfQ */ + private int p_From_RfQ_ID = 0; + /** From RfQ */ + private int p_To_RfQ_ID = 0; + + /** + * Prepare + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_RfQ_ID")) + p_From_RfQ_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + p_To_RfQ_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @see org.compiere.process.SvrProcess#doIt() + * @return message + */ + protected String doIt () throws Exception + { + log.info("doIt - From_RfQ_ID=" + p_From_RfQ_ID + ", To_RfQ_ID=" + p_To_RfQ_ID); + // + MRfQ to = new MRfQ (getCtx(), p_To_RfQ_ID, get_TrxName()); + if (to.get_ID() == 0) + throw new IllegalArgumentException("No To RfQ found"); + MRfQ from = new MRfQ (getCtx(), p_From_RfQ_ID, get_TrxName()); + if (from.get_ID() == 0) + throw new IllegalArgumentException("No From RfQ found"); + + // Copy Lines + int counter = 0; + MRfQLine[] lines = from.getLines(); + for (int i = 0; i < lines.length; i++) + { + MRfQLine newLine = new MRfQLine (to); + newLine.setLine(lines[i].getLine()); + newLine.setDescription(lines[i].getDescription()); + newLine.setHelp(lines[i].getHelp()); + newLine.setM_Product_ID(lines[i].getM_Product_ID()); + newLine.setM_AttributeSetInstance_ID(lines[i].getM_AttributeSetInstance_ID()); + // newLine.setDateWorkStart(); + // newLine.setDateWorkComplete(); + newLine.setDeliveryDays(lines[i].getDeliveryDays()); + newLine.save(); + // Copy Qtys + MRfQLineQty[] qtys = lines[i].getQtys(); + for (int j = 0; j < qtys.length; j++) + { + MRfQLineQty newQty = new MRfQLineQty (newLine); + newQty.setC_UOM_ID(qtys[j].getC_UOM_ID()); + newQty.setQty(qtys[j].getQty()); + newQty.setIsOfferQty(qtys[j].isOfferQty()); + newQty.setIsPurchaseQty(qtys[j].isPurchaseQty()); + newQty.setMargin(qtys[j].getMargin()); + newQty.save(); + } + counter++; + } // copy all lines + + // + return "# " + counter; + } // doIt +} diff --git a/base/src/org/compiere/process/RfQCreate.java b/base/src/org/compiere/process/RfQCreate.java new file mode 100644 index 0000000000..ae83ddc76e --- /dev/null +++ b/base/src/org/compiere/process/RfQCreate.java @@ -0,0 +1,115 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import org.compiere.model.*; + +/** + * Create RfQ Response from RfQ Topic + * + * @author Jorg Janke + * @version $Id: RfQCreate.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class RfQCreate extends SvrProcess +{ + /** Send RfQ */ + private boolean p_IsSendRfQ = false; + /** RfQ */ + private int p_C_RfQ_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("IsSendRfQ")) + p_IsSendRfQ = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_C_RfQ_ID = getRecord_ID(); + } // prepare + + /** + * Perform process. + * @return Message (translated text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + MRfQ rfq = new MRfQ (getCtx(), p_C_RfQ_ID, get_TrxName()); + log.info("doIt - " + rfq + ", Send=" + p_IsSendRfQ); + String error = rfq.checkQuoteTotalAmtOnly(); + if (error != null && error.length() > 0) + throw new Exception (error); + + int counter = 0; + int sent = 0; + int notSent = 0; + + // Get all existing responses + MRfQResponse[] responses = rfq.getResponses (false, false); + + // Topic + MRfQTopic topic = new MRfQTopic (getCtx(), rfq.getC_RfQ_Topic_ID(), get_TrxName()); + MRfQTopicSubscriber[] subscribers = topic.getSubscribers(); + for (int i = 0; i < subscribers.length; i++) + { + MRfQTopicSubscriber subscriber = subscribers[i]; + boolean skip = false; + // existing response + for (int r = 0; r < responses.length; r++) + { + if (subscriber.getC_BPartner_ID() == responses[r].getC_BPartner_ID() + && subscriber.getC_BPartner_Location_ID() == responses[r].getC_BPartner_Location_ID()) + { + skip = true; + break; + } + } + if (skip) + continue; + + // Create Response + MRfQResponse response = new MRfQResponse (rfq, subscriber); + if (response.get_ID() == 0) // no lines + continue; + + counter++; + if (p_IsSendRfQ) + { + if (response.sendRfQ()) + sent++; + else + notSent++; + } + } // for all subscribers + + String retValue = "@Created@ " + counter; + if (p_IsSendRfQ) + retValue += " - @IsSendRfQ@=" + sent + " - @Error@=" + notSent; + return retValue; + } // doIt + +} // RfQCreate diff --git a/base/src/org/compiere/process/RfQCreatePO.java b/base/src/org/compiere/process/RfQCreatePO.java new file mode 100644 index 0000000000..45d079686c --- /dev/null +++ b/base/src/org/compiere/process/RfQCreatePO.java @@ -0,0 +1,195 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.util.logging.*; +import org.compiere.model.*; + +/** + * Create RfQ PO. + * Create purchase order(s) for the resonse(s) and lines marked as + * Selected Winner using the selected Purchase Quantity (in RfQ Line Quantity) + * + * @author Jorg Janke + * @version $Id: RfQCreatePO.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class RfQCreatePO extends SvrProcess +{ + /** RfQ */ + private int p_C_RfQ_ID = 0; + private int p_C_DocType_ID = 0; + + /** + * Prepare + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_DocType_ID")) + p_C_DocType_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_C_RfQ_ID = getRecord_ID(); + } // prepare + + /** + * Process. + * Create purchase order(s) for the resonse(s) and lines marked as + * Selected Winner using the selected Purchase Quantity (in RfQ Line Quantity) . + * If a Response is marked as Selected Winner, all lines are created + * (and Selected Winner of other responses ignored). + * If there is no response marked as Selected Winner, the lines are used. + * @return message + */ + protected String doIt () throws Exception + { + MRfQ rfq = new MRfQ (getCtx(), p_C_RfQ_ID, get_TrxName()); + if (rfq.get_ID() == 0) + throw new IllegalArgumentException("No RfQ found"); + log.info(rfq.toString()); + + // Complete + MRfQResponse[] responses = rfq.getResponses(true, true); + log.config("#Responses=" + responses.length); + if (responses.length == 0) + throw new IllegalArgumentException("No completed RfQ Responses found"); + + // Winner for entire RfQ + for (int i = 0; i < responses.length; i++) + { + MRfQResponse response = responses[i]; + if (!response.isSelectedWinner()) + continue; + // + MBPartner bp = new MBPartner(getCtx(), response.getC_BPartner_ID(), get_TrxName()); + log.config("Winner=" + bp); + MOrder order = new MOrder (getCtx(), 0, get_TrxName()); + order.setIsSOTrx(false); + if (p_C_DocType_ID != 0) + order.setC_DocTypeTarget_ID(p_C_DocType_ID); + else + order.setC_DocTypeTarget_ID(); + order.setBPartner(bp); + order.setC_BPartner_Location_ID(response.getC_BPartner_Location_ID()); + order.setSalesRep_ID(rfq.getSalesRep_ID()); + if (response.getDateWorkComplete() != null) + order.setDatePromised(response.getDateWorkComplete()); + else if (rfq.getDateWorkComplete() != null) + order.setDatePromised(rfq.getDateWorkComplete()); + order.save(); + // + MRfQResponseLine[] lines = response.getLines(false); + for (int j = 0; j < lines.length; j++) + { + // Respones Line + MRfQResponseLine line = lines[j]; + if (!line.isActive()) + continue; + MRfQResponseLineQty[] qtys = line.getQtys(false); + // Response Line Qty + for (int k = 0; k < qtys.length; k++) + { + MRfQResponseLineQty qty = qtys[k]; + // Create PO Lline for all Purchase Line Qtys + if (qty.getRfQLineQty().isActive() && qty.getRfQLineQty().isPurchaseQty()) + { + MOrderLine ol = new MOrderLine (order); + ol.setM_Product_ID(line.getRfQLine().getM_Product_ID(), + qty.getRfQLineQty().getC_UOM_ID()); + ol.setDescription(line.getDescription()); + ol.setQty(qty.getRfQLineQty().getQty()); + BigDecimal price = qty.getNetAmt(); + ol.setPrice(price); + ol.save(); + } + } + } + response.setC_Order_ID(order.getC_Order_ID()); + response.save(); + return order.getDocumentNo(); + } + + + // Selected Winner on Line Level + int noOrders = 0; + for (int i = 0; i < responses.length; i++) + { + MRfQResponse response = responses[i]; + MBPartner bp = null; + MOrder order = null; + // For all Response Lines + MRfQResponseLine[] lines = response.getLines(false); + for (int j = 0; j < lines.length; j++) + { + MRfQResponseLine line = lines[j]; + if (!line.isActive() || !line.isSelectedWinner()) + continue; + // New/different BP + if (bp == null) + { + bp = new MBPartner(getCtx(), response.getC_BPartner_ID(), get_TrxName()); + order = null; + } + log.config("Line=" + line + ", Winner=" + bp); + // New Order + if (order == null) + { + order = new MOrder (getCtx(), 0, get_TrxName()); + order.setIsSOTrx(false); + order.setC_DocTypeTarget_ID(); + order.setBPartner(bp); + order.setC_BPartner_Location_ID(response.getC_BPartner_Location_ID()); + order.setSalesRep_ID(rfq.getSalesRep_ID()); + order.save(); + noOrders++; + addLog(0, null, null, order.getDocumentNo()); + } + // For all Qtys + MRfQResponseLineQty[] qtys = line.getQtys(false); + for (int k = 0; k < qtys.length; k++) + { + MRfQResponseLineQty qty = qtys[k]; + if (qty.getRfQLineQty().isActive() && qty.getRfQLineQty().isPurchaseQty()) + { + MOrderLine ol = new MOrderLine (order); + ol.setM_Product_ID(line.getRfQLine().getM_Product_ID(), + qty.getRfQLineQty().getC_UOM_ID()); + ol.setDescription(line.getDescription()); + ol.setQty(qty.getRfQLineQty().getQty()); + BigDecimal price = qty.getNetAmt(); + ol.setPriceActual(price); + ol.save(); + } + } // for all Qtys + } // for all Response Lines + if (order != null) + { + response.setC_Order_ID(order.getC_Order_ID()); + response.save(); + } + } + + return "#" + noOrders; + } // doIt +} // RfQCreatePO diff --git a/base/src/org/compiere/process/RfQCreateSO.java b/base/src/org/compiere/process/RfQCreateSO.java new file mode 100644 index 0000000000..54c20ca0ec --- /dev/null +++ b/base/src/org/compiere/process/RfQCreateSO.java @@ -0,0 +1,145 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Create SO for RfQ. + * + * @author Jorg Janke + * @version $Id: RfQCreateSO.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class RfQCreateSO extends SvrProcess +{ + /** RfQ */ + private int p_C_RfQ_ID = 0; + private int p_C_DocType_ID = 0; + + /** 100 */ + private static BigDecimal ONEHUNDRED = new BigDecimal (100); + + /** + * Prepare + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_DocType_ID")) + p_C_DocType_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + p_C_RfQ_ID = getRecord_ID(); + } // prepare + + /** + * Process. + * A Sales Order is created for the entered Business Partner. + * A sales order line is created for each RfQ line quantity, + * where "Offer Quantity" is selected. + * If on the RfQ Line Quantity, an offer amount is entered (not 0), + * that price is used. + * If a magin is entered on RfQ Line Quantity, it overwrites the + * general margin. The margin is the percentage added to the + * Best Response Amount. + * @return message + */ + protected String doIt () throws Exception + { + MRfQ rfq = new MRfQ (getCtx(), p_C_RfQ_ID, get_TrxName()); + if (rfq.get_ID() == 0) + throw new IllegalArgumentException("No RfQ found"); + log.info("doIt - " + rfq); + + if (rfq.getC_BPartner_ID() == 0 || rfq.getC_BPartner_Location_ID() == 0) + throw new Exception ("No Business Partner/Location"); + MBPartner bp = new MBPartner (getCtx(), rfq.getC_BPartner_ID(), get_TrxName()); + + MOrder order = new MOrder (getCtx(), 0, get_TrxName()); + order.setIsSOTrx(true); + if (p_C_DocType_ID != 0) + order.setC_DocTypeTarget_ID(p_C_DocType_ID); + else + order.setC_DocTypeTarget_ID(); + order.setBPartner(bp); + order.setC_BPartner_Location_ID(rfq.getC_BPartner_Location_ID()); + order.setSalesRep_ID(rfq.getSalesRep_ID()); + if (rfq.getDateWorkComplete() != null) + order.setDatePromised(rfq.getDateWorkComplete()); + order.save(); + + MRfQLine[] lines = rfq.getLines(); + for (int i = 0; i < lines.length; i++) + { + MRfQLine line = lines[i]; + MRfQLineQty[] qtys = line.getQtys(); + for (int j = 0; j < qtys.length; j++) + { + MRfQLineQty qty = qtys[j]; + if (qty.isActive() && qty.isOfferQty()) + { + MOrderLine ol = new MOrderLine (order); + ol.setM_Product_ID(line.getM_Product_ID(), + qty.getC_UOM_ID()); + ol.setDescription(line.getDescription()); + ol.setQty(qty.getQty()); + // + BigDecimal price = qty.getOfferAmt(); + if (price == null || price.signum() == 0) + { + price = qty.getBestResponseAmt(); + if (price == null || price.signum() == 0) + { + price = Env.ZERO; + log.warning(" - BestResponse=0 - " + qty); + } + else + { + BigDecimal margin = qty.getMargin(); + if (margin == null || margin.signum() == 0) + margin = rfq.getMargin(); + if (margin != null && margin.signum() != 0) + { + margin = margin.add(ONEHUNDRED); + price = price.multiply(margin) + .divide(ONEHUNDRED, 2, BigDecimal.ROUND_HALF_UP); + } + } + } // price + ol.setPrice(price); + ol.save(); + } // Offer Qty + } // All Qtys + } // All Lines + + // + rfq.setC_Order_ID(order.getC_Order_ID()); + rfq.save(); + return order.getDocumentNo(); + } // doIt +} diff --git a/base/src/org/compiere/process/RfQResponseCComplete.java b/base/src/org/compiere/process/RfQResponseCComplete.java new file mode 100644 index 0000000000..41eb0fcd7d --- /dev/null +++ b/base/src/org/compiere/process/RfQResponseCComplete.java @@ -0,0 +1,68 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import org.compiere.model.*; + +/** + * Check if Response is Complete + * + * @author Jorg Janke + * @version $Id: RfQResponseCComplete.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class RfQResponseCComplete extends SvrProcess +{ + /** RfQ Response */ + private int p_C_RfQResponse_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_C_RfQResponse_ID = getRecord_ID(); + } // prepare + + /** + * Perform process. + * @return Message + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + MRfQResponse response = new MRfQResponse (getCtx(), p_C_RfQResponse_ID, get_TrxName()); + log.info("doIt - " + response); + // + String error = response.checkComplete(); + if (error != null && error.length() > 0) + throw new Exception (error); + // + response.save(); + return "OK"; + } // doIt + +} // RfQResponseCComplete diff --git a/base/src/org/compiere/process/RfQResponseInvite.java b/base/src/org/compiere/process/RfQResponseInvite.java new file mode 100644 index 0000000000..55e2158c45 --- /dev/null +++ b/base/src/org/compiere/process/RfQResponseInvite.java @@ -0,0 +1,71 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import org.compiere.model.*; + + +/** + * RfQ Response - Invite. + * Send Inites/Reminder to Vendor to respond to RfQ. + * + * @author Jorg Janke + * @version $Id: RfQResponseInvite.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class RfQResponseInvite extends SvrProcess +{ + /** RfQ Response */ + private int p_C_RfQResponse_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_C_RfQResponse_ID = getRecord_ID(); + } // prepare + + /** + * Perform process. + * @return Message + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + MRfQResponse response = new MRfQResponse (getCtx(), p_C_RfQResponse_ID, get_TrxName()); + log.info("doIt - " + response); + String error = response.getRfQ().checkQuoteTotalAmtOnly(); + if (error != null && error.length() > 0) + throw new Exception (error); + // Send it + if (response.sendRfQ()) + return "OK"; + // + return "@Error@"; + } // doIt + +} // RfQResponseInvite diff --git a/base/src/org/compiere/process/RfQResponseRank.java b/base/src/org/compiere/process/RfQResponseRank.java new file mode 100644 index 0000000000..64294c3267 --- /dev/null +++ b/base/src/org/compiere/process/RfQResponseRank.java @@ -0,0 +1,265 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Rank RfQ Responses + * + * @author Jorg Janke + * @version $Id: RfQResponseRank.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class RfQResponseRank extends SvrProcess +{ + /** RfQ */ + private int p_C_RfQ_ID = 0; + + /** + * Prepare + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_C_RfQ_ID = getRecord_ID(); + } // prepare + + /** + * Process. + *
+	 * 	- ignore 0 or invalid responses
+	 * 	- rank among qty
+	 * 	- for selected PO qty select winner
+	 * 	- if all lines are winner - select that
+	 *  
+ * @return message + */ + protected String doIt () throws Exception + { + MRfQ rfq = new MRfQ (getCtx(), p_C_RfQ_ID, get_TrxName()); + if (rfq.get_ID() == 0) + throw new IllegalArgumentException("No RfQ found"); + log.info(rfq.toString()); + String error = rfq.checkQuoteTotalAmtOnly(); + if (error != null && error.length() > 0) + throw new Exception (error); + + // Get Completed, Active Responses + MRfQResponse[] responses = rfq.getResponses (true, true); + log.fine("doIt - #Responses=" + responses.length); + if (responses.length == 0) + throw new IllegalArgumentException("No completed RfQ Responses found"); + if (responses.length == 1) + { + responses[0].setIsSelectedWinner(true); + responses[0].save(); + throw new IllegalArgumentException("Only one completed RfQ Response found"); + } + + // Rank + if (rfq.isQuoteTotalAmtOnly()) + rankResponses(rfq, responses); + else + rankLines (rfq, responses); + return "# " + responses.length; + } // doIt + + + /************************************************************************** + * Rank Lines + * @param rfq RfQ + * @param responses responses + */ + @SuppressWarnings("unchecked") + private void rankLines (MRfQ rfq, MRfQResponse[] responses) + { + MRfQLine[] rfqLines = rfq.getLines(); + if (rfqLines.length == 0) + throw new IllegalArgumentException("No RfQ Lines found"); + + // for all lines + for (int i = 0; i < rfqLines.length; i++) + { + // RfQ Line + MRfQLine rfqLine = rfqLines[i]; + if (!rfqLine.isActive()) + continue; + log.fine("rankLines - " + rfqLine); + MRfQLineQty[] rfqQtys = rfqLine.getQtys(); + for (int j = 0; j < rfqQtys.length; j++) + { + // RfQ Line Qty + MRfQLineQty rfqQty = rfqQtys[j]; + if (!rfqQty.isActive() || !rfqQty.isRfQQty()) + continue; + log.fine("rankLines Qty - " + rfqQty); + MRfQResponseLineQty[] respQtys = rfqQty.getResponseQtys(false); + for (int kk = 0; kk < respQtys.length; kk++) + { + // Response Line Qty + MRfQResponseLineQty respQty = respQtys[kk]; + if (!respQty.isActive() || !respQty.isValidAmt()) + { + respQty.setRanking(999); + respQty.save(); + log.fine(" - ignored: " + respQty); + } + } // for all respones line qtys + + // Rank RfQ Line Qtys + respQtys = rfqQty.getResponseQtys(false); + if (respQtys.length == 0) + log.fine(" - No Qtys with valid Amounts"); + else + { + Arrays.sort(respQtys, respQtys[0]); + int lastRank = 1; // multiple rank #1 + BigDecimal lastAmt = Env.ZERO; + for (int rank = 0; rank < respQtys.length; rank++) + { + MRfQResponseLineQty qty = respQtys[rank]; + if (!qty.isActive() || qty.getRanking() == 999) + continue; + BigDecimal netAmt = qty.getNetAmt(); + if (netAmt == null) + { + qty.setRanking(999); + log.fine(" - Rank 999: " + qty); + } + else + { + if (lastAmt.compareTo(netAmt) != 0) + { + lastRank = rank+1; + lastAmt = qty.getNetAmt(); + } + qty.setRanking(lastRank); + log.fine(" - Rank " + lastRank + ": " + qty); + } + qty.save(); + // + if (rank == 0) // Update RfQ + { + rfqQty.setBestResponseAmt(qty.getNetAmt()); + rfqQty.save(); + } + } + } + } // for all rfq line qtys + } // for all rfq lines + + // Select Winner based on line ranking + MRfQResponse winner = null; + for (int ii = 0; ii < responses.length; ii++) + { + MRfQResponse response = responses[ii]; + if (response.isSelectedWinner()) + response.setIsSelectedWinner(false); + int ranking = 0; + MRfQResponseLine[] respLines = response.getLines(false); + for (int jj = 0; jj < respLines.length; jj++) + { + // Response Line + MRfQResponseLine respLine = respLines[jj]; + if (!respLine.isActive()) + continue; + if (respLine.isSelectedWinner()) + respLine.setIsSelectedWinner(false); + MRfQResponseLineQty[] respQtys = respLine.getQtys(false); + for (int kk = 0; kk < respQtys.length; kk++) + { + // Response Line Qty + MRfQResponseLineQty respQty = respQtys[kk]; + if (!respQty.isActive()) + continue; + ranking += respQty.getRanking(); + if (respQty.getRanking() == 1 + && respQty.getRfQLineQty().isPurchaseQty()) + { + respLine.setIsSelectedWinner(true); + respLine.save(); + break; + } + } + } + response.setRanking(ranking); + response.save(); + log.fine("- Response Ranking " + ranking + ": " + response); + if (!rfq.isQuoteSelectedLines()) // no total selected winner if not all lines + { + if (winner == null && ranking > 0) + winner = response; + if (winner != null + && response.getRanking() > 0 + && response.getRanking() < winner.getRanking()) + winner = response; + } + } + if (winner != null) + { + winner.setIsSelectedWinner(true); + winner.save(); + log.fine("- Response Winner: " + winner); + } + } // rankLines + + + /************************************************************************** + * Rank Response based on Header + * @param rfq RfQ + * @param responses responses + */ + private void rankResponses (MRfQ rfq, MRfQResponse[] responses) + { + int ranking = 1; + // Responses Ordered by Price + for (int ii = 0; ii < responses.length; ii++) + { + MRfQResponse response = responses[ii]; + if (response.getPrice() != null + && response.getPrice().compareTo(Env.ZERO) > 0) + { + if (response.isSelectedWinner() != (ranking == 1)) + response.setIsSelectedWinner(ranking == 1); + response.setRanking(ranking); + // + ranking++; + } + else + { + response.setRanking(999); + if (response.isSelectedWinner()) + response.setIsSelectedWinner(false); + } + response.save(); + log.fine("rankResponse - " + response); + } + } // rankResponses + +} // RfQResponseRank diff --git a/base/src/org/compiere/process/RoleAccessUpdate.java b/base/src/org/compiere/process/RoleAccessUpdate.java new file mode 100644 index 0000000000..45b83e8243 --- /dev/null +++ b/base/src/org/compiere/process/RoleAccessUpdate.java @@ -0,0 +1,119 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Update Role Access + * + * @author Jorg Janke + * @version $Id: RoleAccessUpdate.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class RoleAccessUpdate extends SvrProcess +{ + /** Update Role */ + private int p_AD_Role_ID = 0; + /** Update Roles of Client */ + private int p_AD_Client_ID = 0; + + + /** + * Prepare + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Role_ID")) + p_AD_Role_ID = para[i].getParameterAsInt(); + else if (name.equals("AD_Client_ID")) + p_AD_Client_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("AD_Client_ID=" + p_AD_Client_ID + ", AD_Role_ID=" + p_AD_Role_ID); + // + if (p_AD_Role_ID != 0) + updateRole (new MRole (getCtx(), p_AD_Role_ID, get_TrxName())); + else + { + String sql = "SELECT * FROM AD_Role "; + if (p_AD_Client_ID != 0) + sql += "WHERE AD_Client_ID=? "; + sql += "ORDER BY AD_Client_ID, Name"; + + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + if (p_AD_Client_ID != 0) + pstmt.setInt (1, p_AD_Client_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + updateRole (new MRole (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + } + + return ""; + } // doIt + + /** + * Update Role + * @param role role + */ + private void updateRole (MRole role) + { + addLog(0, null, null, role.getName() + ": " + + role.updateAccessRecords()); + } // updateRole + +} // RoleAccessUpdate diff --git a/base/src/org/compiere/process/SendMailText.java b/base/src/org/compiere/process/SendMailText.java new file mode 100644 index 0000000000..b7ea1a7706 --- /dev/null +++ b/base/src/org/compiere/process/SendMailText.java @@ -0,0 +1,294 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Send Mail to Interest Area Subscribers + * + * @author Jorg Janke + * @version $Id: SendMailText.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class SendMailText extends SvrProcess +{ + /** What to send */ + private int m_R_MailText_ID = -1; + /** Mail Text */ + private MMailText m_MailText = null; + + /** From (sender) */ + private int m_AD_User_ID = -1; + /** Client Info */ + private MClient m_client = null; + /** From */ + private MUser m_from = null; + /** Recipient List to prevent duplicate mails */ + private ArrayList m_list = new ArrayList(); + + + private int m_counter = 0; + private int m_errors = 0; + /** To Subscribers */ + private int m_R_InterestArea_ID = -1; + /** Interest Area */ + private MInterestArea m_ia = null; + /** To Customer Type */ + private int m_C_BP_Group_ID = -1; + /** To Purchaser of Product */ + // comes here + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("R_InterestArea_ID")) + m_R_InterestArea_ID = para[i].getParameterAsInt(); + else if (name.equals("R_MailText_ID")) + m_R_MailText_ID = para[i].getParameterAsInt(); + else if (name.equals("C_BP_Group_ID")) + m_C_BP_Group_ID = para[i].getParameterAsInt(); + else if (name.equals("AD_User_ID")) + m_AD_User_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info("R_MailText_ID=" + m_R_MailText_ID); + // Mail Test + m_MailText = new MMailText (getCtx(), m_R_MailText_ID, get_TrxName()); + if (m_MailText.getR_MailText_ID() == 0) + throw new Exception ("Not found @R_MailText_ID@=" + m_R_MailText_ID); + // Client Info + m_client = MClient.get (getCtx()); + if (m_client.getAD_Client_ID() == 0) + throw new Exception ("Not found @AD_Client_ID@"); + if (m_client.getSMTPHost() == null || m_client.getSMTPHost().length() == 0) + throw new Exception ("No SMTP Host found"); + // + if (m_AD_User_ID > 0) + { + m_from = new MUser (getCtx(), m_AD_User_ID, get_TrxName()); + if (m_from.getAD_User_ID() == 0) + throw new Exception ("No found @AD_User_ID@=" + m_AD_User_ID); + } + log.fine("From " + m_from); + long start = System.currentTimeMillis(); + + if (m_R_InterestArea_ID > 0) + sendInterestArea(); + if (m_C_BP_Group_ID > 0) + sendBPGroup(); + + return "@Created@=" + m_counter + ", @Errors@=" + m_errors + " - " + + (System.currentTimeMillis()-start) + "ms"; + } // doIt + + /** + * Send to InterestArea + */ + private void sendInterestArea() + { + log.info("R_InterestArea_ID=" + m_R_InterestArea_ID); + m_ia = MInterestArea.get(getCtx(), m_R_InterestArea_ID); + String unsubscribe = null; + if (m_ia.isSelfService()) + { + unsubscribe = "\n\n---------.----------.----------.----------.----------.----------\n" + + Msg.getElement(getCtx(), "R_InterestArea_ID") + + ": " + m_ia.getName() + + "\n" + Msg.getMsg(getCtx(), "UnsubscribeInfo") + + "\n"; + MStore[] wstores = MStore.getOfClient(m_client); + int index = 0; + for (int i = 0; i < wstores.length; i++) + { + if (wstores[i].isDefault()) + { + index = i; + break; + } + } + if (wstores.length > 0) + unsubscribe += wstores[index].getWebContext(true); + } + + // + String sql = "SELECT u.Name, u.EMail, u.AD_User_ID " + + "FROM R_ContactInterest ci" + + " INNER JOIN AD_User u ON (ci.AD_User_ID=u.AD_User_ID) " + + "WHERE ci.IsActive='Y' AND u.IsActive='Y'" + + " AND ci.OptOutDate IS NULL" + + " AND u.EMail IS NOT NULL" + + " AND ci.R_InterestArea_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, m_R_InterestArea_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + Boolean ok = sendIndividualMail (rs.getString(1), rs.getInt(3), unsubscribe); + if (ok == null) + ; + else if (ok.booleanValue()) + m_counter++; + else + m_errors++; + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + } + // Clean Up + try + { + if (pstmt != null) + pstmt.close(); + } + catch (SQLException ex1) + { + } + pstmt = null; + m_ia = null; + } // sendInterestArea + + + /** + * Send to BPGroup + */ + private void sendBPGroup() + { + log.info("C_BP_Group_ID=" + m_C_BP_Group_ID); + String sql = "SELECT u.Name, u.EMail, u.AD_User_ID " + + "FROM AD_User u" + + " INNER JOIN C_BPartner bp ON (u.C_BPartner_ID=bp.C_BPartner_ID) " + + "WHERE u.IsActive='Y' AND bp.IsActive='Y'" + + " AND u.EMail IS NOT NULL" + + " AND bp.C_BP_Group_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, m_C_BP_Group_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + Boolean ok = sendIndividualMail (rs.getString(1), rs.getInt(3), null); + if (ok == null) + ; + else if (ok.booleanValue()) + m_counter++; + else + m_errors++; + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + } + // Clean Up + try + { + if (pstmt != null) + pstmt.close(); + } + catch (SQLException ex1) + { + } + pstmt = null; + } // sendBPGroup + + /** + * Send Individual Mail + * @param Name user name + * @param AD_User_ID user + * @param unsubscribe unsubscribe message + * @return true if mail has been sent + */ + private Boolean sendIndividualMail (String Name, int AD_User_ID, String unsubscribe) + { + // Prevent two email + Integer ii = new Integer (AD_User_ID); + if (m_list.contains(ii)) + return null; + m_list.add(ii); + // + MUser to = new MUser (getCtx(), AD_User_ID, null); + m_MailText.setUser(AD_User_ID); // parse context + String message = m_MailText.getMailText(true); + // Unsubscribe + if (unsubscribe != null) + message += unsubscribe; + // + EMail email = m_client.createEMail(m_from, to, m_MailText.getMailHeader(), message); + if (m_MailText.isHtml()) + email.setMessageHTML(m_MailText.getMailHeader(), message); + else + { + email.setSubject (m_MailText.getMailHeader()); + email.setMessageText (message); + } + if (!email.isValid() && !email.isValid(true)) + { + log.warning("NOT VALID - " + email); + to.setIsActive(false); + to.addDescription("Invalid EMail"); + to.save(); + return Boolean.FALSE; + } + boolean OK = EMail.SENT_OK.equals(email.send()); + new MUserMail(m_MailText, AD_User_ID, email).save(); + // + if (OK) + log.fine(to.getEMail()); + else + log.warning("FAILURE - " + to.getEMail()); + addLog(0, null, null, (OK ? "@OK@" : "@ERROR@") + " - " + to.getEMail()); + return new Boolean(OK); + } // sendIndividualMail + +} // SendMailText diff --git a/base/src/org/compiere/process/StorageCleanup.java b/base/src/org/compiere/process/StorageCleanup.java new file mode 100644 index 0000000000..11ef3705a7 --- /dev/null +++ b/base/src/org/compiere/process/StorageCleanup.java @@ -0,0 +1,297 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import java.math.*; + +import org.compiere.util.*; +import org.compiere.model.*; + +/** + * StorageCleanup + * + * @author Jorg Janke + * @version $Id: StorageCleanup.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class StorageCleanup extends SvrProcess +{ + /** Movement Document Type */ + private int p_C_DocType_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_DocType_ID")) + p_C_DocType_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info(""); + // Clean up empty Storage + String sql = "DELETE FROM M_Storage " + + "WHERE QtyOnHand = 0 AND QtyReserved = 0 AND QtyOrdered = 0" + + " AND Created < SysDate-3"; + int no = DB.executeUpdate(sql, get_TrxName()); + log.info("Delete Empty #" + no); + + // + sql = "SELECT * " + + "FROM M_Storage s " + + "WHERE AD_Client_ID = ?" + + " AND QtyOnHand < 0" + // Instance Attribute + + " AND EXISTS (SELECT * FROM M_Product p" + + " INNER JOIN M_AttributeSet mas ON (p.M_AttributeSet_ID=mas.M_AttributeSet_ID) " + + "WHERE s.M_Product_ID=p.M_Product_ID AND mas.IsInstanceAttribute='Y')" + // Stock in same location + // + " AND EXISTS (SELECT * FROM M_Storage sl " + // + "WHERE sl.QtyOnHand > 0" + // + " AND s.M_Product_ID=sl.M_Product_ID" + // + " AND s.M_Locator_ID=sl.M_Locator_ID)" + // Stock in same Warehouse + + " AND EXISTS (SELECT * FROM M_Storage sw" + + " INNER JOIN M_Locator swl ON (sw.M_Locator_ID=swl.M_Locator_ID), M_Locator sl " + + "WHERE sw.QtyOnHand > 0" + + " AND s.M_Product_ID=sw.M_Product_ID" + + " AND s.M_Locator_ID=sl.M_Locator_ID" + + " AND sl.M_Warehouse_ID=swl.M_Warehouse_ID)"; + PreparedStatement pstmt = null; + int lines = 0; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt(1, Env.getAD_Client_ID(getCtx())); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + lines += move (new MStorage(getCtx(), rs, get_TrxName())); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + return "#" + lines; + } // doIt + + /** + * Move stock to location + * @param target target storage + * @return no of movements + */ + private int move (MStorage target) + { + log.info(target.toString()); + BigDecimal qty = target.getQtyOnHand().negate(); + + // Create Movement + MMovement mh = new MMovement (getCtx(), 0, get_TrxName()); + mh.setAD_Org_ID(target.getAD_Org_ID()); + mh.setC_DocType_ID(p_C_DocType_ID); + mh.setDescription(getName()); + if (!mh.save()) + return 0; + + int lines = 0; + MStorage[] sources = getSources(target.getM_Product_ID(), target.getM_Locator_ID()); + for (int i = 0; i < sources.length; i++) + { + MStorage source = sources[i]; + + // Movement Line + MMovementLine ml = new MMovementLine(mh); + ml.setM_Product_ID(target.getM_Product_ID()); + ml.setM_LocatorTo_ID(target.getM_Locator_ID()); + ml.setM_AttributeSetInstanceTo_ID(target.getM_AttributeSetInstance_ID()); + // From + ml.setM_Locator_ID(source.getM_Locator_ID()); + ml.setM_AttributeSetInstance_ID(source.getM_AttributeSetInstance_ID()); + + BigDecimal qtyMove = qty; + if (qtyMove.compareTo(source.getQtyOnHand()) > 0) + qtyMove = source.getQtyOnHand(); + ml.setMovementQty(qtyMove); + // + lines++; + ml.setLine(lines*10); + if (!ml.save()) + return 0; + + qty = qty.subtract(qtyMove); + if (qty.signum() <= 0) + break; + } // for all movements + + // Process + mh.processIt(MMovement.ACTION_Complete); + mh.save(); + + addLog(0, null, new BigDecimal(lines), "@M_Movement_ID@ " + mh.getDocumentNo() + " (" + + MRefList.get(getCtx(), MMovement.DOCSTATUS_AD_Reference_ID, + mh.getDocStatus(), get_TrxName()) + ")"); + + eliminateReservation(target); + return lines; + } // move + + /** + * Eliminate Reserved/Ordered + * @param target target Storage + */ + private void eliminateReservation(MStorage target) + { + // Negative Ordered / Reserved Qty + if (target.getQtyReserved().signum() != 0 || target.getQtyOrdered().signum() != 0) + { + int M_Locator_ID = target.getM_Locator_ID(); + MStorage storage0 = MStorage.get(getCtx(), M_Locator_ID, + target.getM_Product_ID(), 0, get_TrxName()); + if (storage0 == null) + { + MLocator defaultLoc = MLocator.getDefault(getCtx(), M_Locator_ID); + if (M_Locator_ID != defaultLoc.getM_Locator_ID()) + { + M_Locator_ID = defaultLoc.getM_Locator_ID(); + storage0 = MStorage.get(getCtx(), M_Locator_ID, + target.getM_Product_ID(), 0, get_TrxName()); + } + } + if (storage0 != null) + { + BigDecimal reserved = Env.ZERO; + BigDecimal ordered = Env.ZERO; + if (target.getQtyReserved().add(storage0.getQtyReserved()).signum() >= 0) + reserved = target.getQtyReserved(); // negative + if (target.getQtyOrdered().add(storage0.getQtyOrdered()).signum() >= 0) + ordered = target.getQtyOrdered(); // negative + // Eliminate Reservation + if (reserved.signum() != 0 || ordered.signum() != 0) + { + if (MStorage.add(getCtx(), target.getM_Warehouse_ID(), target.getM_Locator_ID(), + target.getM_Product_ID(), + target.getM_AttributeSetInstance_ID(), target.getM_AttributeSetInstance_ID(), + Env.ZERO, reserved.negate(), ordered.negate(), get_TrxName())) + { + if (MStorage.add(getCtx(), storage0.getM_Warehouse_ID(), storage0.getM_Locator_ID(), + storage0.getM_Product_ID(), + storage0.getM_AttributeSetInstance_ID(), storage0.getM_AttributeSetInstance_ID(), + Env.ZERO, reserved, ordered, get_TrxName())) + log.info("Reserved=" + reserved + ",Ordered=" + ordered); + else + log.warning("Failed Storage0 Update"); + } + else + log.warning("Failed Target Update"); + } + } + } + } // eliminateReservation + + /** + * Get Storage Sources + * @param M_Product_ID product + * @param M_Locator_ID locator + * @return sources + */ + private MStorage[] getSources (int M_Product_ID, int M_Locator_ID) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * " + + "FROM M_Storage s " + + "WHERE QtyOnHand > 0" + + " AND M_Product_ID=?" + // Empty ASI + + " AND (M_AttributeSetInstance_ID=0" + + " OR EXISTS (SELECT * FROM M_AttributeSetInstance asi " + + "WHERE s.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID" + + " AND asi.Description IS NULL) )" + // Stock in same Warehouse + + " AND EXISTS (SELECT * FROM M_Locator sl, M_Locator x " + + "WHERE s.M_Locator_ID=sl.M_Locator_ID" + + " AND x.M_Locator_ID=?" + + " AND sl.M_Warehouse_ID=x.M_Warehouse_ID) " + + "ORDER BY M_AttributeSetInstance_ID"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, M_Product_ID); + pstmt.setInt (2, M_Locator_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + list.add (new MStorage (getCtx(), rs, get_TrxName())); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + MStorage[] retValue = new MStorage[list.size()]; + list.toArray(retValue); + return retValue; + } // getSources + +} // StorageCleanup diff --git a/base/src/org/compiere/process/T_InventoryValue_Create.java b/base/src/org/compiere/process/T_InventoryValue_Create.java new file mode 100644 index 0000000000..abebacdf8d --- /dev/null +++ b/base/src/org/compiere/process/T_InventoryValue_Create.java @@ -0,0 +1,224 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + * Portions created by Carlos Ruiz are Copyright (C) 2005 QSS Ltda. + * Contributor(s): Carlos Ruiz (globalqss) + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.logging.*; + +import org.compiere.util.*; + +/** + * Title: Inventory Valuation Temporary Table + * + * @author Carlos Ruiz (globalqss) + * @version $Id: T_InventoryValue_Create.java,v 1.0 2005/09/21 20:29:00 globalqss Exp $ + */ +public class T_InventoryValue_Create extends SvrProcess +{ + + /** The Parameters */ + private int p_M_PriceList_Version_ID; + private Timestamp p_DateValue; + private int p_M_Warehouse_ID; + private int p_C_Currency_ID; + /** The Record */ + private int p_Record_ID = 0; + /** The Instance */ + private int p_PInstance_ID; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("M_PriceList_Version_ID")) + p_M_PriceList_Version_ID = para[i].getParameterAsInt(); + else if (name.equals("DateValue")) + p_DateValue = (Timestamp)para[i].getParameter(); + else if (name.equals("M_Warehouse_ID")) + p_M_Warehouse_ID = para[i].getParameterAsInt(); + else if (name.equals("C_Currency_ID")) + p_C_Currency_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_Record_ID = getRecord_ID(); + p_PInstance_ID = getAD_PInstance_ID(); + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt() throws Exception + { + String sqlupd; + String sqlins; + int cntu = 0; + int cnti = 0; + + log.info("Inventory Valuation Temporary Table"); + + // Clear + // v_ResultStr := 'ClearTable'; + // DELETE T_InventoryValue WHERE M_Warehouse_ID=p_M_Warehouse_ID; + // COMMIT; + + // Insert Products + sqlins = "INSERT INTO T_InventoryValue " + + "(AD_Client_ID,AD_Org_ID, AD_PInstance_ID, M_Warehouse_ID,M_Product_ID) " + + "SELECT AD_Client_ID,AD_Org_ID," + p_PInstance_ID + "," + p_M_Warehouse_ID + ",M_Product_ID " + + "FROM M_Product " + + "WHERE IsStocked='Y'"; + cnti = DB.executeUpdate(sqlins, get_TrxName()); + if (cnti == 0) { + return "@Created@ = 0"; + } + if (cnti < 0) { + raiseError("InsertStockedProducts:ERROR", sqlins); + } + + // Update Constants + // En Oracle SET DateValue = TRUNC(?) + 0.9993, equivale a sumar 23:59 a la fecha + p_DateValue.setHours(23); + p_DateValue.setMinutes(59); + p_DateValue.setSeconds(0); + sqlupd = "UPDATE T_InventoryValue " + + "SET DateValue = ?, " + + "M_PriceList_Version_ID = ? , " + + "C_Currency_ID = ? " + + "WHERE M_Warehouse_ID = ?"; + PreparedStatement pstmt = DB.prepareStatement(sqlupd, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE, get_TrxName()); + pstmt.setTimestamp(1, p_DateValue); + pstmt.setInt(2, p_M_PriceList_Version_ID); + pstmt.setInt(3, p_C_Currency_ID); + pstmt.setInt(4, p_M_Warehouse_ID); + cntu = pstmt.executeUpdate(); + if (cntu < 0) { + raiseError("UpdateConstants:ERROR", sqlupd); + } + + // Get current QtyOnHand + sqlupd = "UPDATE T_InventoryValue " + + "SET QtyOnHand = (SELECT SUM(QtyOnHand) FROM M_Storage s, M_Locator l " + + "WHERE T_InventoryValue.M_Product_ID=s.M_Product_ID " + + "AND l.M_Locator_ID=s.M_Locator_ID " + + "AND l.M_Warehouse_ID=T_InventoryValue.M_Warehouse_ID) " + + "WHERE T_InventoryValue.M_Warehouse_ID = " + p_M_Warehouse_ID; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + if (cntu < 0) { + raiseError("GetQtyOnHand:ERROR", sqlupd); + } + + // Adjust for Valuation Date + sqlupd = "UPDATE T_InventoryValue " + + "SET QtyOnHand = " + + "(SELECT T_InventoryValue.QtyOnHand - NVL(SUM(t.MovementQty), 0) " + + "FROM M_Transaction t, M_Locator l " + + "WHERE t.M_Product_ID=T_InventoryValue.M_Product_ID " + // + "AND t.M_AttributeSetInstance_ID=T_InventoryValue.M_AttributeSetInstance_ID " + + "AND t.MovementDate > T_InventoryValue.DateValue " + + "AND t.M_Locator_ID=l.M_Locator_ID " + + "AND l.M_Warehouse_ID=T_InventoryValue.M_Warehouse_ID) " + + "WHERE T_InventoryValue.M_Warehouse_ID = " + p_M_Warehouse_ID; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + if (cntu < 0) { + raiseError("AdjustQtyOnHand:ERROR", sqlupd); + } + + // Delete Records w/o OnHand Qty + sqlupd = "DELETE T_InventoryValue " + + "WHERE QtyOnHand=0 " + + "OR QtyOnHand IS NULL"; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + if (cntu < 0) { + raiseError("DeleteZeroQtyOnHand:ERROR", sqlupd); + } + + // Update Prices + sqlupd = "UPDATE T_InventoryValue " + + "SET PricePO = " + + "(SELECT currencyConvert (po.PriceList,po.C_Currency_ID,T_InventoryValue.C_Currency_ID,T_InventoryValue.DateValue, null, T_InventoryValue.AD_Client_ID, T_InventoryValue.AD_Org_ID) " + + "FROM M_Product_PO po WHERE po.M_Product_ID=T_InventoryValue.M_Product_ID " + + "AND po.IsCurrentVendor='Y' AND ROWNUM=1), " + + "PriceList = " + + "(SELECT currencyConvert(pp.PriceList,pl.C_Currency_ID,T_InventoryValue.C_Currency_ID,T_InventoryValue.DateValue, null, T_InventoryValue.AD_Client_ID, T_InventoryValue.AD_Org_ID) " + + "FROM M_PriceList pl, M_PriceList_Version plv, M_ProductPrice pp " + + "WHERE pp.M_Product_ID=T_InventoryValue.M_Product_ID AND pp.M_PriceList_Version_ID=T_InventoryValue.M_PriceList_Version_ID " + + "AND pp.M_PriceList_Version_ID=plv.M_PriceList_Version_ID " + + "AND plv.M_PriceList_ID=pl.M_PriceList_ID), " + + "PriceStd = " + + "(SELECT currencyConvert(pp.PriceStd,pl.C_Currency_ID,T_InventoryValue.C_Currency_ID,T_InventoryValue.DateValue, null, T_InventoryValue.AD_Client_ID, T_InventoryValue.AD_Org_ID) " + + "FROM M_PriceList pl, M_PriceList_Version plv, M_ProductPrice pp " + + "WHERE pp.M_Product_ID=T_InventoryValue.M_Product_ID AND pp.M_PriceList_Version_ID=T_InventoryValue.M_PriceList_Version_ID " + + "AND pp.M_PriceList_Version_ID=plv.M_PriceList_Version_ID " + + "AND plv.M_PriceList_ID=pl.M_PriceList_ID), " + + "PriceLimit = " + + "(SELECT currencyConvert(pp.PriceLimit,pl.C_Currency_ID,T_InventoryValue.C_Currency_ID,T_InventoryValue.DateValue, null, T_InventoryValue.AD_Client_ID, T_InventoryValue.AD_Org_ID) " + + "FROM M_PriceList pl, M_PriceList_Version plv, M_ProductPrice pp " + + "WHERE pp.M_Product_ID=T_InventoryValue.M_Product_ID AND pp.M_PriceList_Version_ID=T_InventoryValue.M_PriceList_Version_ID " + + "AND pp.M_PriceList_Version_ID=plv.M_PriceList_Version_ID " + + "AND plv.M_PriceList_ID=pl.M_PriceList_ID), " + + "CostStandard = " + + "(SELECT currencyConvert(pc.CurrentCostPrice,acs.C_Currency_ID,T_InventoryValue.C_Currency_ID,T_InventoryValue.DateValue, null, T_InventoryValue.AD_Client_ID, T_InventoryValue.AD_Org_ID) " + + "FROM AD_ClientInfo ci, C_AcctSchema acs, M_Product_Costing pc " + + "WHERE T_InventoryValue.AD_Client_ID=ci.AD_Client_ID AND ci.C_AcctSchema1_ID=acs.C_AcctSchema_ID " + + "AND acs.C_AcctSchema_ID=pc.C_AcctSchema_ID " + + "AND T_InventoryValue.M_Product_ID=pc.M_Product_ID) " + + "WHERE T_InventoryValue.M_Warehouse_ID = " + p_M_Warehouse_ID; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + if (cntu < 0) { + raiseError("GetPrices:ERROR", sqlupd); + } + + // Update Values + sqlupd = "UPDATE T_InventoryValue " + + "SET PricePOAmt = QtyOnHand * PricePO, " + + "PriceListAmt = QtyOnHand * PriceList, " + + "PriceStdAmt = QtyOnHand * PriceStd, " + + "PriceLimitAmt = QtyOnHand * PriceLimit, " + + "CostStandardAmt = QtyOnHand * CostStandard " + + "WHERE M_Warehouse_ID = " + p_M_Warehouse_ID; + cntu = DB.executeUpdate(sqlupd, get_TrxName()); + if (cntu < 0) { + raiseError("UpdateValue:ERROR", sqlupd); + } + + DB.commit(true, get_TrxName()); + return "@Created@ = " + cntu; + } // doIt + + private void raiseError(String string, String sql) throws Exception { + DB.rollback(false, get_TrxName()); + String msg = string; + ValueNamePair pp = CLogger.retrieveError(); + if (pp != null) + msg = pp.getName() + " - "; + msg += sql; + throw new AdempiereUserError (msg); + } + +} // T_InventoryValue_Create diff --git a/base/src/org/compiere/process/TabCopy.java b/base/src/org/compiere/process/TabCopy.java new file mode 100644 index 0000000000..163d909797 --- /dev/null +++ b/base/src/org/compiere/process/TabCopy.java @@ -0,0 +1,88 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Copy Tab Fields + * + * @author Jorg Janke + * @version $Id: TabCopy.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class TabCopy extends SvrProcess +{ + /** Tab To */ + private int p_AD_TabTo_ID = 0; + /** Tab From */ + private int p_AD_TabFrom_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Tab_ID")) + p_AD_TabFrom_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_AD_TabTo_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info("To AD_Tab_ID=" + p_AD_TabTo_ID + ", From=" + p_AD_TabFrom_ID); + MTab from = new MTab (getCtx(), p_AD_TabFrom_ID, get_TrxName()); + if (from.get_ID() == 0) + throw new AdempiereUserError("@NotFound@ (from->) @AD_Tab_ID@"); + MTab to = new MTab (getCtx(), p_AD_TabTo_ID, get_TrxName()); + if (to.get_ID() == 0) + throw new AdempiereUserError("@NotFound@ (to<-) @AD_Tab_ID@"); + if (from.getAD_Table_ID() != to.getAD_Table_ID()) + throw new AdempiereUserError("@Error@ @AD_Table_ID@"); + + int count = 0; + MField[] oldFields = from.getFields(false, get_TrxName()); + for (int i = 0; i < oldFields.length; i++) + { + MField oldField = oldFields[i]; + MField newField = new MField (to, oldField); + if (newField.save()) + count++; + else + throw new AdempiereUserError("@Error@ @AD_Field_ID@"); + } + + return "@Copied@ #" + count; + } // doIt + +} // TabCopy diff --git a/base/src/org/compiere/process/TabCreateFields.java b/base/src/org/compiere/process/TabCreateFields.java new file mode 100644 index 0000000000..2aa71dfe83 --- /dev/null +++ b/base/src/org/compiere/process/TabCreateFields.java @@ -0,0 +1,110 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Create Field from Table Column. + * (which do not exist in the Tab yet) + * + * @author Jorg Janke + * @version $Id: TabCreateFields.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class TabCreateFields extends SvrProcess +{ + /** Tab NUmber */ + private int p_AD_Tab_ID= 0; + + /** + * prepare + */ + protected void prepare () + { + p_AD_Tab_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + MTab tab = new MTab (getCtx(), p_AD_Tab_ID, get_TrxName()); + if (p_AD_Tab_ID == 0 || tab == null || tab.get_ID() == 0) + throw new AdempiereSystemError("@NotFound@: @AD_Tab_ID@ " + p_AD_Tab_ID); + log.info(tab.toString()); + // + int count = 0; + String sql = "SELECT * FROM AD_Column c " + + "WHERE NOT EXISTS (SELECT * FROM AD_Field f " + + "WHERE c.AD_Column_ID=f.AD_Column_ID" + + " AND c.AD_Table_ID=?" // #1 + + " AND f.AD_Tab_ID=?)" // #2 + + " AND AD_Table_ID=?" // #3 + + " AND NOT (Name LIKE 'Created%' OR Name LIKE 'Updated%')" + + " AND IsActive='Y' " + + "ORDER BY Name"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, tab.getAD_Table_ID()); + pstmt.setInt (2, tab.getAD_Tab_ID()); + pstmt.setInt (3, tab.getAD_Table_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MColumn column = new MColumn (getCtx(), rs, get_TrxName()); + // + MField field = new MField (tab); + field.setColumn(column); + if (column.isKey()) + field.setIsDisplayed(false); + if (field.save()) + { + addLog(0, null, null, column.getName()); + count++; + } + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return "@Created@ #" + count; + } // doIt + +} // TabCreateFields diff --git a/base/src/org/compiere/process/TableCreateColumns.java b/base/src/org/compiere/process/TableCreateColumns.java new file mode 100644 index 0000000000..d2e29ee0ac --- /dev/null +++ b/base/src/org/compiere/process/TableCreateColumns.java @@ -0,0 +1,343 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.logging.*; +import org.compiere.db.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Create Columns of Table or View + * + * @author Jorg Janke + * @version $Id: TableCreateColumns.java,v 1.3 2006/07/30 00:51:01 jjanke Exp $ + */ +public class TableCreateColumns extends SvrProcess +{ + /** Entity Type */ + private String p_EntityType = "C"; // ENTITYTYPE_Customization + /** Table */ + private int p_AD_Table_ID = 0; + /** CheckAllDBTables */ + private boolean p_AllTables = false; + + /** Column Count */ + private int m_count = 0; + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("EntityType")) + p_EntityType = (String)para[i].getParameter(); + else if (name.equals("AllTables")) + p_AllTables = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_AD_Table_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + if (p_AD_Table_ID == 0) + throw new AdempiereSystemError("@NotFound@ @AD_Table_ID@ " + p_AD_Table_ID); + log.info("EntityType=" + p_EntityType + + ", AllTables=" + p_AllTables + + ", AD_Table_ID=" + p_AD_Table_ID); + // + Connection conn = DB.getConnectionRO(); + AdempiereDatabase db = DB.getDatabase(); + DatabaseMetaData md = conn.getMetaData(); + String catalog = db.getCatalog(); + String schema = db.getSchema(); + + if (p_AllTables) + addTable (md, catalog, schema); + else + { + MTable table = new MTable (getCtx(), p_AD_Table_ID, get_TrxName()); + if (table == null || table.get_ID() == 0) + throw new AdempiereSystemError("@NotFound@ @AD_Table_ID@ " + p_AD_Table_ID); + log.info(table.getTableName() + ", EntityType=" + p_EntityType); + String tableName = table.getTableName(); + if (DB.isOracle()) + tableName = tableName.toUpperCase(); + // globalqss 2005-10-24 + if (DB.isPostgreSQL()) + tableName = tableName.toLowerCase(); + // end globalqss 2005-10-24 + ResultSet rs = md.getColumns(catalog, schema, tableName, null); + addTableColumn(rs, table); + } + + return "#" + m_count; + } // doIt + + /** + * Add Table + * @param md meta data + * @param catalog catalog + * @param schema schema + * @throws Exception + */ + private void addTable (DatabaseMetaData md, String catalog, String schema) throws Exception + { + // globalqss 2005-10-25 + // ResultSet rs = md.getTables(catalog, schema, null, null); + ResultSet rs; + if (DB.isPostgreSQL()) + rs = md.getTables(catalog, schema, null, new String [] {"TABLE", "VIEW"}); + else + rs = md.getTables(catalog, schema, null, null); + // end globalqss 2005-10-25 + while (rs.next()) + { + String tableName = rs.getString("TABLE_NAME"); + String tableType = rs.getString("TABLE_TYPE"); + + // Try to find + MTable table = MTable.get(getCtx(), tableName); + // Create new ? + if (table == null) + { + String tn = tableName.toUpperCase(); + if (tn.startsWith("T_SELECTION") // temp table + || tn.endsWith("_VT") // print trl views + || tn.endsWith("_V") // views + || tn.endsWith("_V1") // views + || tn.startsWith("A_A") // asset tables not yet + || tn.startsWith("A_D") // asset tables not yet + || tn.indexOf("$") != -1 // oracle system tables + || tn.indexOf("EXPLAIN") != -1 // explain plan + ) + { + log.fine("Ignored: " + tableName + " - " + tableType); + continue; + } + // + log.info(tableName + " - " + tableType); + + // Create New + table = new MTable(getCtx(), 0, get_TrxName()); + table.setEntityType (p_EntityType); + table.setName (tableName); + table.setTableName (tableName); + table.setIsView("VIEW".equals(tableType)); + if (!table.save()) + continue; + } + // Check Columns + if (DB.isOracle()) + tableName = tableName.toUpperCase(); + // globalqss 2005-10-24 + if (DB.isPostgreSQL()) + tableName = tableName.toLowerCase(); + // end globalqss 2005-10-24 + ResultSet rsC = md.getColumns(catalog, schema, tableName, null); + addTableColumn(rsC, table); + } + } // addTable + + + /** + * Add Table Column + * @param rs result set with meta data + * @param table table + * @throws Exception + */ + private void addTableColumn (ResultSet rs, MTable table) throws Exception + { + String tableName = table.getTableName (); + if (DB.isOracle ()) + tableName = tableName.toUpperCase (); + // globalqss 2005-10-24 + if (DB.isPostgreSQL()) + tableName = tableName.toLowerCase(); + // end globalqss 2005-10-24 + while (rs.next ()) + { + String tn = rs.getString ("TABLE_NAME"); + if (!tableName.equalsIgnoreCase (tn)) + continue; + String columnName = rs.getString ("COLUMN_NAME"); + MColumn column = table.getColumn (columnName); + if (column != null) + continue; + int dataType = rs.getInt ("DATA_TYPE"); + String typeName = rs.getString ("TYPE_NAME"); + String nullable = rs.getString ("IS_NULLABLE"); + int size = rs.getInt ("COLUMN_SIZE"); + int digits = rs.getInt ("DECIMAL_DIGITS"); + // + log.config (columnName + " - DataType=" + dataType + " " + typeName + + ", Nullable=" + nullable + ", Size=" + size + ", Digits=" + + digits); + // + column = new MColumn (table); + column.setEntityType (p_EntityType); + // + M_Element element = M_Element.get (getCtx (), columnName); + if (element == null) + { + element = new M_Element (getCtx (), columnName, p_EntityType, + get_TrxName ()); + element.save (); + } + column.setColumnName (element.getColumnName ()); + column.setName (element.getName ()); + column.setDescription (element.getDescription ()); + column.setHelp (element.getHelp ()); + column.setAD_Element_ID (element.getAD_Element_ID ()); + // + column.setIsMandatory ("NO".equals (nullable)); + // Key + if (columnName.equalsIgnoreCase (tableName + "_ID")) + { + column.setIsKey (true); + column.setAD_Reference_ID (DisplayType.ID); + column.setIsUpdateable(false); + } + // Account + else if (columnName.toUpperCase ().indexOf ("ACCT") != -1 + && size == 10) + column.setAD_Reference_ID (DisplayType.Account); + // Account + else if (columnName.equalsIgnoreCase ("C_Location_ID")) + column.setAD_Reference_ID (DisplayType.Location); + // Product Attribute + else if (columnName.equalsIgnoreCase ("M_AttributeSetInstance_ID")) + column.setAD_Reference_ID (DisplayType.PAttribute); + // SalesRep_ID (=User) + else if (columnName.equalsIgnoreCase ("SalesRep_ID")) + { + column.setAD_Reference_ID (DisplayType.Table); + column.setAD_Reference_Value_ID (190); + } + // ID + else if (columnName.endsWith ("_ID")) + column.setAD_Reference_ID (DisplayType.TableDir); + // Date + else if (dataType == Types.DATE || dataType == Types.TIME + || dataType == Types.TIMESTAMP + // || columnName.toUpperCase().indexOf("DATE") != -1 + || columnName.equalsIgnoreCase ("Created") + || columnName.equalsIgnoreCase ("Updated")) + column.setAD_Reference_ID (DisplayType.DateTime); + // CreatedBy/UpdatedBy (=User) + else if (columnName.equalsIgnoreCase ("CreatedBy") + || columnName.equalsIgnoreCase ("UpdatedBy")) + { + column.setAD_Reference_ID (DisplayType.Table); + column.setAD_Reference_Value_ID (110); + column.setIsUpdateable(false); + } + // Entity Type + else if (columnName.equalsIgnoreCase ("EntityType")) + { + column.setAD_Reference_ID (DisplayType.Table); + column.setAD_Reference_Value_ID (389); + } + // CLOB + else if (dataType == Types.CLOB) + column.setAD_Reference_ID (DisplayType.TextLong); + // BLOB + else if (dataType == Types.BLOB) + column.setAD_Reference_ID (DisplayType.Binary); + // Amount + else if (columnName.toUpperCase ().indexOf ("AMT") != -1) + column.setAD_Reference_ID (DisplayType.Amount); + // Qty + else if (columnName.toUpperCase ().indexOf ("QTY") != -1) + column.setAD_Reference_ID (DisplayType.Quantity); + // Boolean + else if (size == 1 + && (columnName.toUpperCase ().startsWith ("IS") || dataType == Types.CHAR)) + column.setAD_Reference_ID (DisplayType.YesNo); + // List + else if (size < 4 && dataType == Types.CHAR) + column.setAD_Reference_ID (DisplayType.List); + // Name, DocumentNo + else if (columnName.equalsIgnoreCase ("Name") + || columnName.equals ("DocumentNo")) + { + column.setAD_Reference_ID (DisplayType.String); + column.setIsIdentifier (true); + column.setSeqNo (1); + } + // String, Text + else if (dataType == Types.CHAR || dataType == Types.VARCHAR + || typeName.startsWith ("NVAR") + || typeName.startsWith ("NCHAR")) + { + if (typeName.startsWith("N")) // MultiByte + size /= 2; + if (size > 255) + column.setAD_Reference_ID (DisplayType.Text); + else + column.setAD_Reference_ID (DisplayType.String); + } + // Number + else if (dataType == Types.INTEGER || dataType == Types.SMALLINT + || dataType == Types.DECIMAL || dataType == Types.NUMERIC) + { + if (size == 10) + column.setAD_Reference_ID (DisplayType.Integer); + else + column.setAD_Reference_ID (DisplayType.Number); + } + // ?? + else + column.setAD_Reference_ID (DisplayType.String); + + column.setFieldLength (size); + if (column.isUpdateable() + && (table.isView() + || columnName.equalsIgnoreCase("AD_Client_ID") + || columnName.equalsIgnoreCase("AD_Org_ID") + || columnName.toUpperCase().startsWith("CREATED") + || columnName.toUpperCase().equals("UPDATED") )) + column.setIsUpdateable(false); + + // Done + if (column.save ()) + { + addLog (0, null, null, table.getTableName() + "." + column.getColumnName()); + m_count++; + } + } // while columns + + } // addTableColumn + + +} // TableCreateColumns diff --git a/base/src/org/compiere/process/TaxDeclarationCreate.java b/base/src/org/compiere/process/TaxDeclarationCreate.java new file mode 100644 index 0000000000..41856e9cde --- /dev/null +++ b/base/src/org/compiere/process/TaxDeclarationCreate.java @@ -0,0 +1,204 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.sql.*; +import java.util.logging.*; + +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Create Tax Declaration + * + * @author Jorg Janke + * @version $Id: TaxDeclarationCreate.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class TaxDeclarationCreate extends SvrProcess +{ + /** Tax Declaration */ + private int p_C_TaxDeclaration_ID = 0; + /** Delete Old Lines */ + private boolean p_DeleteOld = true; + + /** Tax Declaration */ + private MTaxDeclaration m_td = null; + /** TDLines */ + private int m_noLines = 0; + /** TDAccts */ + private int m_noAccts = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("DeleteOld")) + p_DeleteOld = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_C_TaxDeclaration_ID = getRecord_ID(); + } // prepare + + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("C_TaxDeclaration_ID=" + p_C_TaxDeclaration_ID); + m_td = new MTaxDeclaration (getCtx(), p_C_TaxDeclaration_ID, get_TrxName()); + if (m_td.get_ID() == 0) + throw new AdempiereSystemError("@NotDound@ @C_TaxDeclaration_ID@ = " + p_C_TaxDeclaration_ID); + + if (p_DeleteOld) + { + // Delete old + String sql = "DELETE C_TaxDeclarationLine WHERE C_TaxDeclaration_ID=?"; + int no = DB.executeUpdate(sql, p_C_TaxDeclaration_ID, false, get_TrxName()); + if (no != 0) + log.config("Delete Line #" + no); + sql = "DELETE C_TaxDeclarationAcct WHERE C_TaxDeclaration_ID=?"; + no = DB.executeUpdate(sql, p_C_TaxDeclaration_ID, false, get_TrxName()); + if (no != 0) + log.config("Delete Acct #" + no); + } + + // Get Invoices + String sql = "SELECT * FROM C_Invoice i " + + "WHERE TRUNC(i.DateInvoiced) >= ? AND TRUNC(i.DateInvoiced) <= ? " + + " AND Processed='Y'" + + " AND NOT EXISTS (SELECT * FROM C_TaxDeclarationLine tdl " + + "WHERE i.C_Invoice_ID=tdl.C_Invoice_ID)"; + PreparedStatement pstmt = null; + int noInvoices = 0; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setTimestamp(1, m_td.getDateFrom()); + pstmt.setTimestamp(2, m_td.getDateTo()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + create (new MInvoice (getCtx(), rs, null)); // no lock + noInvoices++; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + return "@C_Invoice_ID@ #" + noInvoices + + " (" + m_noLines + ", " + m_noAccts + ")"; + } // doIt + + /** + * Create Data + * @param invoice invoice + */ + private void create (MInvoice invoice) + { + /** Lines ** + MInvoiceLine[] lines = invoice.getLines(); + for (int i = 0; i < lines.length; i++) + { + MInvoiceLine line = lines[i]; + if (line.isDescription()) + continue; + // + MTaxDeclarationLine tdl = new MTaxDeclarationLine (m_td, invoice, line); + tdl.setLine((m_noLines+1) * 10); + if (tdl.save()) + m_noLines++; + } + /** **/ + + /** Invoice Tax **/ + MInvoiceTax[] taxes = invoice.getTaxes(false); + for (int i = 0; i < taxes.length; i++) + { + MInvoiceTax tLine = taxes[i]; + // + MTaxDeclarationLine tdl = new MTaxDeclarationLine (m_td, invoice, tLine); + tdl.setLine((m_noLines+1) * 10); + if (tdl.save()) + m_noLines++; + } + /** **/ + + /** Acct **/ + String sql = "SELECT * FROM Fact_Acct WHERE AD_Table_ID=? AND Record_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, MInvoice.Table_ID); + pstmt.setInt (2, invoice.getC_Invoice_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MFactAcct fact = new MFactAcct(getCtx(), rs, null); // no lock + MTaxDeclarationAcct tda = new MTaxDeclarationAcct (m_td, fact); + tda.setLine((m_noAccts+1) * 10); + if (tda.save()) + m_noAccts++; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + /** **/ + } // invoice + +} // TaxDeclarationCreate diff --git a/base/src/org/compiere/process/TransactionXRef.java b/base/src/org/compiere/process/TransactionXRef.java new file mode 100644 index 0000000000..53b0fc3835 --- /dev/null +++ b/base/src/org/compiere/process/TransactionXRef.java @@ -0,0 +1,139 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Material Transaction Cross Reference + * + * @author Jorg Janke + * @version $Id: TransactionXRef.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class TransactionXRef extends SvrProcess +{ + private int p_Search_InOut_ID = 0; + private int p_Search_Order_ID = 0; + private int p_Search_Invoice_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("Search_InOut_ID")) + p_Search_InOut_ID = para[i].getParameterAsInt(); + else if (name.equals("Search_Order_ID")) + p_Search_Order_ID = para[i].getParameterAsInt(); + else if (name.equals("Search_Invoice_ID")) + p_Search_Invoice_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Process it + * @return info + * @throws Exception if error + */ + protected String doIt () throws Exception + { + log.info("M_InOut_ID=" + p_Search_InOut_ID + ", C_Order_ID=" + p_Search_Order_ID + + ", C_Invoice_ID=" + p_Search_Invoice_ID); + // + if (p_Search_InOut_ID != 0) + insertTrx( + "SELECT NVL(ma.M_AttributeSetInstance_ID,iol.M_AttributeSetInstance_ID) " + + "FROM M_InOutLine iol" + + " LEFT OUTER JOIN M_InOutLineMA ma ON (iol.M_InOutLine_ID=ma.M_InOutLine_ID) " + + "WHERE M_InOut_ID=" + p_Search_InOut_ID + ); + else if (p_Search_Order_ID != 0) + insertTrx( + "SELECT NVL(ma.M_AttributeSetInstance_ID,iol.M_AttributeSetInstance_ID) " + + "FROM M_InOutLine iol" + + " LEFT OUTER JOIN M_InOutLineMA ma ON (iol.M_InOutLine_ID=ma.M_InOutLine_ID) " + + " INNER JOIN M_InOut io ON (iol.M_InOut_ID=io.M_InOut_ID)" + + "WHERE io.C_Order_ID=" + p_Search_Order_ID + ); + else if (p_Search_Invoice_ID != 0) + insertTrx( + "SELECT NVL(ma.M_AttributeSetInstance_ID,iol.M_AttributeSetInstance_ID) " + + "FROM M_InOutLine iol" + + " LEFT OUTER JOIN M_InOutLineMA ma ON (iol.M_InOutLine_ID=ma.M_InOutLine_ID) " + + " INNER JOIN C_InvoiceLine il ON (iol.M_InOutLine_ID=il.M_InOutLine_ID) " + + "WHERE il.C_Invoice_ID=" + p_Search_Invoice_ID + ); + else + throw new AdempiereUserError("Select one Parameter"); + // + return ""; + } // doIt + + /** + * Get Trx + * @param sqlSubSelect sql + */ + private void insertTrx (String sqlSubSelect) + { + String sql = "INSERT INTO T_Transaction " + + "(AD_PInstance_ID, M_Transaction_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created,CreatedBy, Updated,UpdatedBy," + + " MovementType, M_Locator_ID, M_Product_ID, M_AttributeSetInstance_ID," + + " MovementDate, MovementQty," + + " M_InOutLine_ID, M_InOut_ID," + + " M_MovementLine_ID, M_Movement_ID," + + " M_InventoryLine_ID, M_Inventory_ID, " + + " C_ProjectIssue_ID, C_Project_ID, " + + " M_ProductionLine_ID, M_Production_ID, " + + " Search_Order_ID, Search_Invoice_ID, Search_InOut_ID) " + // Data + + "SELECT " + getAD_PInstance_ID() + ", M_Transaction_ID," + + " AD_Client_ID, AD_Org_ID, IsActive, Created,CreatedBy, Updated,UpdatedBy," + + " MovementType, M_Locator_ID, M_Product_ID, M_AttributeSetInstance_ID," + + " MovementDate, MovementQty," + + " M_InOutLine_ID, M_InOut_ID, " + + " M_MovementLine_ID, M_Movement_ID," + + " M_InventoryLine_ID, M_Inventory_ID, " + + " C_ProjectIssue_ID, C_Project_ID, " + + " M_ProductionLine_ID, M_Production_ID, " + // Parameter + + p_Search_Order_ID + ", " + p_Search_Invoice_ID + "," + p_Search_InOut_ID + " " + // + + "FROM M_Transaction_v " + + "WHERE M_AttributeSetInstance_ID > 0 AND M_AttributeSetInstance_ID IN (" + + sqlSubSelect + + ") ORDER BY M_Transaction_ID"; + // + int no = DB.executeUpdate(sql, get_TrxName()); + log.fine(sql); + log.config("#" + no); + + // Multi-Level + + } // insertTrx + +} // TransactionXRef diff --git a/base/src/org/compiere/process/TranslationDocSync.java b/base/src/org/compiere/process/TranslationDocSync.java new file mode 100644 index 0000000000..54ca3631ff --- /dev/null +++ b/base/src/org/compiere/process/TranslationDocSync.java @@ -0,0 +1,133 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Document Translation Sync + * + * @author Jorg Janke + * @version $Id: TranslationDocSync.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class TranslationDocSync extends SvrProcess +{ + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message + * @throws Exception + */ + protected String doIt() throws Exception + { + MClient client = MClient.get(getCtx()); + if (client.isMultiLingualDocument()) + throw new AdempiereUserError("@AD_Client_ID@: @IsMultiLingualDocument@"); + // + log.info("" + client); + String sql = "SELECT * FROM AD_Table " + + "WHERE TableName LIKE '%_Trl' AND TableName NOT LIKE 'AD%' " + + "ORDER BY TableName"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + processTable (new MTable(getCtx(), rs, null), client.getAD_Client_ID()); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + return "OK"; + } // doIt + + /** + * Process Translation Table + * @param table table + */ + private void processTable (MTable table, int AD_Client_ID) + { + StringBuffer sql = new StringBuffer(); + MColumn[] columns = table.getColumns(false); + for (int i = 0; i < columns.length; i++) + { + MColumn column = columns[i]; + if (column.getAD_Reference_ID() == DisplayType.String + || column.getAD_Reference_ID() == DisplayType.Text) + { + String columnName = column.getColumnName(); + if (sql.length() != 0) + sql.append(","); + sql.append(columnName); + } + } + String baseTable = table.getTableName(); + baseTable = baseTable.substring(0, baseTable.length()-4); + + log.config(baseTable + ": " + sql); + String columnNames = sql.toString(); + + sql = new StringBuffer(); + sql.append("UPDATE ").append(table.getTableName()).append(" t SET (") + .append(columnNames).append(") = (SELECT ").append(columnNames) + .append(" FROM ").append(baseTable).append(" b WHERE t.") + .append(baseTable).append("_ID=b.").append(baseTable).append("_ID) WHERE AD_Client_ID=") + .append(AD_Client_ID); + + int no = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog(0, null, new BigDecimal(no), baseTable); + } // processTable + +} // TranslationDocSync diff --git a/base/src/org/compiere/process/TreeMaintenance.java b/base/src/org/compiere/process/TreeMaintenance.java new file mode 100644 index 0000000000..64d95aad1f --- /dev/null +++ b/base/src/org/compiere/process/TreeMaintenance.java @@ -0,0 +1,174 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import java.math.*; +import java.sql.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Tree Maintenance + * + * @author Jorg Janke + * @version $Id: TreeMaintenance.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + */ +public class TreeMaintenance extends SvrProcess +{ + /** Tree */ + private int m_AD_Tree_ID; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + m_AD_Tree_ID = getRecord_ID(); // from Window + } // prepare + + /** + * Perrform process. + * @return Message (clear text) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info("doIt - AD_Tree_ID=" + m_AD_Tree_ID); + if (m_AD_Tree_ID == 0) + throw new IllegalArgumentException("Tree_ID = 0"); + MTree tree = new MTree (getCtx(), m_AD_Tree_ID, get_TrxName()); + if (tree == null || tree.getAD_Tree_ID() == 0) + throw new IllegalArgumentException("No Tree -" + tree); + // + if (MTree.TREETYPE_BoM.equals(tree.getTreeType())) + return "BOM Trees not implemented"; + return verifyTree(tree); + } // doIt + + /** + * Verify Tree + * @param tree tree + */ + private String verifyTree (MTree_Base tree) + { + String nodeTableName = tree.getNodeTableName(); + String sourceTableName = tree.getSourceTableName(true); + String sourceTableKey = sourceTableName + "_ID"; + int AD_Client_ID = tree.getAD_Client_ID(); + int C_Element_ID = 0; + if (MTree.TREETYPE_ElementValue.equals(tree.getTreeType())) + { + String sql = "SELECT C_Element_ID FROM C_Element " + + "WHERE AD_Tree_ID=" + tree.getAD_Tree_ID(); + C_Element_ID = DB.getSQLValue(null, sql); + if (C_Element_ID <= 0) + throw new IllegalStateException("No Account Element found"); + } + + // Delete unused + StringBuffer sql = new StringBuffer(); + sql.append("DELETE ").append(nodeTableName) + .append(" WHERE AD_Tree_ID=").append(tree.getAD_Tree_ID()) + .append(" AND Node_ID NOT IN (SELECT ").append(sourceTableKey) + .append(" FROM ").append(sourceTableName) + .append(" WHERE AD_Client_ID=").append(AD_Client_ID); + if (C_Element_ID > 0) + sql.append(" AND C_Element_ID=").append(C_Element_ID); + sql.append(")"); + log.finer(sql.toString()); + // + int deletes = DB.executeUpdate(sql.toString(), get_TrxName()); + addLog(0,null, new BigDecimal(deletes), tree.getName()+ " Deleted"); + if (!tree.isAllNodes()) + return tree.getName() + " OK"; + + // Insert new + int inserts = 0; + sql = new StringBuffer(); + sql.append("SELECT ").append(sourceTableKey) + .append(" FROM ").append(sourceTableName) + .append(" WHERE AD_Client_ID=").append(AD_Client_ID); + if (C_Element_ID > 0) + sql.append(" AND C_Element_ID=").append(C_Element_ID); + sql.append(" AND ").append(sourceTableKey) + .append(" NOT IN (SELECT Node_ID FROM ").append(nodeTableName) + .append(" WHERE AD_Tree_ID=").append(tree.getAD_Tree_ID()).append(")"); + log.finer(sql.toString()); + // + boolean ok = true; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql.toString(), get_TrxName()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + int Node_ID = rs.getInt(1); + PO node = null; + if (nodeTableName.equals("AD_TreeNode")) + node = new MTree_Node(tree, Node_ID); + else if (nodeTableName.equals("AD_TreeNodeBP")) + node = new MTree_NodeBP(tree, Node_ID); + else if (nodeTableName.equals("AD_TreeNodePR")) + node = new MTree_NodePR(tree, Node_ID); +// else if (nodeTableName.equals("AD_TreeNodeMM")) +// node = new MTree_NodeMM(tree, Node_ID); + // + if (node == null) + log.log(Level.SEVERE, "verifyTree - no Model for " + nodeTableName); + else + { + if (node.save()) + inserts++; + else + log.log(Level.SEVERE, "verifyTree - Could not add to " + tree + " Node_ID=" + Node_ID); + } + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "verifyTree", e); + ok = false; + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + addLog(0,null, new BigDecimal(inserts), tree.getName()+ " Inserted"); + return tree.getName() + (ok ? " OK" : " Error"); + } // verifyTree + +} // TreeMaintenence diff --git a/base/src/org/compiere/process/UserPassword.java b/base/src/org/compiere/process/UserPassword.java new file mode 100644 index 0000000000..5cfe05a752 --- /dev/null +++ b/base/src/org/compiere/process/UserPassword.java @@ -0,0 +1,131 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Reset Password + * + * @author Jorg Janke + * @version $Id: UserPassword.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class UserPassword extends SvrProcess +{ + private int p_AD_User_ID = -1; + private String p_OldPassword = null; + private String p_NewPassword = null; + private String p_NewEMail = null; + private String p_NewEMailUser = null; + private String p_NewEMailUserPW = null; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_User_ID")) + p_AD_User_ID = para[i].getParameterAsInt(); + else if (name.equals("OldPassword")) + p_OldPassword = (String)para[i].getParameter(); + else if (name.equals("NewPassword")) + p_NewPassword = (String)para[i].getParameter(); + else if (name.equals("NewEMail")) + p_NewEMail = (String)para[i].getParameter(); + else if (name.equals("NewEMailUser")) + p_NewEMailUser = (String)para[i].getParameter(); + else if (name.equals("NewEMailUserPW")) + p_NewEMailUserPW = (String)para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + /** + * Perrform process. + * @return Message + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + log.info ("AD_User_ID=" + p_AD_User_ID + " from " + getAD_User_ID()); + + MUser user = MUser.get(getCtx(), p_AD_User_ID); + MUser operator = MUser.get(getCtx(), getAD_User_ID()); + log.fine("User=" + user + ", Operator=" + operator); + + + + // Do we need a password ? + if (Util.isEmpty(p_OldPassword)) // Password required + { + if (p_AD_User_ID == 0 // change of System + || p_AD_User_ID == 100 // change of SuperUser + || !operator.isAdministrator()) + throw new IllegalArgumentException("@OldPasswordMandatory@"); + } + + // is entered Password correct ? + else if (!p_OldPassword.equals(user.getPassword())) + throw new IllegalArgumentException("@OldPasswordNoMatch@"); + + // Change Super User + if (p_AD_User_ID == 0) + { + String sql = "UPDATE AD_User SET Updated=SysDate, UpdatedBy=" + getAD_User_ID(); + if (!Util.isEmpty(p_NewPassword)) + sql += ", Password=" + DB.TO_STRING(p_NewPassword); + if (!Util.isEmpty(p_NewEMail)) + sql += ", Email=" + DB.TO_STRING(p_NewEMail); + if (!Util.isEmpty(p_NewEMailUser)) + sql += ", EmailUser=" + DB.TO_STRING(p_NewEMailUser); + if (!Util.isEmpty(p_NewEMailUserPW)) + sql += ", EmailUserPW=" + DB.TO_STRING(p_NewEMailUserPW); + sql += " WHERE AD_User_ID=0"; + if (DB.executeUpdate(sql, get_TrxName()) == 1) + return "OK"; + else + return "@Error@"; + } + else + { + if (!Util.isEmpty(p_NewPassword)) + user.setPassword(p_NewPassword); + if (!Util.isEmpty(p_NewEMail)) + user.setEMail(p_NewEMail); + if (!Util.isEmpty(p_NewEMailUser)) + user.setEMailUser(p_NewEMailUser); + if (!Util.isEmpty(p_NewEMailUserPW)) + user.setEMailUserPW(p_NewEMailUserPW); + // + if (user.save()) + return "OK"; + else + return "@Error@"; + } + } // doIt + +} // UserPassword + diff --git a/base/src/org/compiere/process/WindowCopy.java b/base/src/org/compiere/process/WindowCopy.java new file mode 100644 index 0000000000..21df902bb0 --- /dev/null +++ b/base/src/org/compiere/process/WindowCopy.java @@ -0,0 +1,100 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Copy all Tabs of a Window + * + * @author Jorg Janke + * @version $Id: WindowCopy.java,v 1.3 2006/07/30 00:51:02 jjanke Exp $ + */ +public class WindowCopy extends SvrProcess +{ + /** Window To */ + private int p_AD_WindowTo_ID = 0; + /** Window From */ + private int p_AD_WindowFrom_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Window_ID")) + p_AD_WindowFrom_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + p_AD_WindowTo_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info("doIt - To AD_Window_ID=" + p_AD_WindowTo_ID + ", From=" + p_AD_WindowFrom_ID); + MWindow from = new MWindow (getCtx(), p_AD_WindowFrom_ID, get_TrxName()); + if (from.get_ID() == 0) + throw new AdempiereUserError("@NotFound@ (from->) @AD_Window_ID@"); + MWindow to = new MWindow (getCtx(), p_AD_WindowTo_ID, get_TrxName()); + if (to.get_ID() == 0) + throw new AdempiereUserError("@NotFound@ (to<-) @AD_Window_ID@"); + + int tabCount = 0; + int fieldCount = 0; + MTab[] oldTabs = from.getTabs(false, get_TrxName()); + for (int i = 0; i < oldTabs.length; i++) + { + MTab oldTab = oldTabs[i]; + MTab newTab = new MTab (to, oldTab); + if (newTab.save()) + { + tabCount++; + // Copy Fields + MField[] oldFields = oldTab.getFields(false, get_TrxName()); + for (int j = 0; j < oldFields.length; j++) + { + MField oldField = oldFields[j]; + MField newField = new MField (newTab, oldField); + if (newField.save()) + fieldCount++; + else + throw new AdempiereUserError("@Error@ @AD_Field_ID@"); + } + } + else + throw new AdempiereUserError("@Error@ @AD_Tab_ID@"); + } + + return "@Copied@ #" + tabCount + "/" + fieldCount; + } // doIt + +} // WindowCopy diff --git a/base/src/org/compiere/process/YearCreatePeriods.java b/base/src/org/compiere/process/YearCreatePeriods.java new file mode 100644 index 0000000000..c2db054886 --- /dev/null +++ b/base/src/org/compiere/process/YearCreatePeriods.java @@ -0,0 +1,58 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.process; + +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Create Periods of year + * + * @author Jorg Janke + * @version $Id: YearCreatePeriods.java,v 1.2 2006/07/30 00:51:01 jjanke Exp $ + */ +public class YearCreatePeriods extends SvrProcess +{ + private int p_C_Year_ID = 0; + + /** + * Prepare + */ + protected void prepare () + { + p_C_Year_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt () + throws Exception + { + MYear year = new MYear (getCtx(), p_C_Year_ID, get_TrxName()); + if (p_C_Year_ID == 0 || year.get_ID() != p_C_Year_ID) + throw new AdempiereUserError ("@NotFound@: @C_Year_ID@ - " + p_C_Year_ID); + log.info(year.toString()); + // + if (year.createStdPeriods(null)) + return "@OK@"; + return "@Error@"; + } // doIt + +} // YearCreatePeriods diff --git a/base/src/org/compiere/report/FinBalance.java b/base/src/org/compiere/report/FinBalance.java new file mode 100644 index 0000000000..ecbdac7c43 --- /dev/null +++ b/base/src/org/compiere/report/FinBalance.java @@ -0,0 +1,230 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report; + +import java.math.*; +import java.util.*; + +import org.compiere.model.*; +import org.compiere.process.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Financial Balance Maintenance Engine + * + * @author Jorg Janke + * @version $Id: FinBalance.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class FinBalance extends SvrProcess +{ + /** + * Financial Report Constructor + */ + public FinBalance() + { + super(); + log.info(" "); + } // FinBalance + + /** Logger */ + protected static CLogger s_log = CLogger.getCLogger (FinBalance.class); + + private int p_C_AcctSchema_ID = 0; + private boolean p_IsRecreate = false; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + // Parameter + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_AcctSchema_ID")) + p_C_AcctSchema_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("IsRecreate")) + p_IsRecreate = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + } // prepare + + + /** + * Perform process. + * @return Message to be translated + * @throws Exception + */ + protected String doIt() throws java.lang.Exception + { + log.fine("C_AcctSchema_ID=" + p_C_AcctSchema_ID + + ", IsRecreate=" + p_IsRecreate); + if (p_C_AcctSchema_ID != 0) + updateBalance(p_C_AcctSchema_ID, p_IsRecreate); + else + updateBalanceClient(getCtx(), getAD_Client_ID(), p_IsRecreate); + return ""; + } // doIt + + /** + * Delete Balances + * @param C_AcctSchema_ID accounting schema 0 for all + * @return Message to be translated + */ + public static String deleteBalance (int C_AcctSchema_ID) + { + StringBuffer sql = new StringBuffer ("DELETE FROM Fact_Acct_Balance WHERE "); + if (C_AcctSchema_ID != 0) + sql.append ("C_AcctSchema_ID=").append (C_AcctSchema_ID); + // + int no = DB.executeUpdate(sql.toString(), null); // out of trx + String msg = "@Deleted@=" + no; + s_log.fine("C_AcctSchema_ID=" + C_AcctSchema_ID + " #=" + no); + // + return msg; + } // deleteBalance + + /** + * Update / Create Balances. + * Called from FinReport, FactAcctReset (indirect) + * @param C_AcctSchema_ID accounting schema + * @param deleteFirst delete (all) balances first + * @return Message to be translated + */ + public static String updateBalance (int C_AcctSchema_ID, boolean deleteFirst) + { + s_log.info("C_AcctSchema_ID=" + C_AcctSchema_ID + " - DeleteFirst=" + deleteFirst); + long start = System.currentTimeMillis(); + + if (deleteFirst) + { + int no = DB.executeUpdate("DELETE Fact_Acct_Balance WHERE C_AcctSchema_ID=?", + C_AcctSchema_ID, null); + s_log.fine("Deleted=" + no); + } + + + // Update existing + String sql = "UPDATE Fact_Acct_Balance ab " + + "SET (AmtAcctDr, AmtAcctCr, Qty)= " + + "(SELECT COALESCE(SUM(AmtAcctDr),0), COALESCE(SUM(AmtAcctCr),0), COALESCE(SUM(Qty),0) " + + "FROM Fact_Acct a " + + "WHERE a.AD_Client_ID=ab.AD_Client_ID AND a.AD_Org_ID=ab.AD_Org_ID" + + " AND a.C_AcctSchema_ID=ab.C_AcctSchema_ID AND TRUNC(a.DateAcct)=TRUNC(ab.DateAcct)" + + " AND a.Account_ID=ab.Account_ID AND a.PostingType=ab.PostingType" + + " AND COALESCE(a.M_Product_ID,0)=COALESCE(ab.M_Product_ID,0) AND COALESCE(a.C_BPartner_ID,0)=COALESCE(ab.C_BPartner_ID,0)" + + " AND COALESCE(a.C_Project_ID,0)=COALESCE(ab.C_Project_ID,0) AND COALESCE(a.AD_OrgTrx_ID,0)=COALESCE(ab.AD_OrgTrx_ID,0)" + + " AND COALESCE(a.C_SalesRegion_ID,0)=COALESCE(ab.C_SalesRegion_ID,0) AND COALESCE(a.C_Activity_ID,0)=COALESCE(ab.C_Activity_ID,0)" + + " AND COALESCE(a.C_Campaign_ID,0)=COALESCE(ab.C_Campaign_ID,0) AND COALESCE(a.C_LocTo_ID,0)=COALESCE(ab.C_LocTo_ID,0) AND COALESCE(a.C_LocFrom_ID,0)=COALESCE(ab.C_LocFrom_ID,0)" + + " AND COALESCE(a.User1_ID,0)=COALESCE(ab.User1_ID,0) AND COALESCE(a.User2_ID,0)=COALESCE(ab.User2_ID,0) AND COALESCE(a.GL_Budget_ID,0)=COALESCE(ab.GL_Budget_ID,0) " + + "GROUP BY AD_Client_ID,AD_Org_ID, C_AcctSchema_ID, TRUNC(DateAcct)," + + " Account_ID, PostingType, M_Product_ID, C_BPartner_ID," + + " C_Project_ID, AD_OrgTrx_ID, C_SalesRegion_ID, C_Activity_ID," + + " C_Campaign_ID, C_LocTo_ID, C_LocFrom_ID, User1_ID, User2_ID, GL_Budget_ID) " + + "WHERE C_AcctSchema_ID=" + C_AcctSchema_ID + + " AND EXISTS (SELECT * FROM Fact_Acct a " + + "WHERE a.AD_Client_ID=ab.AD_Client_ID AND a.AD_Org_ID=ab.AD_Org_ID" + + " AND a.C_AcctSchema_ID=ab.C_AcctSchema_ID AND TRUNC(a.DateAcct)=TRUNC(ab.DateAcct)" + + " AND a.Account_ID=ab.Account_ID AND a.PostingType=ab.PostingType" + + " AND COALESCE(a.M_Product_ID,0)=COALESCE(ab.M_Product_ID,0) AND COALESCE(a.C_BPartner_ID,0)=COALESCE(ab.C_BPartner_ID,0)" + + " AND COALESCE(a.C_Project_ID,0)=COALESCE(ab.C_Project_ID,0) AND COALESCE(a.AD_OrgTrx_ID,0)=COALESCE(ab.AD_OrgTrx_ID,0)" + + " AND COALESCE(a.C_SalesRegion_ID,0)=COALESCE(ab.C_SalesRegion_ID,0) AND COALESCE(a.C_Activity_ID,0)=COALESCE(ab.C_Activity_ID,0)" + + " AND COALESCE(a.C_Campaign_ID,0)=COALESCE(ab.C_Campaign_ID,0) AND COALESCE(a.C_LocTo_ID,0)=COALESCE(ab.C_LocTo_ID,0) AND COALESCE(a.C_LocFrom_ID,0)=COALESCE(ab.C_LocFrom_ID,0)" + + " AND COALESCE(a.User1_ID,0)=COALESCE(ab.User1_ID,0) AND COALESCE(a.User2_ID,0)=COALESCE(ab.User2_ID,0) AND COALESCE(a.GL_Budget_ID,0)=COALESCE(ab.GL_Budget_ID,0) " + + "GROUP BY AD_Client_ID,AD_Org_ID," + + " C_AcctSchema_ID, TRUNC(DateAcct)," + + " Account_ID, PostingType," + + " M_Product_ID, C_BPartner_ID," + + " C_Project_ID, AD_OrgTrx_ID," + + " C_SalesRegion_ID, C_Activity_ID," + + " C_Campaign_ID, C_LocTo_ID, C_LocFrom_ID," + + " User1_ID, User2_ID, GL_Budget_ID)"; + if (!deleteFirst) + { + int no = DB.executeUpdate(sql, null); + s_log.fine("Updates=" + no); + } + + /** Insert **/ + sql = "INSERT INTO Fact_Acct_Balance ab " + + "(AD_Client_ID, AD_Org_ID, C_AcctSchema_ID, DateAcct," + + " Account_ID, PostingType, M_Product_ID, C_BPartner_ID," + + " C_Project_ID, AD_OrgTrx_ID, C_SalesRegion_ID,C_Activity_ID," + + " C_Campaign_ID, C_LocTo_ID, C_LocFrom_ID, User1_ID, User2_ID, GL_Budget_ID," + + " AmtAcctDr, AmtAcctCr, Qty) " + // + + "SELECT AD_Client_ID, AD_Org_ID, C_AcctSchema_ID, TRUNC(DateAcct)," + + " Account_ID, PostingType, M_Product_ID, C_BPartner_ID," + + " C_Project_ID, AD_OrgTrx_ID, C_SalesRegion_ID,C_Activity_ID," + + " C_Campaign_ID, C_LocTo_ID, C_LocFrom_ID, User1_ID, User2_ID, GL_Budget_ID," + + " COALESCE(SUM(AmtAcctDr),0), COALESCE(SUM(AmtAcctCr),0), COALESCE(SUM(Qty),0) " + + "FROM Fact_Acct a " + + "WHERE C_AcctSchema_ID=" + C_AcctSchema_ID; + if (!deleteFirst) + sql += " AND NOT EXISTS (SELECT * " + + "FROM Fact_Acct_Balance x " + + "WHERE a.AD_Client_ID=x.AD_Client_ID AND a.AD_Org_ID=x.AD_Org_ID" + + " AND a.C_AcctSchema_ID=x.C_AcctSchema_ID AND TRUNC(a.DateAcct)=TRUNC(x.DateAcct)" + + " AND a.Account_ID=x.Account_ID AND a.PostingType=x.PostingType" + + " AND COALESCE(a.M_Product_ID,0)=COALESCE(x.M_Product_ID,0) AND COALESCE(a.C_BPartner_ID,0)=COALESCE(x.C_BPartner_ID,0)" + + " AND COALESCE(a.C_Project_ID,0)=COALESCE(x.C_Project_ID,0) AND COALESCE(a.AD_OrgTrx_ID,0)=COALESCE(x.AD_OrgTrx_ID,0)" + + " AND COALESCE(a.C_SalesRegion_ID,0)=COALESCE(x.C_SalesRegion_ID,0) AND COALESCE(a.C_Activity_ID,0)=COALESCE(x.C_Activity_ID,0)" + + " AND COALESCE(a.C_Campaign_ID,0)=COALESCE(x.C_Campaign_ID,0) AND COALESCE(a.C_LocTo_ID,0)=COALESCE(x.C_LocTo_ID,0) AND COALESCE(a.C_LocFrom_ID,0)=COALESCE(x.C_LocFrom_ID,0)" + + " AND COALESCE(a.User1_ID,0)=COALESCE(x.User1_ID,0) AND COALESCE(a.User2_ID,0)=COALESCE(x.User2_ID,0) AND COALESCE(a.GL_Budget_ID,0)=COALESCE(x.GL_Budget_ID,0) )"; + sql += " GROUP BY AD_Client_ID,AD_Org_ID, C_AcctSchema_ID, TRUNC(DateAcct)," + + " Account_ID, PostingType, M_Product_ID, C_BPartner_ID," + + " C_Project_ID, AD_OrgTrx_ID, C_SalesRegion_ID, C_Activity_ID," + + " C_Campaign_ID, C_LocTo_ID, C_LocFrom_ID, User1_ID, User2_ID, GL_Budget_ID"; + int no = DB.executeUpdate(sql, null); + s_log.fine("Inserts=" + no); + + start = System.currentTimeMillis() - start; + s_log.info((start/1000) + " sec"); + return ""; + } // updateBalance + + /** + * Update Balance of Client + * @param ctx context + * @param AD_Client_ID client + * @param deleteFirst delete first + * @return error or "" + */ + public static String updateBalanceClient (Properties ctx, int AD_Client_ID, boolean deleteFirst) + { + MAcctSchema[] ass = MAcctSchema.getClientAcctSchema(ctx, AD_Client_ID); + for (int i = 0; i < ass.length; i++) + updateBalance(ass[i].getC_AcctSchema_ID(), deleteFirst); + return ""; + } // updateBalanceClient + + + /************************************************************************** + * Test + * @param args ignored + */ + public static void main(String[] args) + { + FinBalance finBalance1 = new FinBalance(); + } // main + +} // FinBalance diff --git a/base/src/org/compiere/report/FinReport.java b/base/src/org/compiere/report/FinReport.java new file mode 100644 index 0000000000..04bab9ed0f --- /dev/null +++ b/base/src/org/compiere/report/FinReport.java @@ -0,0 +1,1221 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.print.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Financial Report Engine + * + * @author Jorg Janke + * @version $Id: FinReport.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class FinReport extends SvrProcess +{ + /** Period Parameter */ + private int p_C_Period_ID = 0; + /** Org Parameter */ + private int p_Org_ID = 0; + /** BPartner Parameter */ + private int p_C_BPartner_ID = 0; + /** Product Parameter */ + private int p_M_Product_ID = 0; + /** Project Parameter */ + private int p_C_Project_ID = 0; + /** Activity Parameter */ + private int p_C_Activity_ID = 0; + /** SalesRegion Parameter */ + private int p_C_SalesRegion_ID = 0; + /** Campaign Parameter */ + private int p_C_Campaign_ID = 0; + /** Update Balances Parameter */ + private boolean p_UpdateBalances = true; + /** Details before Lines */ + private boolean p_DetailsSourceFirst = false; + /** Hierarchy */ + private int p_PA_Hierarchy_ID = 0; + + /** Start Time */ + private long m_start = System.currentTimeMillis(); + + /** Report Definition */ + private MReport m_report = null; + /** Periods in Calendar */ + private FinReportPeriod[] m_periods = null; + /** Index of m_C_Period_ID in m_periods **/ + private int m_reportPeriod = -1; + /** Parameter Where Clause */ + private StringBuffer m_parameterWhere = new StringBuffer(); + /** The Report Columns */ + private MReportColumn[] m_columns; + /** The Report Lines */ + private MReportLine[] m_lines; + + + /** + * Prepare - e.g., get Parameters. + */ + 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) + ; + else if (name.equals("C_Period_ID")) + p_C_Period_ID = para[i].getParameterAsInt(); + else if (name.equals("PA_Hierarchy_ID")) + p_PA_Hierarchy_ID = para[i].getParameterAsInt(); + else if (name.equals("Org_ID")) + p_Org_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("M_Product_ID")) + p_M_Product_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_Project_ID")) + p_C_Project_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_Activity_ID")) + p_C_Activity_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_SalesRegion_ID")) + p_C_SalesRegion_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_Campaign_ID")) + p_C_Campaign_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("UpdateBalances")) + p_UpdateBalances = "Y".equals(para[i].getParameter()); + else if (name.equals("DetailsSourceFirst")) + p_DetailsSourceFirst = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + // Optional Org + if (p_Org_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_Organization, p_Org_ID)); + // Optional BPartner + if (p_C_BPartner_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_BPartner, p_C_BPartner_ID)); + // Optional Product + if (p_M_Product_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_Product, p_M_Product_ID)); + // Optional Project + if (p_C_Project_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_Project, p_C_Project_ID)); + // Optional Activity + if (p_C_Activity_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_Activity, p_C_Activity_ID)); + // Optional Campaign + if (p_C_Campaign_ID != 0) + m_parameterWhere.append(" AND C_Campaign_ID=").append(p_C_Campaign_ID); + // m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + // MAcctSchemaElement.ELEMENTTYPE_Campaign, p_C_Campaign_ID)); + // Optional Sales Region + if (p_C_SalesRegion_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_SalesRegion, p_C_SalesRegion_ID)); + + // Load Report Definition + m_report = new MReport (getCtx(), getRecord_ID(), null); + sb.append(" - ").append(m_report); + // + setPeriods(); + sb.append(" - C_Period_ID=").append(p_C_Period_ID) + .append(" - ").append(m_parameterWhere); + // + log.info(sb.toString()); + // m_report.list(); + } // prepare + + /** + * Set Periods + */ + private void setPeriods() + { + log.info("C_Calendar_ID=" + m_report.getC_Calendar_ID()); + Timestamp today = TimeUtil.getDay(System.currentTimeMillis()); + ArrayList list = new ArrayList(); + + String sql = "SELECT p.C_Period_ID, p.Name, p.StartDate, p.EndDate, MIN(p1.StartDate) " + + "FROM C_Period p " + + " INNER JOIN C_Year y ON (p.C_Year_ID=y.C_Year_ID)," + + " C_Period p1 " + + "WHERE y.C_Calendar_ID=?" + // globalqss - cruiz - Bug [ 1577712 ] Financial Period Bug + + " AND p.IsActive='Y'" + + " AND p.PeriodType='S' " + + " AND p1.C_Year_ID=y.C_Year_ID AND p1.PeriodType='S' " + + "GROUP BY p.C_Period_ID, p.Name, p.StartDate, p.EndDate " + + "ORDER BY p.StartDate"; + + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, m_report.getC_Calendar_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + FinReportPeriod frp = new FinReportPeriod (rs.getInt(1), rs.getString(2), + rs.getTimestamp(3), rs.getTimestamp(4), rs.getTimestamp(5)); + list.add(frp); + if (p_C_Period_ID == 0 && frp.inPeriod(today)) + p_C_Period_ID = frp.getC_Period_ID(); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + // convert to Array + m_periods = new FinReportPeriod[list.size()]; + list.toArray(m_periods); + // today after latest period + if (p_C_Period_ID == 0) + { + m_reportPeriod = m_periods.length - 1; + p_C_Period_ID = m_periods[m_reportPeriod].getC_Period_ID (); + } + } // setPeriods + + + /************************************************************************** + * Perform process. + * @return Message to be translated + * @throws Exception + */ + protected String doIt() throws Exception + { + log.info("AD_PInstance_ID=" + getAD_PInstance_ID()); + // ** Create Temporary and empty Report Lines from PA_ReportLine + // - AD_PInstance_ID, PA_ReportLine_ID, 0, 0 + int PA_ReportLineSet_ID = m_report.getLineSet().getPA_ReportLineSet_ID(); + StringBuffer sql = new StringBuffer ("INSERT INTO T_Report " + + "(AD_PInstance_ID, PA_ReportLine_ID, Record_ID,Fact_Acct_ID, SeqNo,LevelNo, Name,Description) " + + "SELECT ").append(getAD_PInstance_ID()).append(", PA_ReportLine_ID, 0,0, SeqNo,0, Name,Description " + + "FROM PA_ReportLine " + + "WHERE IsActive='Y' AND PA_ReportLineSet_ID=").append(PA_ReportLineSet_ID); + + int no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("Report Lines = " + no); + + // Update AcctSchema Balances + if (p_UpdateBalances) + FinBalance.updateBalance (m_report.getC_AcctSchema_ID(), false); + + // ** Get Data ** Segment Values + m_columns = m_report.getColumnSet().getColumns(); + if (m_columns.length == 0) + throw new AdempiereUserError("@No@ @PA_ReportColumn_ID@"); + m_lines = m_report.getLineSet().getLiness(); + if (m_lines.length == 0) + throw new AdempiereUserError("@No@ @PA_ReportLine_ID@"); + + // for all lines + for (int line = 0; line < m_lines.length; line++) + { + // Line Segment Value (i.e. not calculation) + if (m_lines[line].isLineTypeSegmentValue()) + insertLine (line); + } // for all lines + + insertLineDetail(); + doCalculations(); + + deleteUnprintedLines(); + + // Create Report + if (Ini.isClient()) + getProcessInfo().setTransientObject (getPrintFormat()); + else + getProcessInfo().setSerializableObject(getPrintFormat()); + + log.fine((System.currentTimeMillis() - m_start) + " ms"); + return ""; + } // doIt + + + /************************************************************************** + * For all columns (in a line) with relative period access + * @param line line + */ + private void insertLine (int line) + { + log.info("" + m_lines[line]); + + // No source lines - Headings + if (m_lines[line] == null || m_lines[line].getSources().length == 0) + { + log.warning ("No Source lines: " + m_lines[line]); + return; + } + + StringBuffer update = new StringBuffer(); + // for all columns + for (int col = 0; col < m_columns.length; col++) + { + // Ignore calculation columns + if (m_columns[col].isColumnTypeCalculation()) + continue; + StringBuffer info = new StringBuffer(); + info.append("Line=").append(line).append(",Col=").append(col); + + // SELECT SUM() + StringBuffer select = new StringBuffer ("SELECT "); + if (m_lines[line].getAmountType() != null) // line amount type overwrites column + { + String sql = m_lines[line].getSelectClause (true); + select.append (sql); + info.append(": LineAmtType=").append(m_lines[line].getAmountType()); + } + else if (m_columns[col].getAmountType() != null) + { + String sql = m_columns[col].getSelectClause (true); + select.append (sql); + info.append(": ColumnAmtType=").append(m_columns[col].getAmountType()); + } + else + { + log.warning("No Amount Type in line: " + m_lines[line] + " or column: " + m_columns[col]); + continue; + } + + // Get Period/Date info + select.append(" FROM Fact_Acct_Balance WHERE DateAcct "); + BigDecimal relativeOffset = null; // current + if (m_columns[col].isColumnTypeRelativePeriod()) + relativeOffset = m_columns[col].getRelativePeriod(); + FinReportPeriod frp = getPeriod (relativeOffset); + if (m_lines[line].getAmountType() != null) // line amount type overwrites column + { + info.append(" - LineDateAcct="); + if (m_lines[line].isPeriod()) + { + String sql = frp.getPeriodWhere(); + info.append("Period"); + select.append(sql); + } + else if (m_lines[line].isYear()) + { + String sql = frp.getYearWhere(); + info.append("Year"); + select.append(sql); + } + else if (m_lines[line].isTotal()) + { + String sql = frp.getTotalWhere(); + info.append("Total"); + select.append(sql); + } + else + { + log.log(Level.SEVERE, "No valid Line AmountType"); + select.append("=0"); // valid sql + } + } + else if (m_columns[col].getAmountType() != null) + { + info.append(" - ColumnDateAcct="); + if (m_columns[col].isPeriod()) + { + String sql = frp.getPeriodWhere(); + info.append("Period"); + select.append(sql); + } + else if (m_columns[col].isYear()) + { + String sql = frp.getYearWhere(); + info.append("Year"); + select.append(sql); + } + else if (m_columns[col].isTotal()) + { + String sql = frp.getTotalWhere(); + info.append("Total"); + select.append(sql); + } + else + { + log.log(Level.SEVERE, "No valid Column AmountType"); + select.append("=0"); // valid sql + } + } + + // Line Where + String s = m_lines[line].getWhereClause(p_PA_Hierarchy_ID); // (sources, posting type) + if (s != null && s.length() > 0) + select.append(" AND ").append(s); + + // Report Where + s = m_report.getWhereClause(); + if (s != null && s.length() > 0) + select.append(" AND ").append(s); + + // PostingType + if (!m_lines[line].isPostingType()) // only if not defined on line + { + String PostingType = m_columns[col].getPostingType(); + if (PostingType != null && PostingType.length() > 0) + select.append(" AND PostingType='").append(PostingType).append("'"); + } + + if (m_columns[col].isColumnTypeSegmentValue()) + { + String elementType = m_columns[col].getElementType(); + if (MReportColumn.ELEMENTTYPE_Organization.equals(elementType)) + select.append(" AND AD_Org_ID=").append(m_columns[col].getOrg_ID()); + else if (MReportColumn.ELEMENTTYPE_BPartner.equals(elementType)) + select.append(" AND C_BPartner_ID=").append(m_columns[col].getC_BPartner_ID()); + else if (MReportColumn.ELEMENTTYPE_Product.equals(elementType)) + select.append(" AND M_Product_ID=").append(m_columns[col].getM_Product_ID()); + else if (MReportColumn.ELEMENTTYPE_Project.equals(elementType)) + select.append(" AND C_Project_ID=").append(m_columns[col].getC_Project_ID()); + else if (MReportColumn.ELEMENTTYPE_Activity.equals(elementType)) + select.append(" AND C_Activity_ID=").append(m_columns[col].getC_Activity_ID()); + else if (MReportColumn.ELEMENTTYPE_Campaign.equals(elementType)) + select.append(" AND C_Campaign_ID=").append(m_columns[col].getC_Campaign_ID()); + else if (MReportColumn.ELEMENTTYPE_LocationFrom.equals(elementType)) + select.append(" AND C_LocFrom_ID=").append(m_columns[col].getC_Location_ID()); + else if (MReportColumn.ELEMENTTYPE_LocationTo.equals(elementType)) + select.append(" AND C_LocTo_ID=").append(m_columns[col].getC_Location_ID()); + else if (MReportColumn.ELEMENTTYPE_OrgTrx.equals(elementType)) + select.append(" AND AD_OrgTrx_ID=").append(m_columns[col].getOrg_ID()); + else if (MReportColumn.ELEMENTTYPE_SalesRegion.equals(elementType)) + select.append(" AND C_SalesRegion_ID=").append(m_columns[col].getC_SalesRegion_ID()); + else if (MReportColumn.ELEMENTTYPE_Account.equals(elementType)) + select.append(" AND Account_ID=").append(m_columns[col].getC_ElementValue_ID()); + else if (MReportColumn.ELEMENTTYPE_UserList1.equals(elementType)) + select.append(" AND User1_ID=").append(m_columns[col].getC_ElementValue_ID()); + else if (MReportColumn.ELEMENTTYPE_UserList2.equals(elementType)) + select.append(" AND User2_ID=").append(m_columns[col].getC_ElementValue_ID()); + else if (MReportColumn.ELEMENTTYPE_UserElement1.equals(elementType)) + select.append(" AND UserElement1_ID=").append(m_columns[col].getC_ElementValue_ID()); + else if (MReportColumn.ELEMENTTYPE_UserElement2.equals(elementType)) + select.append(" AND UserElement2_ID=").append(m_columns[col].getC_ElementValue_ID()); + } + + // Parameter Where + select.append(m_parameterWhere); + log.finest("Line=" + line + ",Col=" + line + ": " + select); + + // Update SET portion + if (update.length() > 0) + update.append(", "); + update.append("Col_").append(col) + .append(" = (").append(select).append(")"); + // + log.finest(info.toString()); + } + // Update Line Values + if (update.length() > 0) + { + update.insert (0, "UPDATE T_Report SET "); + update.append(" WHERE AD_PInstance_ID=").append(getAD_PInstance_ID()) + .append(" AND PA_ReportLine_ID=").append(m_lines[line].getPA_ReportLine_ID()) + .append(" AND ABS(LevelNo)<2"); // 0=Line 1=Acct + int no = DB.executeUpdate(update.toString(), get_TrxName()); + if (no != 1) + log.log(Level.SEVERE, "#=" + no + " for " + update); + log.finest(update.toString()); + } + } // insertLine + + + /************************************************************************** + * Line + Column calculation + */ + private void doCalculations() + { + // for all lines *************************************************** + for (int line = 0; line < m_lines.length; line++) + { + if (!m_lines[line].isLineTypeCalculation ()) + continue; + + int oper_1 = m_lines[line].getOper_1_ID(); + int oper_2 = m_lines[line].getOper_2_ID(); + + log.fine("Line " + line + " = #" + oper_1 + " " + + m_lines[line].getCalculationType() + " #" + oper_2); + + // Adding + if (m_lines[line].isCalculationTypeAdd() + || m_lines[line].isCalculationTypeRange()) + { + // Reverse range + if (oper_1 > oper_2) + { + int temp = oper_1; + oper_1 = oper_2; + oper_2 = temp; + } + StringBuffer sb = new StringBuffer ("UPDATE T_Report SET ("); + for (int col = 0; col < m_columns.length; col++) + { + if (col > 0) + sb.append(","); + sb.append ("Col_").append (col); + } + sb.append(") = (SELECT "); + for (int col = 0; col < m_columns.length; col++) + { + if (col > 0) + sb.append(","); + sb.append ("COALESCE(SUM(Col_").append (col).append("),0)"); + } + sb.append(" FROM T_Report WHERE AD_PInstance_ID=").append(getAD_PInstance_ID()) + .append(" AND PA_ReportLine_ID IN ("); + if (m_lines[line].isCalculationTypeAdd()) + sb.append(oper_1).append(",").append(oper_2); + else + sb.append(getLineIDs (oper_1, oper_2)); // list of columns to add up + sb.append(") AND ABS(LevelNo)<1) " // 0=Line 1=Acct + + "WHERE AD_PInstance_ID=").append(getAD_PInstance_ID()) + .append(" AND PA_ReportLine_ID=").append(m_lines[line].getPA_ReportLine_ID()) + .append(" AND ABS(LevelNo)<1"); // not trx + int no = DB.executeUpdate(sb.toString(), get_TrxName()); + if (no != 1) + log.log(Level.SEVERE, "(+) #=" + no + " for " + m_lines[line] + " - " + sb.toString()); + else + { + log.fine("(+) Line=" + line + " - " + m_lines[line]); + log.finest ("(+) " + sb.toString ()); + } + } + else // No Add (subtract, percent) + { + // Step 1 - get First Value or 0 in there + StringBuffer sb = new StringBuffer ("UPDATE T_Report SET ("); + for (int col = 0; col < m_columns.length; col++) + { + if (col > 0) + sb.append(","); + sb.append ("Col_").append (col); + } + sb.append(") = (SELECT "); + for (int col = 0; col < m_columns.length; col++) + { + if (col > 0) + sb.append(","); + sb.append ("COALESCE(r2.Col_").append (col).append(",0)"); + } + sb.append(" FROM T_Report r2 WHERE r2.AD_PInstance_ID=").append(getAD_PInstance_ID()) + .append(" AND r2.PA_ReportLine_ID=").append(oper_1) + .append(" AND r2.Record_ID=0 AND r2.Fact_Acct_ID=0) " + // + + "WHERE AD_PInstance_ID=").append(getAD_PInstance_ID()) + .append(" AND PA_ReportLine_ID=").append(m_lines[line].getPA_ReportLine_ID()) + .append(" AND ABS(LevelNo)<1"); // 0=Line 1=Acct + int no = DB.executeUpdate(sb.toString(), get_TrxName()); + if (no != 1) + { + log.severe ("(x) #=" + no + " for " + m_lines[line] + " - " + sb.toString ()); + continue; + } + + // Step 2 - do Calculation with Second Value + sb = new StringBuffer ("UPDATE T_Report r1 SET ("); + for (int col = 0; col < m_columns.length; col++) + { + if (col > 0) + sb.append(","); + sb.append ("Col_").append (col); + } + sb.append(") = (SELECT "); + for (int col = 0; col < m_columns.length; col++) + { + if (col > 0) + sb.append(","); + sb.append ("COALESCE(r1.Col_").append (col).append(",0)"); + // fix bug [ 1563664 ] Errors in values shown in Financial Reports + // Carlos Ruiz - globalqss + if (m_lines[line].isCalculationTypeSubtract()) { + sb.append("-"); + // Solution, for subtraction replace the null with 0, instead of 0.000000001 + sb.append ("COALESCE(r2.Col_").append (col).append(",0)"); + } else { + // Solution, for division don't replace the null, convert 0 to null (avoid ORA-01476) + sb.append("/"); + sb.append ("DECODE (r2.Col_").append (col).append(", 0, NULL, r2.Col_").append (col).append(")"); + } + // end fix bug [ 1563664 ] + if (m_lines[line].isCalculationTypePercent()) + sb.append(" *100"); + } + sb.append(" FROM T_Report r2 WHERE r2.AD_PInstance_ID=").append(getAD_PInstance_ID()) + .append(" AND r2.PA_ReportLine_ID=").append(oper_2) + .append(" AND r2.Record_ID=0 AND r2.Fact_Acct_ID=0) " + // + + "WHERE AD_PInstance_ID=").append(getAD_PInstance_ID()) + .append(" AND PA_ReportLine_ID=").append(m_lines[line].getPA_ReportLine_ID()) + .append(" AND ABS(LevelNo)<1"); // 0=Line 1=Acct + no = DB.executeUpdate(sb.toString(), get_TrxName()); + if (no != 1) + log.severe ("(x) #=" + no + " for " + m_lines[line] + " - " + sb.toString ()); + else + { + log.fine("(x) Line=" + line + " - " + m_lines[line]); + log.finest (sb.toString()); + } + } + } // for all lines + + + // for all columns *********************************************** + for (int col = 0; col < m_columns.length; col++) + { + // Only Calculations + if (!m_columns[col].isColumnTypeCalculation ()) + continue; + + StringBuffer sb = new StringBuffer ("UPDATE T_Report SET "); + // Column to set + sb.append ("Col_").append (col).append("="); + // First Operand + int ii_1 = getColumnIndex(m_columns[col].getOper_1_ID()); + if (ii_1 < 0) + { + log.log(Level.SEVERE, "Column Index for Operator 1 not found - " + m_columns[col]); + continue; + } + // Second Operand + int ii_2 = getColumnIndex(m_columns[col].getOper_2_ID()); + if (ii_2 < 0) + { + log.log(Level.SEVERE, "Column Index for Operator 2 not found - " + m_columns[col]); + continue; + } + log.fine("Column " + col + " = #" + ii_1 + " " + + m_columns[col].getCalculationType() + " #" + ii_2); + // Reverse Range + if (ii_1 > ii_2 && m_columns[col].isCalculationTypeRange()) + { + log.fine("Swap operands from " + ii_1 + " op " + ii_2); + int temp = ii_1; + ii_1 = ii_2; + ii_2 = temp; + } + + // + + if (m_columns[col].isCalculationTypeAdd()) + sb.append ("COALESCE(Col_").append (ii_1).append(",0)") + .append("+") + .append ("COALESCE(Col_").append (ii_2).append(",0)"); + // - + else if (m_columns[col].isCalculationTypeSubtract()) + sb.append ("COALESCE(Col_").append (ii_1).append(",0)") + .append("-") + .append ("COALESCE(Col_").append (ii_2).append(",0)"); + // / + if (m_columns[col].isCalculationTypePercent()) + sb.append ("CASE WHEN COALESCE(Col_").append(ii_2) + .append(",0)=0 THEN NULL ELSE ") + .append("COALESCE(Col_").append (ii_1).append(",0)") + .append("/") + .append ("Col_").append (ii_2) + .append("*100 END"); // Zero Divide + // Range + else if (m_columns[col].isCalculationTypeRange()) + { + sb.append ("COALESCE(Col_").append (ii_1).append(",0)"); + for (int ii = ii_1+1; ii <= ii_2; ii++) + sb.append("+COALESCE(Col_").append (ii).append(",0)"); + } + // + sb.append(" WHERE AD_PInstance_ID=").append(getAD_PInstance_ID()) + .append(" AND ABS(LevelNo)<2"); // 0=Line 1=Acct + int no = DB.executeUpdate(sb.toString(), get_TrxName()); + if (no < 1) + log.severe ("#=" + no + " for " + m_columns[col] + + " - " + sb.toString()); + else + { + log.fine("Col=" + col + " - " + m_columns[col]); + log.finest (sb.toString ()); + } + } // for all columns + + } // doCalculations + + /** + * Get List of PA_ReportLine_ID from .. to + * @param fromID from ID + * @param toID to ID + * @return comma separated list + */ + private String getLineIDs (int fromID, int toID) + { + log.finest("From=" + fromID + " To=" + toID); + StringBuffer sb = new StringBuffer(); + sb.append(fromID); + boolean addToList = false; + for (int line = 0; line < m_lines.length; line++) + { + int PA_ReportLine_ID = m_lines[line].getPA_ReportLine_ID(); + log.finest("Add=" + addToList + + " ID=" + PA_ReportLine_ID + " - " + m_lines[line]); + if (addToList) + { + sb.append (",").append (PA_ReportLine_ID); + if (PA_ReportLine_ID == toID) // done + break; + } + else if (PA_ReportLine_ID == fromID) // from already added + addToList = true; + } + return sb.toString(); + } // getLineIDs + + /** + * Get Column Index + * @param PA_ReportColumn_ID PA_ReportColumn_ID + * @return zero based index or if not found + */ + private int getColumnIndex (int PA_ReportColumn_ID) + { + for (int i = 0; i < m_columns.length; i++) + { + if (m_columns[i].getPA_ReportColumn_ID() == PA_ReportColumn_ID) + return i; + } + return -1; + } // getColumnIndex + + + /************************************************************************** + * Get Financial Reporting Period based on reportong Period and offset. + * @param relativeOffset offset + * @return reporting period + */ + private FinReportPeriod getPeriod (BigDecimal relativeOffset) + { + if (relativeOffset == null) + return getPeriod(0); + return getPeriod(relativeOffset.intValue()); + } // getPeriod + + /** + * Get Financial Reporting Period based on reporting Period and offset. + * @param relativeOffset offset + * @return reporting period + */ + private FinReportPeriod getPeriod (int relativeOffset) + { + // find current reporting period C_Period_ID + if (m_reportPeriod < 0) + { + for (int i = 0; i < m_periods.length; i++) + { + if (p_C_Period_ID == m_periods[i].getC_Period_ID()) + { + m_reportPeriod = i; + break; + } + } + } + if (m_reportPeriod < 0 || m_reportPeriod >= m_periods.length) + throw new UnsupportedOperationException ("Period index not found - ReportPeriod=" + + m_reportPeriod + ", C_Period_ID=" + p_C_Period_ID); + + // Bounds check + int index = m_reportPeriod + relativeOffset; + if (index < 0) + { + log.log(Level.SEVERE, "Relative Offset(" + relativeOffset + + ") not valid for selected Period(" + m_reportPeriod + ")"); + index = 0; + } + else if (index >= m_periods.length) + { + log.log(Level.SEVERE, "Relative Offset(" + relativeOffset + + ") not valid for selected Period(" + m_reportPeriod + ")"); + index = m_periods.length - 1; + } + // Get Period + return m_periods[index]; + } // getPeriod + + + /************************************************************************** + * Insert Detail Lines if enabled + */ + private void insertLineDetail() + { + if (!m_report.isListSources()) + return; + log.info(""); + + // for all source lines + for (int line = 0; line < m_lines.length; line++) + { + // Line Segment Value (i.e. not calculation) + if (m_lines[line].isLineTypeSegmentValue ()) + insertLineSource (line); + } + + // Set SeqNo + StringBuffer sql = new StringBuffer ("UPDATE T_Report r1 " + + "SET SeqNo = (SELECT SeqNo " + + "FROM T_Report r2 " + + "WHERE r1.AD_PInstance_ID=r2.AD_PInstance_ID AND r1.PA_ReportLine_ID=r2.PA_ReportLine_ID" + + " AND r2.Record_ID=0 AND r2.Fact_Acct_ID=0)" + + "WHERE SeqNo IS NULL"); + int no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("SeqNo #=" + no); + + if (!m_report.isListTrx()) + return; + + // Set Name,Description + String sql_select = "SELECT e.Name, fa.Description " + + "FROM Fact_Acct fa" + + " INNER JOIN AD_Table t ON (fa.AD_Table_ID=t.AD_Table_ID)" + + " INNER JOIN AD_Element e ON (t.TableName||'_ID'=e.ColumnName) " + + "WHERE r.Fact_Acct_ID=fa.Fact_Acct_ID"; + // Translated Version ... + sql = new StringBuffer ("UPDATE T_Report r SET (Name,Description)=(") + .append(sql_select).append(") " + + "WHERE Fact_Acct_ID <> 0 AND AD_PInstance_ID=") + .append(getAD_PInstance_ID()); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (CLogMgt.isLevelFinest()) + log.fine("Trx Name #=" + no + " - " + sql.toString()); + } // insertLineDetail + + /** + * Insert Detail Line per Source. + * For all columns (in a line) with relative period access + * - AD_PInstance_ID, PA_ReportLine_ID, variable, 0 - Level 1 + * @param line line + */ + private void insertLineSource (int line) + { + log.info("Line=" + line + " - " + m_lines[line]); + + // No source lines + if (m_lines[line] == null || m_lines[line].getSources().length == 0) + return; + String variable = m_lines[line].getSourceColumnName(); + if (variable == null) + return; + log.fine("Variable=" + variable); + + // Insert + StringBuffer insert = new StringBuffer("INSERT INTO T_Report " + + "(AD_PInstance_ID, PA_ReportLine_ID, Record_ID,Fact_Acct_ID,LevelNo "); + for (int col = 0; col < m_columns.length; col++) + insert.append(",Col_").append(col); + // Select + insert.append(") SELECT ") + .append(getAD_PInstance_ID()).append(",") + .append(m_lines[line].getPA_ReportLine_ID()).append(",") + .append(variable).append(",0,"); + if (p_DetailsSourceFirst) + insert.append("-1 "); + else + insert.append("1 "); + + // for all columns create select statement + for (int col = 0; col < m_columns.length; col++) + { + insert.append(", "); + // No calculation + if (m_columns[col].isColumnTypeCalculation()) + { + insert.append("NULL"); + continue; + } + + // SELECT SUM() + StringBuffer select = new StringBuffer ("SELECT "); + if (m_lines[line].getAmountType() != null) // line amount type overwrites column + select.append (m_lines[line].getSelectClause (true)); + else if (m_columns[col].getAmountType() != null) + select.append (m_columns[col].getSelectClause (true)); + else + { + insert.append("NULL"); + continue; + } + + // Get Period info + select.append(" FROM Fact_Acct_Balance fb WHERE DateAcct "); + FinReportPeriod frp = getPeriod (m_columns[col].getRelativePeriod()); + if (m_lines[line].getAmountType() != null) // line amount type overwrites column + { + if (m_lines[line].isPeriod()) + select.append(frp.getPeriodWhere()); + else if (m_lines[line].isYear()) + select.append(frp.getYearWhere()); + else + select.append(frp.getTotalWhere()); + } + else if (m_columns[col].getAmountType() != null) + { + if (m_columns[col].isPeriod()) + select.append(frp.getPeriodWhere()); + else if (m_columns[col].isYear()) + select.append(frp.getYearWhere()); + else + select.append(frp.getTotalWhere()); + } + // Link + select.append(" AND fb.").append(variable).append("=x.").append(variable); + // PostingType + if (!m_lines[line].isPostingType()) // only if not defined on line + { + String PostingType = m_columns[col].getPostingType(); + if (PostingType != null && PostingType.length() > 0) + select.append(" AND fb.PostingType='").append(PostingType).append("'"); + } + // Report Where + String s = m_report.getWhereClause(); + if (s != null && s.length() > 0) + select.append(" AND ").append(s); + // Limited Segment Values + if (m_columns[col].isColumnTypeSegmentValue()) + { + String elementType = m_columns[col].getElementType(); + if (MReportColumn.ELEMENTTYPE_Organization.equals(elementType)) + select.append(" AND AD_Org_ID=").append(m_columns[col].getOrg_ID()); + else if (MReportColumn.ELEMENTTYPE_BPartner.equals(elementType)) + select.append(" AND C_BPartner_ID=").append(m_columns[col].getC_BPartner_ID()); + else if (MReportColumn.ELEMENTTYPE_Product.equals(elementType)) + select.append(" AND M_Product_ID=").append(m_columns[col].getM_Product_ID()); + else if (MReportColumn.ELEMENTTYPE_Project.equals(elementType)) + select.append(" AND C_Project_ID=").append(m_columns[col].getC_Project_ID()); + else if (MReportColumn.ELEMENTTYPE_Activity.equals(elementType)) + select.append(" AND C_Activity_ID=").append(m_columns[col].getC_Activity_ID()); + else if (MReportColumn.ELEMENTTYPE_Campaign.equals(elementType)) + select.append(" AND C_Campaign_ID=").append(m_columns[col].getC_Campaign_ID()); + else if (MReportColumn.ELEMENTTYPE_LocationFrom.equals(elementType)) + select.append(" AND C_LocFrom_ID=").append(m_columns[col].getC_Location_ID()); + else if (MReportColumn.ELEMENTTYPE_LocationTo.equals(elementType)) + select.append(" AND C_LocTo_ID=").append(m_columns[col].getC_Location_ID()); + else if (MReportColumn.ELEMENTTYPE_OrgTrx.equals(elementType)) + select.append(" AND AD_OrgTrx_ID=").append(m_columns[col].getOrg_ID()); + else if (MReportColumn.ELEMENTTYPE_SalesRegion.equals(elementType)) + select.append(" AND C_SalesRegion_ID=").append(m_columns[col].getC_SalesRegion_ID()); + else if (MReportColumn.ELEMENTTYPE_Account.equals(elementType)) + select.append(" AND Account_ID=").append(m_columns[col].getC_ElementValue_ID()); + else if (MReportColumn.ELEMENTTYPE_UserList1.equals(elementType)) + select.append(" AND User1_ID=").append(m_columns[col].getC_ElementValue_ID()); + else if (MReportColumn.ELEMENTTYPE_UserList2.equals(elementType)) + select.append(" AND User2_ID=").append(m_columns[col].getC_ElementValue_ID()); + else if (MReportColumn.ELEMENTTYPE_UserElement1.equals(elementType)) + select.append(" AND UserElement1_ID=").append(m_columns[col].getC_ElementValue_ID()); + else if (MReportColumn.ELEMENTTYPE_UserElement2.equals(elementType)) + select.append(" AND UserElement2_ID=").append(m_columns[col].getC_ElementValue_ID()); + } + // Parameter Where + select.append(m_parameterWhere); + // System.out.println(" c=" + col + ", l=" + line + ": " + select); + // + insert.append("(").append(select).append(")"); + } + // + insert.append(" FROM Fact_Acct_Balance x WHERE ") + .append(m_lines[line].getWhereClause(p_PA_Hierarchy_ID)); // (sources, posting type) + String s = m_report.getWhereClause(); + if (s != null && s.length() > 0) + insert.append(" AND ").append(s); + // + insert.append(m_parameterWhere) + .append(" GROUP BY ").append(variable); + + int no = DB.executeUpdate(insert.toString(), get_TrxName()); + if (CLogMgt.isLevelFinest()) + log.fine("Source #=" + no + " - " + insert); + if (no == 0) + return; + + // Set Name,Description + StringBuffer sql = new StringBuffer ("UPDATE T_Report SET (Name,Description)=(") + .append(m_lines[line].getSourceValueQuery()).append("Record_ID) " + // + + "WHERE Record_ID <> 0 AND AD_PInstance_ID=").append(getAD_PInstance_ID()) + .append(" AND PA_ReportLine_ID=").append(m_lines[line].getPA_ReportLine_ID()) + .append(" AND Fact_Acct_ID=0"); + no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (CLogMgt.isLevelFinest()) + log.fine("Name #=" + no + " - " + sql.toString()); + + if (m_report.isListTrx()) + insertLineTrx (line, variable); + } // insertLineSource + + /** + * Create Trx Line per Source Detail. + * - AD_PInstance_ID, PA_ReportLine_ID, variable, Fact_Acct_ID - Level 2 + * @param line line + * @param variable variable, e.g. Account_ID + */ + private void insertLineTrx (int line, String variable) + { + log.info("Line=" + line + " - Variable=" + variable); + + // Insert + StringBuffer insert = new StringBuffer("INSERT INTO T_Report " + + "(AD_PInstance_ID, PA_ReportLine_ID, Record_ID,Fact_Acct_ID,LevelNo "); + for (int col = 0; col < m_columns.length; col++) + insert.append(",Col_").append(col); + // Select + insert.append(") SELECT ") + .append(getAD_PInstance_ID()).append(",") + .append(m_lines[line].getPA_ReportLine_ID()).append(",") + .append(variable).append(",Fact_Acct_ID, "); + if (p_DetailsSourceFirst) + insert.append("-2 "); + else + insert.append("2 "); + + // for all columns create select statement + for (int col = 0; col < m_columns.length; col++) + { + insert.append(", "); + // Only relative Period (not calculation or segment value) + if (!(m_columns[col].isColumnTypeRelativePeriod() + && m_columns[col].getRelativePeriodAsInt() == 0)) + { + insert.append("NULL"); + continue; + } + // Amount Type ... Qty + if (m_lines[line].getAmountType() != null) // line amount type overwrites column + insert.append (m_lines[line].getSelectClause (false)); + else if (m_columns[col].getAmountType() != null) + insert.append (m_columns[col].getSelectClause (false)); + else + { + insert.append("NULL"); + continue; + } + } + // + insert.append(" FROM Fact_Acct WHERE ") + .append(m_lines[line].getWhereClause(p_PA_Hierarchy_ID)); // (sources, posting type) + // Report Where + String s = m_report.getWhereClause(); + if (s != null && s.length() > 0) + insert.append(" AND ").append(s); + // Period restriction + FinReportPeriod frp = getPeriod (0); + insert.append(" AND DateAcct ") + .append(frp.getPeriodWhere()); + // PostingType ?? +// if (!m_lines[line].isPostingType()) // only if not defined on line +// { +// String PostingType = m_columns[col].getPostingType(); +// if (PostingType != null && PostingType.length() > 0) +// insert.append(" AND PostingType='").append(PostingType).append("'"); +// } + + int no = DB.executeUpdate(insert.toString(), get_TrxName()); + log.finest("Trx #=" + no + " - " + insert); + if (no == 0) + return; + } // insertLineTrx + + + /************************************************************************** + * Delete Unprinted Lines + */ + private void deleteUnprintedLines() + { + for (int line = 0; line < m_lines.length; line++) + { + // Not Printed - Delete in T + if (!m_lines[line].isPrinted()) + { + String sql = "DELETE FROM T_Report WHERE AD_PInstance_ID=" + getAD_PInstance_ID() + + " AND PA_ReportLine_ID=" + m_lines[line].getPA_ReportLine_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + if (no > 0) + log.fine(m_lines[line].getName() + " - #" + no); + } + } // for all lines + } // deleteUnprintedLines + + + /************************************************************************** + * Get/Create PrintFormat + * @return print format + */ + private MPrintFormat getPrintFormat() + { + int AD_PrintFormat_ID = m_report.getAD_PrintFormat_ID(); + log.info("AD_PrintFormat_ID=" + AD_PrintFormat_ID); + MPrintFormat pf = null; + boolean createNew = AD_PrintFormat_ID == 0; + + // Create New + if (createNew) + { + int AD_Table_ID = 544; // T_Report + pf = MPrintFormat.createFromTable(Env.getCtx(), AD_Table_ID); + AD_PrintFormat_ID = pf.getAD_PrintFormat_ID(); + m_report.setAD_PrintFormat_ID(AD_PrintFormat_ID); + m_report.save(); + } + else + pf = MPrintFormat.get (getCtx(), AD_PrintFormat_ID, false); // use Cache + + // Print Format Sync + if (!m_report.getName().equals(pf.getName())) + pf.setName(m_report.getName()); + if (m_report.getDescription() == null) + { + if (pf.getDescription () != null) + pf.setDescription (null); + } + else if (!m_report.getDescription().equals(pf.getDescription())) + pf.setDescription(m_report.getDescription()); + pf.save(); + log.fine(pf + " - #" + pf.getItemCount()); + + // Print Format Item Sync + int count = pf.getItemCount(); + for (int i = 0; i < count; i++) + { + MPrintFormatItem pfi = pf.getItem(i); + String ColumnName = pfi.getColumnName(); + // + if (ColumnName == null) + { + log.log(Level.SEVERE, "No ColumnName for #" + i + " - " + pfi); + if (pfi.isPrinted()) + pfi.setIsPrinted(false); + if (pfi.isOrderBy()) + pfi.setIsOrderBy(false); + if (pfi.getSortNo() != 0) + pfi.setSortNo(0); + } + else if (ColumnName.startsWith("Col")) + { + int index = Integer.parseInt(ColumnName.substring(4)); + if (index < m_columns.length) + { + pfi.setIsPrinted(m_columns[index].isPrinted()); + String s = m_columns[index].getName(); + if (!pfi.getName().equals(s)) + { + pfi.setName (s); + pfi.setPrintName (s); + } + int seq = 30 + index; + if (pfi.getSeqNo() != seq) + pfi.setSeqNo(seq); + } + else // not printed + { + if (pfi.isPrinted()) + pfi.setIsPrinted(false); + } + // Not Sorted + if (pfi.isOrderBy()) + pfi.setIsOrderBy(false); + if (pfi.getSortNo() != 0) + pfi.setSortNo(0); + } + else if (ColumnName.equals("SeqNo")) + { + if (pfi.isPrinted()) + pfi.setIsPrinted(false); + if (!pfi.isOrderBy()) + pfi.setIsOrderBy(true); + if (pfi.getSortNo() != 10) + pfi.setSortNo(10); + } + else if (ColumnName.equals("LevelNo")) + { + if (pfi.isPrinted()) + pfi.setIsPrinted(false); + if (!pfi.isOrderBy()) + pfi.setIsOrderBy(true); + if (pfi.getSortNo() != 20) + pfi.setSortNo(20); + } + else if (ColumnName.equals("Name")) + { + if (pfi.getSeqNo() != 10) + pfi.setSeqNo(10); + if (!pfi.isPrinted()) + pfi.setIsPrinted(true); + if (!pfi.isOrderBy()) + pfi.setIsOrderBy(true); + if (pfi.getSortNo() != 30) + pfi.setSortNo(30); + } + else if (ColumnName.equals("Description")) + { + if (pfi.getSeqNo() != 20) + pfi.setSeqNo(20); + if (!pfi.isPrinted()) + pfi.setIsPrinted(true); + if (pfi.isOrderBy()) + pfi.setIsOrderBy(false); + if (pfi.getSortNo() != 0) + pfi.setSortNo(0); + } + else // Not Printed, No Sort + { + if (pfi.isPrinted()) + pfi.setIsPrinted(false); + if (pfi.isOrderBy()) + pfi.setIsOrderBy(false); + if (pfi.getSortNo() != 0) + pfi.setSortNo(0); + } + pfi.save(); + log.fine(pfi.toString()); + } + // set translated to original + pf.setTranslation(); + // First one is unsorted - just re-load + if (createNew) + pf = MPrintFormat.get (getCtx(), AD_PrintFormat_ID, false); // use Cache + return pf; + } // getPrintFormat + +} // FinReport diff --git a/base/src/org/compiere/report/FinReportPeriod.java b/base/src/org/compiere/report/FinReportPeriod.java new file mode 100644 index 0000000000..8400631fe2 --- /dev/null +++ b/base/src/org/compiere/report/FinReportPeriod.java @@ -0,0 +1,149 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report; + +import java.sql.*; +import org.compiere.util.*; + +/** + * Financial Report Periods + * + * @author Jorg Janke + * @version $Id: FinReportPeriod.java,v 1.3 2006/08/03 22:16:52 jjanke Exp $ + */ +public class FinReportPeriod +{ + /** + * Constructor + * @param C_Period_ID period + * @param Name name + * @param StartDate period start date + * @param EndDate period end date + * @param YearStartDate year start date + */ + public FinReportPeriod (int C_Period_ID, String Name, Timestamp StartDate, Timestamp EndDate, + Timestamp YearStartDate) + { + m_C_Period_ID = C_Period_ID; + m_Name = Name; + m_StartDate = StartDate; + m_EndDate = EndDate; + m_YearStartDate = YearStartDate; + } // + + private int m_C_Period_ID; + private String m_Name; + private Timestamp m_StartDate; + private Timestamp m_EndDate; + private Timestamp m_YearStartDate; + + + /** + * Get Period Info + * @return BETWEEN start AND end + */ + public String getPeriodWhere () + { + StringBuffer sql = new StringBuffer ("BETWEEN "); + sql.append(DB.TO_DATE(m_StartDate)) + .append(" AND ") + .append(DB.TO_DATE(m_EndDate)); + return sql.toString(); + } // getPeriodWhere + + /** + * Get Year Info + * @return BETWEEN start AND end + */ + public String getYearWhere () + { + StringBuffer sql = new StringBuffer ("BETWEEN "); + sql.append(DB.TO_DATE(m_YearStartDate)) + .append(" AND ") + .append(DB.TO_DATE(m_EndDate)); + return sql.toString(); + } // getPeriodWhere + + /** + * Get Total Info + * @return <= end + */ + public String getTotalWhere () + { + StringBuffer sql = new StringBuffer ("<= "); + sql.append(DB.TO_DATE(m_EndDate)); + return sql.toString(); + } // getPeriodWhere + + /** + * Is date in period + * @param date date + * @return true if in period + */ + public boolean inPeriod (Timestamp date) + { + if (date == null) + return false; + if (date.before(m_StartDate)) + return false; + if (date.after(m_EndDate)) + return false; + return true; + } // inPeriod + + /** + * Get Name + * @return name + */ + public String getName() + { + return m_Name; + } + /** + * Get C_Period_ID + * @return period + */ + public int getC_Period_ID() + { + return m_C_Period_ID; + } + /** + * Get End Date + * @return end date + */ + public Timestamp getEndDate() + { + return m_EndDate; + } + /** + * Get Start Date + * @return start date + */ + public Timestamp getStartDate() + { + return m_StartDate; + } + /** + * Get Year Start Date + * @return year start date + */ + public Timestamp getYearStartDate() + { + return m_YearStartDate; + } + +} // FinReportPeriod diff --git a/base/src/org/compiere/report/FinStatement.java b/base/src/org/compiere/report/FinStatement.java new file mode 100644 index 0000000000..01cdeb14f5 --- /dev/null +++ b/base/src/org/compiere/report/FinStatement.java @@ -0,0 +1,325 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.print.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Statement of Account + * + * @author Jorg Janke + * @version $Id: FinStatement.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class FinStatement extends SvrProcess +{ + /** AcctSchame Parameter */ + private int p_C_AcctSchema_ID = 0; + /** Posting Type */ + private String p_PostingType = "A"; + /** Period Parameter */ + private int p_C_Period_ID = 0; + private Timestamp p_DateAcct_From = null; + private Timestamp p_DateAcct_To = null; + /** Org Parameter */ + private int p_AD_Org_ID = 0; + /** Account Parameter */ + private int p_Account_ID = 0; + /** BPartner Parameter */ + private int p_C_BPartner_ID = 0; + /** Product Parameter */ + private int p_M_Product_ID = 0; + /** Project Parameter */ + private int p_C_Project_ID = 0; + /** Activity Parameter */ + private int p_C_Activity_ID = 0; + /** SalesRegion Parameter */ + private int p_C_SalesRegion_ID = 0; + /** Campaign Parameter */ + private int p_C_Campaign_ID = 0; + /** Update Balances Parameter */ + private boolean p_UpdateBalances = true; + /** Hierarchy */ + private int p_PA_Hierarchy_ID = 0; + + /** Parameter Where Clause */ + private StringBuffer m_parameterWhere = new StringBuffer(); + /** Account */ + private MElementValue m_acct = null; + + /** Start Time */ + private long m_start = System.currentTimeMillis(); + + /** + * Prepare - e.g., get Parameters. + */ + 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) + ; + else if (name.equals("C_AcctSchema_ID")) + p_C_AcctSchema_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("PostingType")) + p_PostingType = (String)para[i].getParameter(); + else if (name.equals("C_Period_ID")) + p_C_Period_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("DateAcct")) + { + p_DateAcct_From = (Timestamp)para[i].getParameter(); + p_DateAcct_To = (Timestamp)para[i].getParameter_To(); + } + else if (name.equals("PA_Hierarchy_ID")) + p_PA_Hierarchy_ID = para[i].getParameterAsInt(); + else if (name.equals("AD_Org_ID")) + p_AD_Org_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("Account_ID")) + p_Account_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("M_Product_ID")) + p_M_Product_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_Project_ID")) + p_C_Project_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_Activity_ID")) + p_C_Activity_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_SalesRegion_ID")) + p_C_SalesRegion_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_Campaign_ID")) + p_C_Campaign_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("UpdateBalances")) + p_UpdateBalances = "Y".equals(para[i].getParameter()); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + // Mandatory C_AcctSchema_ID, PostingType + m_parameterWhere.append("C_AcctSchema_ID=").append(p_C_AcctSchema_ID) + .append(" AND PostingType='").append(p_PostingType).append("'"); + // Optional Account_ID + if (p_Account_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_Account, p_Account_ID)); + // Optional Org + if (p_AD_Org_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_Organization, p_AD_Org_ID)); + // Optional BPartner + if (p_C_BPartner_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_BPartner, p_C_BPartner_ID)); + // Optional Product + if (p_M_Product_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_Product, p_M_Product_ID)); + // Optional Project + if (p_C_Project_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_Project, p_C_Project_ID)); + // Optional Activity + if (p_C_Activity_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_Activity, p_C_Activity_ID)); + // Optional Campaign + if (p_C_Campaign_ID != 0) + m_parameterWhere.append(" AND C_Campaign_ID=").append(p_C_Campaign_ID); + // m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + // MAcctSchemaElement.ELEMENTTYPE_Campaign, p_C_Campaign_ID)); + // Optional Sales Region + if (p_C_SalesRegion_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_SalesRegion, p_C_SalesRegion_ID)); + // + setDateAcct(); + sb.append(" - DateAcct ").append(p_DateAcct_From).append("-").append(p_DateAcct_To); + sb.append(" - Where=").append(m_parameterWhere); + log.fine(sb.toString()); + } // prepare + + /** + * Set Start/End Date of Report - if not defined current Month + */ + private void setDateAcct() + { + // Date defined + if (p_DateAcct_From != null) + { + if (p_DateAcct_To == null) + p_DateAcct_To = new Timestamp (System.currentTimeMillis()); + return; + } + // Get Date from Period + if (p_C_Period_ID == 0) + { + GregorianCalendar cal = new GregorianCalendar(Language.getLoginLanguage().getLocale()); + cal.setTimeInMillis(System.currentTimeMillis()); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + cal.set(Calendar.DAY_OF_MONTH, 1); // set to first of month + p_DateAcct_From = new Timestamp (cal.getTimeInMillis()); + cal.add(Calendar.MONTH, 1); + cal.add(Calendar.DAY_OF_YEAR, -1); // last of month + p_DateAcct_To = new Timestamp (cal.getTimeInMillis()); + return; + } + + String sql = "SELECT StartDate, EndDate FROM C_Period WHERE C_Period_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, p_C_Period_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + p_DateAcct_From = rs.getTimestamp(1); + p_DateAcct_To = rs.getTimestamp(2); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + } // setDateAcct + + + + /************************************************************************** + * Perform process. + * @return Message to be translated + */ + protected String doIt() + { + // Update AcctSchema Balances + if (p_UpdateBalances) + FinBalance.updateBalance (p_C_AcctSchema_ID, false); + + createBalanceLine(); + createDetailLines(); + + int AD_PrintFormat_ID = 134; + if (Ini.isClient()) + getProcessInfo().setTransientObject (MPrintFormat.get (getCtx(), AD_PrintFormat_ID, false)); + else + getProcessInfo().setSerializableObject(MPrintFormat.get (getCtx(), AD_PrintFormat_ID, false)); + + log.fine((System.currentTimeMillis() - m_start) + " ms"); + return ""; + } // doIt + + /** + * Create Beginning Balance Line + */ + private void createBalanceLine() + { + StringBuffer sb = new StringBuffer ("INSERT INTO T_ReportStatement " + + "(AD_PInstance_ID, Fact_Acct_ID, LevelNo," + + "DateAcct, Name, Description," + + "AmtAcctDr, AmtAcctCr, Balance, Qty) "); + sb.append("SELECT ").append(getAD_PInstance_ID()).append(",0,0,") + .append(DB.TO_DATE(p_DateAcct_From, true)).append(",") + .append(DB.TO_STRING(Msg.getMsg(Env.getCtx(), "BeginningBalance"))).append(",NULL," + + "COALESCE(SUM(AmtAcctDr),0), COALESCE(SUM(AmtAcctCr),0), COALESCE(SUM(AmtAcctDr-AmtAcctCr),0), COALESCE(SUM(Qty),0) " + + "FROM Fact_Acct_Balance " + + "WHERE ").append(m_parameterWhere) + .append(" AND DateAcct < ").append(DB.TO_DATE(p_DateAcct_From)); + + // Start Beginning of Year + if (p_Account_ID > 0) + { + m_acct = new MElementValue (getCtx(), p_Account_ID, get_TrxName()); + if (!m_acct.isBalanceSheet()) + { + MPeriod first = MPeriod.getFirstInYear (getCtx(), p_DateAcct_From); + if (first != null) + sb.append(" AND DateAcct >= ").append(DB.TO_DATE(first.getStartDate())); + else + log.log(Level.SEVERE, "First period not found"); + } + } + // + int no = DB.executeUpdate(sb.toString(), get_TrxName()); + log.fine("#" + no + " (Account_ID=" + p_Account_ID + ")"); + log.finest(sb.toString()); + } // createBalanceLine + + /** + * Create Beginning Balance Line + */ + private void createDetailLines() + { + StringBuffer sb = new StringBuffer ("INSERT INTO T_ReportStatement " + + "(AD_PInstance_ID, Fact_Acct_ID, LevelNo," + + "DateAcct, Name, Description," + + "AmtAcctDr, AmtAcctCr, Balance, Qty) "); + sb.append("SELECT ").append(getAD_PInstance_ID()).append(",Fact_Acct_ID,1,") + .append("DateAcct,NULL,NULL," + + "AmtAcctDr, AmtAcctCr, AmtAcctDr-AmtAcctCr, Qty " + + "FROM Fact_Acct " + + "WHERE ").append(m_parameterWhere) + .append(" AND DateAcct BETWEEN ").append(DB.TO_DATE(p_DateAcct_From)) + .append(" AND ").append(DB.TO_DATE(p_DateAcct_To)); + // + int no = DB.executeUpdate(sb.toString(), get_TrxName()); + log.fine("#" + no); + log.finest(sb.toString()); + + // Set Name,Description + String sql_select = "SELECT e.Name, fa.Description " + + "FROM Fact_Acct fa" + + " INNER JOIN AD_Table t ON (fa.AD_Table_ID=t.AD_Table_ID)" + + " INNER JOIN AD_Element e ON (t.TableName||'_ID'=e.ColumnName) " + + "WHERE r.Fact_Acct_ID=fa.Fact_Acct_ID"; + // Translated Version ... + sb = new StringBuffer ("UPDATE T_ReportStatement r SET (Name,Description)=(") + .append(sql_select).append(") " + + "WHERE Fact_Acct_ID <> 0 AND AD_PInstance_ID=").append(getAD_PInstance_ID()); + // + no = DB.executeUpdate(sb.toString(), get_TrxName()); + log.fine("Name #" + no); + log.finest("Name - " + sb); + + } // createDetailLines + +} // FinStatement diff --git a/base/src/org/compiere/report/MReport.java b/base/src/org/compiere/report/MReport.java new file mode 100644 index 0000000000..79ec0279ea --- /dev/null +++ b/base/src/org/compiere/report/MReport.java @@ -0,0 +1,135 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report; + +import java.sql.*; +import java.util.*; +import org.compiere.model.*; + + +/** + * Report Model + * + * @author Jorg Janke + * @version $Id: MReport.java,v 1.3 2006/08/03 22:16:52 jjanke Exp $ + */ +public class MReport extends X_PA_Report +{ + /** + * Constructor + * @param ctx context + * @param PA_Report_ID id + * @param trxName transaction + */ + public MReport (Properties ctx, int PA_Report_ID, String trxName) + { + super (ctx, PA_Report_ID, trxName); + if (PA_Report_ID == 0) + { + // setName (null); + // setPA_ReportLineSet_ID (0); + // setPA_ReportColumnSet_ID (0); + setListSources(false); + setListTrx(false); + } + else + { + m_columnSet = new MReportColumnSet (ctx, getPA_ReportColumnSet_ID(), trxName); + m_lineSet = new MReportLineSet (ctx, getPA_ReportLineSet_ID(), trxName); + } + } // MReport + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MReport (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + m_columnSet = new MReportColumnSet (ctx, getPA_ReportColumnSet_ID(), trxName); + m_lineSet = new MReportLineSet (ctx, getPA_ReportLineSet_ID(), trxName); + } // MReport + + private MReportColumnSet m_columnSet = null; + private MReportLineSet m_lineSet = null; + + /** + * List Info + */ + public void list() + { + System.out.println(toString()); + if (m_columnSet != null) + m_columnSet.list(); + System.out.println(); + if (m_lineSet != null) + m_lineSet.list(); + } // dump + + /** + * Get Where Clause for Report + * @return Where Clause for Report + */ + public String getWhereClause() + { + // AD_Client indirectly via AcctSchema + StringBuffer sb = new StringBuffer(); + // Mandatory AcctSchema + sb.append("C_AcctSchema_ID=").append(getC_AcctSchema_ID()); + // + return sb.toString(); + } // getWhereClause + + /*************************************************************************/ + + /** + * String Representation + * @return Info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MReport[") + .append(get_ID()).append(" - ").append(getName()); + if (getDescription() != null) + sb.append("(").append(getDescription()).append(")"); + sb.append(" - C_AcctSchema_ID=").append(getC_AcctSchema_ID()) + .append(", C_Calendar_ID=").append(getC_Calendar_ID()); + sb.append ("]"); + return sb.toString (); + } // toString + + /** + * Get Column Set + * @return Column Set + */ + public MReportColumnSet getColumnSet() + { + return m_columnSet; + } + + /** + * Get Line Set + * @return Line Set + */ + public MReportLineSet getLineSet() + { + return m_lineSet; + } + +} // MReport diff --git a/base/src/org/compiere/report/MReportColumn.java b/base/src/org/compiere/report/MReportColumn.java new file mode 100644 index 0000000000..03ffeb1747 --- /dev/null +++ b/base/src/org/compiere/report/MReportColumn.java @@ -0,0 +1,263 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report; + +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; + +/** + * Report Column Model + * + * @author Jorg Janke + * @version $Id: MReportColumn.java,v 1.3 2006/08/03 22:16:52 jjanke Exp $ + */ +public class MReportColumn extends X_PA_ReportColumn +{ + /** + * Constructor + * @param ctx context + * @param PA_ReportColumn_ID id + * @param trxName transaction + */ + public MReportColumn (Properties ctx, int PA_ReportColumn_ID, String trxName) + { + super (ctx, PA_ReportColumn_ID, trxName); + if (PA_ReportColumn_ID == 0) + { + setIsPrinted (true); + setSeqNo (0); + } + } // MReportColumn + + /** + * Constructor + * @param ctx context + * @param rs ResultSet to load from + * @param trxName transaction + */ + public MReportColumn (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MReportColumn + + /************************************************************************** + * Get Column SQL Select Clause. + * @param withSum with SUM() function + * @return select clause - AmtAcctCR+AmtAcctDR/etc or "null" if not defined + */ + public String getSelectClause (boolean withSum) + { + // Amount Type = Period Balance, Period Credit + String amountType = getAmountType().substring(0,1); // first character + StringBuffer sb = new StringBuffer(); + if (withSum) + sb.append("SUM("); + if (AmountType_Balance.equals(amountType)) + // sb.append("AmtAcctDr-AmtAcctCr"); + sb.append("acctBalance(Account_ID,AmtAcctDr,AmtAcctCr)"); + else if (AmountType_CR.equals(amountType)) + sb.append("AmtAcctCr"); + else if (AmountType_DR.equals(amountType)) + sb.append("AmtAcctDr"); + else if (AmountType_Qty.equals(amountType)) + sb.append("Qty"); + else + { + log.log(Level.SEVERE, "AmountType=" + getAmountType () + ", at=" + amountType); + return "NULL"; + } + if (withSum) + sb.append(")"); + return sb.toString(); + } // getSelectClause + + /** + * Is it Period Info ? + * @return true if Period Amount Type + */ + public boolean isPeriod() + { + String at = getAmountType(); + if (at == null) + return false; + return AMOUNTTYPE_PeriodBalance.equals(at) + || AMOUNTTYPE_PeriodCreditOnly.equals(at) + || AMOUNTTYPE_PeriodDebitOnly.equals(at) + || AMOUNTTYPE_PeriodQuantity.equals(at); + } // isPeriod + + /** + * Is it Year Info ? + * @return true if Year Amount Type + */ + public boolean isYear() + { + String at = getAmountType(); + if (at == null) + return false; + return AMOUNTTYPE_YearBalance.equals(at) + || AMOUNTTYPE_YearCreditOnly.equals(at) + || AMOUNTTYPE_YearDebitOnly.equals(at) + || AMOUNTTYPE_YearQuantity.equals(at); + } // isYear + + /** + * Is it Total Info ? + * @return true if Year Amount Type + */ + public boolean isTotal() + { + String at = getAmountType(); + if (at == null) + return false; + return AMOUNTTYPE_TotalBalance.equals(at) + || AMOUNTTYPE_TotalCreditOnly.equals(at) + || AMOUNTTYPE_TotalDebitOnly.equals(at) + || AMOUNTTYPE_TotalQuantity.equals(at); + } // isTotalBalance + + + /** + * Get String Representation + * @return String Representation + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MReportColumn[") + .append(get_ID()).append(" - ").append(getName()).append(" - ").append(getDescription()) + .append(", SeqNo=").append(getSeqNo()).append(", AmountType=").append(getAmountType()) + .append(", CurrencyType=").append(getCurrencyType()).append("/").append(getC_Currency_ID()) + .append(" - ColumnType=").append(getColumnType()); + if (isColumnTypeCalculation()) + sb.append(" - Calculation=").append(getCalculationType()) + .append(" - ").append(getOper_1_ID()).append(" - ").append(getOper_2_ID()); + else if (isColumnTypeRelativePeriod()) + sb.append(" - Period=").append(getRelativePeriod()); + else + sb.append(" - SegmentValue ElementType=").append(getElementType()); + sb.append ("]"); + return sb.toString (); + } // toString + + static final String AmountType_Balance = "B"; + static final String AmountType_CR = "C"; + static final String AmountType_DR = "D"; + static final String AmountType_Qty = "Q"; + // + static final String AmountType_Period = "P"; + static final String AmountType_Year = "Y"; + static final String AmountType_Total = "T"; + + /** + * Calculation Type Range + * @return true if range + */ + public boolean isCalculationTypeRange() + { + return CALCULATIONTYPE_AddRangeOp1ToOp2.equals(getCalculationType()); + } + /** + * Calculation Type Add + * @return true id add + */ + public boolean isCalculationTypeAdd() + { + return CALCULATIONTYPE_AddOp1PlusOp2.equals(getCalculationType()); + } + /** + * Calculation Type Subtract + * @return true if subtract + */ + public boolean isCalculationTypeSubtract() + { + return CALCULATIONTYPE_SubtractOp1_Op2.equals(getCalculationType()); + } + /** + * Calculation Type Percent + * @return true if percent + */ + public boolean isCalculationTypePercent() + { + return CALCULATIONTYPE_PercentageOp1OfOp2.equals(getCalculationType()); + } + + + /** + * Column Type Calculation + * @return true if calculation + */ + public boolean isColumnTypeCalculation() + { + return COLUMNTYPE_Calculation.equals(getColumnType()); + } + /** + * Column Type Relative Period + * @return true if ralative period + */ + public boolean isColumnTypeRelativePeriod() + { + return COLUMNTYPE_RelativePeriod.equals(getColumnType()); + } + /** + * Column Type Segment Value + * @return true if segment value + */ + public boolean isColumnTypeSegmentValue() + { + return COLUMNTYPE_SegmentValue.equals(getColumnType()); + } + /** + * Get Relative Period As Int + * @return relative period + */ + public int getRelativePeriodAsInt () + { + BigDecimal bd = getRelativePeriod(); + if (bd == null) + return 0; + return bd.intValue(); + } // getRelativePeriodAsInt + + + /************************************************************************** + + /** + * Copy + * @param ctx context + * @param AD_Client_ID parent + * @param AD_Org_ID parent + * @param PA_ReportColumnSet_ID parent + * @param source copy source + * @param trxName transaction + * @return Report Column + */ + public static MReportColumn copy (Properties ctx, int AD_Client_ID, int AD_Org_ID, + int PA_ReportColumnSet_ID, MReportColumn source, String trxName) + { + MReportColumn retValue = new MReportColumn (ctx, 0, trxName); + MReportColumn.copyValues(source, retValue, AD_Client_ID, AD_Org_ID); + // + retValue.setPA_ReportColumnSet_ID(PA_ReportColumnSet_ID); // parent + retValue.setOper_1_ID(0); + retValue.setOper_2_ID(0); + return retValue; + } // copy + +} // MReportColumn diff --git a/base/src/org/compiere/report/MReportColumnSet.java b/base/src/org/compiere/report/MReportColumnSet.java new file mode 100644 index 0000000000..16b2e7f7ff --- /dev/null +++ b/base/src/org/compiere/report/MReportColumnSet.java @@ -0,0 +1,129 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Report Column Set Model + * + * @author Jorg Janke + * @version $Id: MReportColumnSet.java,v 1.3 2006/08/03 22:16:52 jjanke Exp $ + */ +public class MReportColumnSet extends X_PA_ReportColumnSet +{ + /** + * Constructor + * @param ctx context + * @param PA_ReportColumnSet_ID id + * @param trxName transaction + */ + public MReportColumnSet (Properties ctx, int PA_ReportColumnSet_ID, String trxName) + { + super (ctx, PA_ReportColumnSet_ID, trxName); + if (PA_ReportColumnSet_ID == 0) + { + } + else + loadColumns(); + } // MReportColumnSet + + /** Contained Columns */ + private MReportColumn[] m_columns = null; + + /** + * Load contained columns + */ + private void loadColumns() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM PA_ReportColumn WHERE PA_ReportColumnSet_ID=? AND IsActive='Y' ORDER BY SeqNo"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getPA_ReportColumnSet_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MReportColumn (getCtx(), rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + // + m_columns = new MReportColumn[list.size()]; + list.toArray(m_columns); + log.finest("ID=" + getPA_ReportColumnSet_ID() + + " - Size=" + list.size()); + } // loadColumns + + /** + * Get Columns + * @return columns + */ + public MReportColumn[] getColumns() + { + return m_columns; + } // getColumns + + /** + * List Info + */ + public void list() + { + System.out.println(toString()); + if (m_columns == null) + return; + for (int i = 0; i < m_columns.length; i++) + System.out.println("- " + m_columns[i].toString()); + } // list + + /*************************************************************************/ + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MReportColumnSet[") + .append(get_ID()).append(" - ").append(getName()) + .append ("]"); + return sb.toString (); + } + +} // MReportColumnSet diff --git a/base/src/org/compiere/report/MReportLine.java b/base/src/org/compiere/report/MReportLine.java new file mode 100644 index 0000000000..9347d756fd --- /dev/null +++ b/base/src/org/compiere/report/MReportLine.java @@ -0,0 +1,417 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Report Line Model + * + * @author Jorg Janke + * @version $Id: MReportLine.java,v 1.3 2006/08/03 22:16:52 jjanke Exp $ + */ +public class MReportLine extends X_PA_ReportLine +{ + /** + * Constructor + * @param ctx context + * @param PA_ReportLine_ID id + * @param trxName transaction + */ + public MReportLine (Properties ctx, int PA_ReportLine_ID, String trxName) + { + super (ctx, PA_ReportLine_ID, trxName); + if (PA_ReportLine_ID == 0) + { + setSeqNo (0); + // setIsSummary (false); // not active in DD + setIsPrinted (false); + } + else + loadSources(); + } // MReportLine + + /** + * Constructor + * @param ctx context + * @param rs ResultSet to load from + * @param trxName transaction + */ + public MReportLine (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + loadSources(); + } // MReportLine + + /** Containt Sources */ + private MReportSource[] m_sources = null; + /** Cache result */ + private String m_whereClause = null; + + /** + * Load contained Sources + */ + private void loadSources() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM PA_ReportSource WHERE PA_ReportLine_ID=? AND IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getPA_ReportLine_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MReportSource (getCtx(), rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, null, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + // + m_sources = new MReportSource[list.size()]; + list.toArray(m_sources); + log.finest("ID=" + getPA_ReportLine_ID() + + " - Size=" + list.size()); + } // loadSources + + /** + * Get Sources + * @return sources + */ + public MReportSource[] getSources() + { + return m_sources; + } // getSources + + /** + * List Info + */ + public void list() + { + System.out.println("- " + toString()); + if (m_sources == null) + return; + for (int i = 0; i < m_sources.length; i++) + System.out.println(" - " + m_sources[i].toString()); + } // list + + + /** + * Get Source Column Name + * @return Source ColumnName + */ + public String getSourceColumnName() + { + String ColumnName = null; + for (int i = 0; i < m_sources.length; i++) + { + String col = MAcctSchemaElement.getColumnName (m_sources[i].getElementType()); + if (ColumnName == null || ColumnName.length() == 0) + ColumnName = col; + else if (!ColumnName.equals(col)) + { + log.config("More than one: " + ColumnName + " - " + col); + return null; + } + } + return ColumnName; + } // getColumnName + + /** + * Get Value Query for Segment Type + * @return Query for first source element or null + */ + public String getSourceValueQuery() + { + if (m_sources != null && m_sources.length > 0) + return MAcctSchemaElement.getValueQuery(m_sources[0].getElementType()); + return null; + } // + + + /** + * Get SQL Select Clause. + * @param withSum with SUM() function + * @return select clause - AmtAcctCR+AmtAcctDR/etc or "null" if not defined + */ + public String getSelectClause (boolean withSum) + { + String at = getAmountType().substring(0,1); // first letter + StringBuffer sb = new StringBuffer(); + if (withSum) + sb.append("SUM("); + if (AmountType_Balance.equals(at)) + // sb.append("AmtAcctDr-AmtAcctCr"); + sb.append("acctBalance(Account_ID,AmtAcctDr,AmtAcctCr)"); + else if (AmountType_CR.equals(at)) + sb.append("AmtAcctCr"); + else if (AmountType_DR.equals(at)) + sb.append("AmtAcctDr"); + else if (AmountType_Qty.equals(at)) + sb.append("Qty"); + else + { + log.log(Level.SEVERE, "AmountType=" + getAmountType () + ", at=" + at); + return "NULL"; + } + if (withSum) + sb.append(")"); + return sb.toString(); + } // getSelectClause + + /** + * Is it Period ? + * @return true if Period Amount Type + */ + public boolean isPeriod() + { + String at = getAmountType(); + if (at == null) + return false; + return AMOUNTTYPE_PeriodBalance.equals(at) + || AMOUNTTYPE_PeriodCreditOnly.equals(at) + || AMOUNTTYPE_PeriodDebitOnly.equals(at) + || AMOUNTTYPE_PeriodQuantity.equals(at); + } // isPeriod + + /** + * Is it Year ? + * @return true if Year Amount Type + */ + public boolean isYear() + { + String at = getAmountType(); + if (at == null) + return false; + return AMOUNTTYPE_YearBalance.equals(at) + || AMOUNTTYPE_YearCreditOnly.equals(at) + || AMOUNTTYPE_YearDebitOnly.equals(at) + || AMOUNTTYPE_YearQuantity.equals(at); + } // isYear + + /** + * Is it Total ? + * @return true if Year Amount Type + */ + public boolean isTotal() + { + String at = getAmountType(); + if (at == null) + return false; + return AMOUNTTYPE_TotalBalance.equals(at) + || AMOUNTTYPE_TotalCreditOnly.equals(at) + || AMOUNTTYPE_TotalDebitOnly.equals(at) + || AMOUNTTYPE_TotalQuantity.equals(at); + } // isTotal + + /** + * Get SQL where clause (sources, posting type) + * @param PA_Hierarchy_ID hierarchy + * @return where clause + */ + public String getWhereClause(int PA_Hierarchy_ID) + { + if (m_sources == null) + return ""; + if (m_whereClause == null) + { + // Only one + if (m_sources.length == 0) + m_whereClause = ""; + else if (m_sources.length == 1) + m_whereClause = m_sources[0].getWhereClause(PA_Hierarchy_ID); + else + { + // Multiple + StringBuffer sb = new StringBuffer ("("); + for (int i = 0; i < m_sources.length; i++) + { + if (i > 0) + sb.append (" OR "); + sb.append (m_sources[i].getWhereClause(PA_Hierarchy_ID)); + } + sb.append (")"); + m_whereClause = sb.toString (); + } + // Posting Type + String PostingType = getPostingType(); + if (PostingType != null && PostingType.length() > 0) + { + if (m_whereClause.length() > 0) + m_whereClause += " AND "; + m_whereClause += "PostingType='" + PostingType + "'"; + } + log.fine(m_whereClause); + } + return m_whereClause; + } // getWhereClause + + /** + * Has Posting Type + * @return true if posting + */ + public boolean isPostingType() + { + String PostingType = getPostingType(); + return (PostingType != null && PostingType.length() > 0); + } // isPostingType + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MReportLine[") + .append(get_ID()).append(" - ").append(getName()).append(" - ").append(getDescription()) + .append(", SeqNo=").append(getSeqNo()).append(", AmountType=").append(getAmountType()) + .append(" - LineType=").append(getLineType()); + if (isLineTypeCalculation()) + sb.append(" - Calculation=").append(getCalculationType()) + .append(" - ").append(getOper_1_ID()).append(" - ").append(getOper_2_ID()); + else // SegmentValue + sb.append(" - SegmentValue - PostingType=").append(getPostingType()) + .append(", AmountType=").append(getAmountType()); + sb.append ("]"); + return sb.toString (); + } // toString + + // First Letter + static final String AmountType_Balance = "B"; + static final String AmountType_CR = "C"; + static final String AmountType_DR = "D"; + static final String AmountType_Qty = "Q"; + // Second Letter + static final String AmountType_Period = "P"; + static final String AmountType_Year = "Y"; + static final String AmountType_Total = "T"; + + /** + * Line Type Calculation + * @return true if calculation + */ + public boolean isLineTypeCalculation() + { + return LINETYPE_Calculation.equals(getLineType()); + } + /** + * Line Type Segment Value + * @return true if segment value + */ + public boolean isLineTypeSegmentValue() + { + return LINETYPE_SegmentValue.equals(getLineType()); + } + + /** + * Calculation Type Range + * @return true if range + */ + public boolean isCalculationTypeRange() + { + return CALCULATIONTYPE_AddRangeOp1ToOp2.equals(getCalculationType()); + } + /** + * Calculation Type Add + * @return true if add + */ + public boolean isCalculationTypeAdd() + { + return CALCULATIONTYPE_AddOp1PlusOp2.equals(getCalculationType()); + } + /** + * Calculation Type Subtract + * @return true if subtract + */ + public boolean isCalculationTypeSubtract() + { + return CALCULATIONTYPE_SubtractOp1_Op2.equals(getCalculationType()); + } + /** + * Calculation Type Percent + * @return true if percent + */ + public boolean isCalculationTypePercent() + { + return CALCULATIONTYPE_PercentageOp1OfOp2.equals(getCalculationType()); + } + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (LINETYPE_SegmentValue.equals(getLineType())) + { + if (getCalculationType() != null) + setCalculationType(null); + if (getOper_1_ID() != 0) + setOper_1_ID(0); + if (getOper_2_ID() != 0) + setOper_2_ID(0); + } + return true; + } // beforeSave + + + /************************************************************************** + * Copy + * @param ctx context + * @param AD_Client_ID parent + * @param AD_Org_ID parent + * @param PA_ReportLineSet_ID parent + * @param source copy source + * @param trxName transaction + * @return Report Line + */ + public static MReportLine copy (Properties ctx, int AD_Client_ID, int AD_Org_ID, + int PA_ReportLineSet_ID, MReportLine source, String trxName) + { + MReportLine retValue = new MReportLine (ctx, 0, trxName); + MReportLine.copyValues(source, retValue, AD_Client_ID, AD_Org_ID); + // + retValue.setPA_ReportLineSet_ID(PA_ReportLineSet_ID); + retValue.setOper_1_ID(0); + retValue.setOper_2_ID(0); + return retValue; + } // copy + + +} // MReportLine diff --git a/base/src/org/compiere/report/MReportLineSet.java b/base/src/org/compiere/report/MReportLineSet.java new file mode 100644 index 0000000000..cbb6041d08 --- /dev/null +++ b/base/src/org/compiere/report/MReportLineSet.java @@ -0,0 +1,129 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Report Line Set Model + * + * @author Jorg Janke + * @version $Id: MReportLineSet.java,v 1.3 2006/08/03 22:16:52 jjanke Exp $ + */ +public class MReportLineSet extends X_PA_ReportLineSet +{ + /** + * Constructor + * @param ctx context + * @param PA_ReportLineSet_ID id + * @param trxName transaction + */ + public MReportLineSet (Properties ctx, int PA_ReportLineSet_ID, String trxName) + { + super (ctx, PA_ReportLineSet_ID, trxName); + if (PA_ReportLineSet_ID == 0) + { + } + else + loadLines(); + } // MReportLineSet + + /** Contained Lines */ + private MReportLine[] m_lines = null; + + /** + * Load Lines + */ + private void loadLines() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM PA_ReportLine " + + "WHERE PA_ReportLineSet_ID=? AND IsActive='Y' " + + "ORDER BY SeqNo"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getPA_ReportLineSet_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MReportLine (getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + // + m_lines = new MReportLine[list.size()]; + list.toArray(m_lines); + log.finest("ID=" + getPA_ReportLineSet_ID() + + " - Size=" + list.size()); + } // loadColumns + + /** + * Get Liness + * @return array of lines + */ + public MReportLine[] getLiness() + { + return m_lines; + } // getLines + + /** + * List Info + */ + public void list() + { + System.out.println(toString()); + if (m_lines == null) + return; + for (int i = 0; i < m_lines.length; i++) + m_lines[i].list(); + } // list + + /** + * String representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MReportLineSet[") + .append(get_ID()).append(" - ").append(getName()) + .append ("]"); + return sb.toString (); + } + +} // MReportLineSet diff --git a/base/src/org/compiere/report/MReportSource.java b/base/src/org/compiere/report/MReportSource.java new file mode 100644 index 0000000000..29b7852a81 --- /dev/null +++ b/base/src/org/compiere/report/MReportSource.java @@ -0,0 +1,137 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report; + +import java.sql.*; +import java.util.*; +import org.compiere.model.*; + + +/** + * Report Line Source Model + * + * @author Jorg Janke + * @version $Id: MReportSource.java,v 1.3 2006/08/03 22:16:52 jjanke Exp $ + */ +public class MReportSource extends X_PA_ReportSource +{ + /** + * Constructor + * @param ctx context + * @param PA_ReportSource_ID id + * @param trxName transaction + */ + public MReportSource (Properties ctx, int PA_ReportSource_ID, String trxName) + { + super (ctx, PA_ReportSource_ID, trxName); + if (PA_ReportSource_ID == 0) + { + } + } // MReportSource + + /** + * Constructor + * @param ctx context + * @param rs ResultSet to load from + * @param trxName transaction + */ + public MReportSource (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MReportSource + + + /** + * Get SQL where clause + * @param PA_Hierarchy_ID hierarchy + * @return where clause + */ + public String getWhereClause(int PA_Hierarchy_ID) + { + String et = getElementType(); + // ID for Tree Leaf Value + int ID = 0; + // + if (MAcctSchemaElement.ELEMENTTYPE_Account.equals(et)) + ID = getC_ElementValue_ID (); + else if (MAcctSchemaElement.ELEMENTTYPE_Activity.equals(et)) + ID = getC_Activity_ID (); + else if (MAcctSchemaElement.ELEMENTTYPE_BPartner.equals(et)) + ID = getC_BPartner_ID (); + else if (MAcctSchemaElement.ELEMENTTYPE_Campaign.equals(et)) + ID = getC_Campaign_ID (); + else if (MAcctSchemaElement.ELEMENTTYPE_LocationFrom.equals(et)) + ID = getC_Location_ID (); + else if (MAcctSchemaElement.ELEMENTTYPE_LocationTo.equals(et)) + ID = getC_Location_ID (); + else if (MAcctSchemaElement.ELEMENTTYPE_Organization.equals(et)) + ID = getOrg_ID (); + else if (MAcctSchemaElement.ELEMENTTYPE_Product.equals(et)) + ID = getM_Product_ID (); + else if (MAcctSchemaElement.ELEMENTTYPE_Project.equals(et)) + ID = getC_Project_ID (); + else if (MAcctSchemaElement.ELEMENTTYPE_SalesRegion.equals(et)) + ID = getC_SalesRegion_ID (); + else if (MAcctSchemaElement.ELEMENTTYPE_OrgTrx.equals(et)) + ID = getOrg_ID (); // (re)uses Org_ID + else if (MAcctSchemaElement.ELEMENTTYPE_UserList1.equals(et)) + ID = getC_ElementValue_ID (); + else if (MAcctSchemaElement.ELEMENTTYPE_UserList2.equals(et)) + ID = getC_ElementValue_ID (); +// else if (MAcctSchemaElement.ELEMENTTYPE_UserElement1.equals(et)) +// ID = getUserElement1_ID (); +// else if (MAcctSchemaElement.ELEMENTTYPE_UserElement2.equals(et)) +// ID = getUserElement2_ID (); + // + return MReportTree.getWhereClause (getCtx(), PA_Hierarchy_ID, et, ID); + } // getWhereClause + + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MReportSource[") + .append(get_ID()).append(" - ").append(getDescription()) + .append(" - ").append(getElementType()); + sb.append ("]"); + return sb.toString (); + } // toString + + + /************************************************************************** + * Copy Constructor + * @param ctx context + * @param AD_Client_ID parent + * @param AD_Org_ID parent + * @param PA_ReportLine_ID parent + * @param source copy source + * @param trxName transaction + * @return Report Source + */ + public static MReportSource copy (Properties ctx, int AD_Client_ID, int AD_Org_ID, + int PA_ReportLine_ID, MReportSource source, String trxName) + { + MReportSource retValue = new MReportSource (ctx, 0, trxName); + MReportSource.copyValues(source, retValue, AD_Client_ID, AD_Org_ID); + retValue.setPA_ReportLine_ID(PA_ReportLine_ID); + return retValue; + } // copy + +} // MReportSource diff --git a/base/src/org/compiere/report/MReportTree.java b/base/src/org/compiere/report/MReportTree.java new file mode 100644 index 0000000000..ae0443f76c --- /dev/null +++ b/base/src/org/compiere/report/MReportTree.java @@ -0,0 +1,295 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; + +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Report Tree Model + * + * @author Jorg Janke + * @version $Id: MReportTree.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MReportTree +{ + /** + * Get Report Tree (cached) + * @param ctx context + * @param PA_Hierarchy_ID optional hierarchy + * @param ElementType Account Schema Element Type + * @return tree + */ + public static MReportTree get (Properties ctx, int PA_Hierarchy_ID, String ElementType) + { + String key = PA_Hierarchy_ID + ElementType; + MReportTree tree = (MReportTree)s_trees.get(key); + if (tree == null) + { + tree = new MReportTree (ctx, PA_Hierarchy_ID, ElementType); + s_trees.put(key, tree); + } + return tree; + } // get + + /** + * Get Where Clause + * @param ctx context + * @param PA_Hierarchy_ID optional hierarchy + * @param ElementType Account Schema Element Type + * @param ID leaf element id + * @return where clause + */ + public static String getWhereClause (Properties ctx, + int PA_Hierarchy_ID, String ElementType, int ID) + { + MReportTree tree = get (ctx, PA_Hierarchy_ID, ElementType); + return tree.getWhereClause(ID); + } // getWhereClause + + /** + * Get Child IDs + * @param ctx context + * @param PA_Hierarchy_ID optional hierarchie + * @param ElementType Account Schema Element Type + * @param ID id + * @return array of IDs + */ + public static Integer[] getChildIDs (Properties ctx, + int PA_Hierarchy_ID, String ElementType, int ID) + { + MReportTree tree = get (ctx, PA_Hierarchy_ID, ElementType); + return tree.getChildIDs(ID); + } // getChildIDs + + /** Map with Tree */ + private static CCache s_trees = new CCache("MReportTree", 20); + + + /************************************************************************** + * Report Tree + * @param ctx context + * @param PA_Hierarchy_ID optional hierarchy + * @param ElementType Account Schema Element Type + */ + public MReportTree (Properties ctx, int PA_Hierarchy_ID, String ElementType) + { + m_ElementType = ElementType; + m_TreeType = m_ElementType; + if (MAcctSchemaElement.ELEMENTTYPE_Account.equals(m_ElementType) + || MAcctSchemaElement.ELEMENTTYPE_UserList1.equals(m_ElementType) + || MAcctSchemaElement.ELEMENTTYPE_UserList2.equals(m_ElementType) ) + m_TreeType = MTree.TREETYPE_ElementValue; + m_PA_Hierarchy_ID = PA_Hierarchy_ID; + m_ctx = ctx; + // + int AD_Tree_ID = getAD_Tree_ID(); + // Not found + if (AD_Tree_ID == 0) + throw new IllegalArgumentException("No AD_Tree_ID for TreeType=" + m_TreeType + + ", PA_Hierarchy_ID=" + PA_Hierarchy_ID); + // + boolean clientTree = true; + m_tree = new MTree (ctx, AD_Tree_ID, false, clientTree, null); + } // MReportTree + + /** Optional Hierarchy */ + private int m_PA_Hierarchy_ID = 0; + /** Element Type */ + private String m_ElementType = null; + /** Context */ + private Properties m_ctx = null; + /** Tree Type */ + private String m_TreeType = null; + /** The Tree */ + private MTree m_tree = null; + /** Logger */ + private CLogger log = CLogger.getCLogger(getClass()); + + + /** + * Get AD_Tree_ID + * @return tree + */ + protected int getAD_Tree_ID () + { + if (m_PA_Hierarchy_ID == 0) + return getDefaultAD_Tree_ID(); + + MHierarchy hierarchy = MHierarchy.get(m_ctx, m_PA_Hierarchy_ID); + int AD_Tree_ID = hierarchy.getAD_Tree_ID (m_TreeType); + + if (AD_Tree_ID == 0) + return getDefaultAD_Tree_ID(); + + return AD_Tree_ID; + } // getAD_Tree_ID + + /** + * Get Default AD_Tree_ID + * see MTree.getDefaultAD_Tree_ID + * @return tree + */ + protected int getDefaultAD_Tree_ID() + { + int AD_Tree_ID = 0; + int AD_Client_ID = Env.getAD_Client_ID(m_ctx); + + String sql = "SELECT AD_Tree_ID, Name FROM AD_Tree " + + "WHERE AD_Client_ID=? AND TreeType=? AND IsActive='Y' AND IsAllNodes='Y' " + + "ORDER BY IsDefault DESC, AD_Tree_ID"; // assumes first is primary tree + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Client_ID); + pstmt.setString(2, m_TreeType); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + AD_Tree_ID = rs.getInt(1); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + + return AD_Tree_ID; + } // getDefaultAD_Tree_ID + + /** + * Get Account Schema Element Type + * @return element Type + */ + public String getElementType() + { + return m_ElementType; + } // getElementType + + /** + * Get Tree Type + * @return tree type + */ + public String getTreeType() + { + return m_TreeType; + } // getTreeType + + /** + * Get Tree + * @return tree + */ + public MTree getTree() + { + return m_tree; + } // getTreeType + + /** + * Get Where Clause + * @param ID start node + * @return ColumnName = 1 or ColumnName IN (1,2,3) + */ + public String getWhereClause (int ID) + { + log.fine("(" + m_ElementType + ") ID=" + ID); + String ColumnName = MAcctSchemaElement.getColumnName(m_ElementType); + // + MTreeNode node = m_tree.getRoot().findNode(ID); + log.finest("Root=" + node); + // + StringBuffer result = null; + if (node != null && node.isSummary()) + { + StringBuffer sb = new StringBuffer(); + Enumeration en = node.preorderEnumeration(); + while (en.hasMoreElements()) + { + MTreeNode nn = (MTreeNode)en.nextElement(); + if (!nn.isSummary()) + { + if (sb.length () > 0) + sb.append (","); + sb.append(nn.getNode_ID()); + log.finest("- " + nn); + } + else + log.finest("- skipped parent (" + nn + ")"); + } + result = new StringBuffer (ColumnName).append(" IN (").append(sb).append(")"); + } + else // not found or not summary + result = new StringBuffer (ColumnName).append("=").append(ID); + // + log.finest(result.toString()); + return result.toString(); + } // getWhereClause + + /** + * Get Child IDs + * @param ID start node + * @return array if IDs + */ + public Integer[] getChildIDs (int ID) + { + log.fine("(" + m_ElementType + ") ID=" + ID); + ArrayList list = new ArrayList(); + // + MTreeNode node = m_tree.getRoot().findNode(ID); + log.finest("Root=" + node); + // + if (node != null && node.isSummary()) + { + Enumeration en = node.preorderEnumeration(); + while (en.hasMoreElements()) + { + MTreeNode nn = (MTreeNode)en.nextElement(); + if (!nn.isSummary()) + { + list.add(new Integer(nn.getNode_ID())); + log.finest("- " + nn); + } + else + log.finest("- skipped parent (" + nn + ")"); + } + } + else // not found or not summary + list.add(new Integer(ID)); + // + Integer[] retValue = new Integer[list.size()]; + list.toArray(retValue); + return retValue; + } // getWhereClause + + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("MReportTree[ElementType="); + sb.append(m_ElementType).append(",TreeType=").append(m_TreeType) + .append(",").append(m_tree) + .append("]"); + return sb.toString(); + } // toString + +} // MReportTree diff --git a/base/src/org/compiere/report/TrialBalance.java b/base/src/org/compiere/report/TrialBalance.java new file mode 100644 index 0000000000..2e06356fca --- /dev/null +++ b/base/src/org/compiere/report/TrialBalance.java @@ -0,0 +1,458 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.model.*; +import org.compiere.process.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Trial Balance + * + * @author Jorg Janke + * @version $Id: TrialBalance.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class TrialBalance extends SvrProcess +{ + /** AcctSchame Parameter */ + private int p_C_AcctSchema_ID = 0; + /** Period Parameter */ + private int p_C_Period_ID = 0; + private Timestamp p_DateAcct_From = null; + private Timestamp p_DateAcct_To = null; + /** Org Parameter */ + private int p_AD_Org_ID = 0; + /** Account Parameter */ + private int p_Account_ID = 0; + private String p_AccountValue_From = null; + private String p_AccountValue_To = null; + /** BPartner Parameter */ + private int p_C_BPartner_ID = 0; + /** Product Parameter */ + private int p_M_Product_ID = 0; + /** Project Parameter */ + private int p_C_Project_ID = 0; + /** Activity Parameter */ + private int p_C_Activity_ID = 0; + /** SalesRegion Parameter */ + private int p_C_SalesRegion_ID = 0; + /** Campaign Parameter */ + private int p_C_Campaign_ID = 0; + /** Posting Type */ + private String p_PostingType = "A"; + /** Hierarchy */ + private int p_PA_Hierarchy_ID = 0; + + private int p_AD_OrgTrx_ID = 0; + private int p_C_LocFrom_ID = 0; + private int p_C_LocTo_ID = 0; + private int p_User1_ID = 0; + private int p_User2_ID = 0; + + + /** Parameter Where Clause */ + private StringBuffer m_parameterWhere = new StringBuffer(); + /** Account */ + private MElementValue m_acct = null; + + /** Start Time */ + private long m_start = System.currentTimeMillis(); + /** Insert Statement */ + private static String s_insert = "INSERT INTO T_TrialBalance " + + "(AD_PInstance_ID, Fact_Acct_ID," + + " AD_Client_ID, AD_Org_ID, Created,CreatedBy, Updated,UpdatedBy," + + " C_AcctSchema_ID, Account_ID, AccountValue, DateTrx, DateAcct, C_Period_ID," + + " AD_Table_ID, Record_ID, Line_ID," + + " GL_Category_ID, GL_Budget_ID, C_Tax_ID, M_Locator_ID, PostingType," + + " C_Currency_ID, AmtSourceDr, AmtSourceCr, AmtSourceBalance," + + " AmtAcctDr, AmtAcctCr, AmtAcctBalance, C_UOM_ID, Qty," + + " M_Product_ID, C_BPartner_ID, AD_OrgTrx_ID, C_LocFrom_ID,C_LocTo_ID," + + " C_SalesRegion_ID, C_Project_ID, C_Campaign_ID, C_Activity_ID," + + " User1_ID, User2_ID, A_Asset_ID, Description)"; + + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + StringBuffer sb = new StringBuffer ("AD_PInstance_ID=") + .append(getAD_PInstance_ID()); + // Parameter + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("C_AcctSchema_ID")) + p_C_AcctSchema_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_Period_ID")) + p_C_Period_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("DateAcct")) + { + p_DateAcct_From = (Timestamp)para[i].getParameter(); + p_DateAcct_To = (Timestamp)para[i].getParameter_To(); + } + else if (name.equals("PA_Hierarchy_ID")) + p_PA_Hierarchy_ID = para[i].getParameterAsInt(); + else if (name.equals("AD_Org_ID")) + p_AD_Org_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("Account_ID")) + p_Account_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("AccountValue")) + { + p_AccountValue_From = (String)para[i].getParameter(); + p_AccountValue_To = (String)para[i].getParameter_To(); + } + else if (name.equals("C_BPartner_ID")) + p_C_BPartner_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("M_Product_ID")) + p_M_Product_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_Project_ID")) + p_C_Project_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_Activity_ID")) + p_C_Activity_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_SalesRegion_ID")) + p_C_SalesRegion_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("C_Campaign_ID")) + p_C_Campaign_ID = ((BigDecimal)para[i].getParameter()).intValue(); + else if (name.equals("PostingType")) + p_PostingType = (String)para[i].getParameter(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + // Mandatory C_AcctSchema_ID + m_parameterWhere.append("C_AcctSchema_ID=").append(p_C_AcctSchema_ID); + // Optional Account_ID + if (p_Account_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID,MAcctSchemaElement.ELEMENTTYPE_Account, p_Account_ID)); + if (p_AccountValue_From != null && p_AccountValue_From.length() == 0) + p_AccountValue_From = null; + if (p_AccountValue_To != null && p_AccountValue_To.length() == 0) + p_AccountValue_To = null; + if (p_AccountValue_From != null && p_AccountValue_To != null) + m_parameterWhere.append(" AND (Account_ID IS NULL OR EXISTS (SELECT * FROM C_ElementValue ev ") + .append("WHERE Account_ID=ev.C_ElementValue_ID AND ev.Value >= ") + .append(DB.TO_STRING(p_AccountValue_From)).append(" AND ev.Value <= ") + .append(DB.TO_STRING(p_AccountValue_To)).append("))"); + else if (p_AccountValue_From != null && p_AccountValue_To == null) + m_parameterWhere.append(" AND (Account_ID IS NULL OR EXISTS (SELECT * FROM C_ElementValue ev ") + .append("WHERE Account_ID=ev.C_ElementValue_ID AND ev.Value >= ") + .append(DB.TO_STRING(p_AccountValue_From)).append("))"); + else if (p_AccountValue_From == null && p_AccountValue_To != null) + m_parameterWhere.append(" AND (Account_ID IS NULL OR EXISTS (SELECT * FROM C_ElementValue ev ") + .append("WHERE Account_ID=ev.C_ElementValue_ID AND ev.Value <= ") + .append(DB.TO_STRING(p_AccountValue_To)).append("))"); + // Optional Org + if (p_AD_Org_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_Organization, p_AD_Org_ID)); + // Optional BPartner + if (p_C_BPartner_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_BPartner, p_C_BPartner_ID)); + // Optional Product + if (p_M_Product_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_Product, p_M_Product_ID)); + // Optional Project + if (p_C_Project_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_Project, p_C_Project_ID)); + // Optional Activity + if (p_C_Activity_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_Activity, p_C_Activity_ID)); + // Optional Campaign + if (p_C_Campaign_ID != 0) + m_parameterWhere.append(" AND C_Campaign_ID=").append(p_C_Campaign_ID); + // m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + // MAcctSchemaElement.ELEMENTTYPE_Campaign, p_C_Campaign_ID)); + // Optional Sales Region + if (p_C_SalesRegion_ID != 0) + m_parameterWhere.append(" AND ").append(MReportTree.getWhereClause(getCtx(), + p_PA_Hierarchy_ID, MAcctSchemaElement.ELEMENTTYPE_SalesRegion, p_C_SalesRegion_ID)); + // Mandatory Posting Type + m_parameterWhere.append(" AND PostingType='").append(p_PostingType).append("'"); + // + setDateAcct(); + sb.append(" - DateAcct ").append(p_DateAcct_From).append("-").append(p_DateAcct_To); + sb.append(" - Where=").append(m_parameterWhere); + log.fine(sb.toString()); + } // prepare + + /** + * Set Start/End Date of Report - if not defined current Month + */ + private void setDateAcct() + { + // Date defined + if (p_DateAcct_From != null) + { + if (p_DateAcct_To == null) + p_DateAcct_To = new Timestamp (System.currentTimeMillis()); + return; + } + // Get Date from Period + if (p_C_Period_ID == 0) + { + GregorianCalendar cal = new GregorianCalendar(Language.getLoginLanguage().getLocale()); + cal.setTimeInMillis(System.currentTimeMillis()); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + cal.set(Calendar.DAY_OF_MONTH, 1); // set to first of month + p_DateAcct_From = new Timestamp (cal.getTimeInMillis()); + cal.add(Calendar.MONTH, 1); + cal.add(Calendar.DAY_OF_YEAR, -1); // last of month + p_DateAcct_To = new Timestamp (cal.getTimeInMillis()); + return; + } + + String sql = "SELECT StartDate, EndDate FROM C_Period WHERE C_Period_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, p_C_Period_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + p_DateAcct_From = rs.getTimestamp(1); + p_DateAcct_To = rs.getTimestamp(2); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + } // setDateAcct + + + /************************************************************************** + * Perform process. + * @return Message to be translated + */ + protected String doIt() + { + createBalanceLine(); + createDetailLines(); + + // int AD_PrintFormat_ID = 134; + // getProcessInfo().setTransientObject (MPrintFormat.get (getCtx(), AD_PrintFormat_ID, false)); + + log.fine((System.currentTimeMillis() - m_start) + " ms"); + return ""; + } // doIt + + /** + * Create Beginning Balance Line + */ + private void createBalanceLine() + { + StringBuffer sql = new StringBuffer (s_insert); + // (AD_PInstance_ID, Fact_Acct_ID, + sql.append("SELECT ").append(getAD_PInstance_ID()).append(",0,"); + // AD_Client_ID, AD_Org_ID, Created,CreatedBy, Updated,UpdatedBy, + sql.append(getAD_Client_ID()).append(","); + if (p_AD_Org_ID == 0) + sql.append("0"); + else + sql.append(p_AD_Org_ID); + sql.append(", SysDate,").append(getAD_User_ID()) + .append(",SysDate,").append(getAD_User_ID()).append(","); + // C_AcctSchema_ID, Account_ID, AccountValue, DateTrx, DateAcct, C_Period_ID, + sql.append(p_C_AcctSchema_ID).append(","); + if (p_Account_ID == 0) + sql.append ("null"); + else + sql.append (p_Account_ID); + if (p_AccountValue_From != null) + sql.append(",").append(DB.TO_STRING(p_AccountValue_From)); + else if (p_AccountValue_To != null) + sql.append(",' '"); + else + sql.append(",null"); + Timestamp balanceDay = p_DateAcct_From; // TimeUtil.addDays(p_DateAcct_From, -1); + sql.append(",null,").append(DB.TO_DATE(balanceDay, true)).append(","); + if (p_C_Period_ID == 0) + sql.append("null"); + else + sql.append(p_C_Period_ID); + sql.append(","); + // AD_Table_ID, Record_ID, Line_ID, + sql.append("null,null,null,"); + // GL_Category_ID, GL_Budget_ID, C_Tax_ID, M_Locator_ID, PostingType, + sql.append("null,null,null,null,'").append(p_PostingType).append("',"); + // C_Currency_ID, AmtSourceDr, AmtSourceCr, AmtSourceBalance, + sql.append("null,null,null,null,"); + // AmtAcctDr, AmtAcctCr, AmtAcctBalance, C_UOM_ID, Qty, + sql.append(" COALESCE(SUM(AmtAcctDr),0),COALESCE(SUM(AmtAcctCr),0)," + + "COALESCE(SUM(AmtAcctDr),0)-COALESCE(SUM(AmtAcctCr),0)," + + " null,COALESCE(SUM(Qty),0),"); + // M_Product_ID, C_BPartner_ID, AD_OrgTrx_ID, C_LocFrom_ID,C_LocTo_ID, + if (p_M_Product_ID == 0) + sql.append ("null"); + else + sql.append (p_M_Product_ID); + sql.append(","); + if (p_C_BPartner_ID == 0) + sql.append ("null"); + else + sql.append (p_C_BPartner_ID); + sql.append(","); + if (p_AD_OrgTrx_ID == 0) + sql.append ("null"); + else + sql.append (p_AD_OrgTrx_ID); + sql.append(","); + if (p_C_LocFrom_ID == 0) + sql.append ("null"); + else + sql.append (p_C_LocFrom_ID); + sql.append(","); + if (p_C_LocTo_ID == 0) + sql.append ("null"); + else + sql.append (p_C_LocTo_ID); + sql.append(","); + // C_SalesRegion_ID, C_Project_ID, C_Campaign_ID, C_Activity_ID, + if (p_C_SalesRegion_ID == 0) + sql.append ("null"); + else + sql.append (p_C_SalesRegion_ID); + sql.append(","); + if (p_C_Project_ID == 0) + sql.append ("null"); + else + sql.append (p_C_Project_ID); + sql.append(","); + if (p_C_Campaign_ID == 0) + sql.append ("null"); + else + sql.append (p_C_Campaign_ID); + sql.append(","); + if (p_C_Activity_ID == 0) + sql.append ("null"); + else + sql.append (p_C_Activity_ID); + sql.append(","); + // User1_ID, User2_ID, A_Asset_ID, Description) + if (p_User1_ID == 0) + sql.append ("null"); + else + sql.append (p_User1_ID); + sql.append(","); + if (p_User2_ID == 0) + sql.append ("null"); + else + sql.append (p_User2_ID); + sql.append(", null,null"); + // + sql.append(" FROM Fact_Acct WHERE AD_Client_ID=").append(getAD_Client_ID()) + .append (" AND ").append(m_parameterWhere) + .append(" AND DateAcct < ").append(DB.TO_DATE(p_DateAcct_From, true)); + // Start Beginning of Year + if (p_Account_ID > 0) + { + m_acct = new MElementValue (getCtx(), p_Account_ID, get_TrxName()); + if (!m_acct.isBalanceSheet()) + { + MPeriod first = MPeriod.getFirstInYear (getCtx(), p_DateAcct_From); + if (first != null) + sql.append(" AND DateAcct >= ").append(DB.TO_DATE(first.getStartDate(), true)); + else + log.log(Level.SEVERE, "first period not found"); + } + } + // + int no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no == 0) + log.fine(sql.toString()); + log.fine("#" + no + " (Account_ID=" + p_Account_ID + ")"); + } // createBalanceLine + + /** + * Create Beginning Balance Line + */ + private void createDetailLines() + { + StringBuffer sql = new StringBuffer (s_insert); + // (AD_PInstance_ID, Fact_Acct_ID, + sql.append("SELECT ").append(getAD_PInstance_ID()).append(",Fact_Acct_ID,"); + // AD_Client_ID, AD_Org_ID, Created,CreatedBy, Updated,UpdatedBy, + sql.append(getAD_Client_ID()).append(",AD_Org_ID,Created,CreatedBy, Updated,UpdatedBy,"); + // C_AcctSchema_ID, Account_ID, DateTrx, AccountValue, DateAcct, C_Period_ID, + sql.append("C_AcctSchema_ID, Account_ID, null, DateTrx, DateAcct, C_Period_ID,"); + // AD_Table_ID, Record_ID, Line_ID, + sql.append("AD_Table_ID, Record_ID, Line_ID,"); + // GL_Category_ID, GL_Budget_ID, C_Tax_ID, M_Locator_ID, PostingType, + sql.append("GL_Category_ID, GL_Budget_ID, C_Tax_ID, M_Locator_ID, PostingType,"); + // C_Currency_ID, AmtSourceDr, AmtSourceCr, AmtSourceBalance, + sql.append("C_Currency_ID, AmtSourceDr,AmtSourceCr, AmtSourceDr-AmtSourceCr,"); + // AmtAcctDr, AmtAcctCr, AmtAcctBalance, C_UOM_ID, Qty, + sql.append(" AmtAcctDr,AmtAcctCr, AmtAcctDr-AmtAcctCr, C_UOM_ID,Qty,"); + // M_Product_ID, C_BPartner_ID, AD_OrgTrx_ID, C_LocFrom_ID,C_LocTo_ID, + sql.append ("M_Product_ID, C_BPartner_ID, AD_OrgTrx_ID, C_LocFrom_ID,C_LocTo_ID,"); + // C_SalesRegion_ID, C_Project_ID, C_Campaign_ID, C_Activity_ID, + sql.append ("C_SalesRegion_ID, C_Project_ID, C_Campaign_ID, C_Activity_ID,"); + // User1_ID, User2_ID, A_Asset_ID, Description) + sql.append ("User1_ID, User2_ID, A_Asset_ID, Description"); + // + sql.append(" FROM Fact_Acct WHERE AD_Client_ID=").append(getAD_Client_ID()) + .append (" AND ").append(m_parameterWhere) + .append(" AND DateAcct >= ").append(DB.TO_DATE(p_DateAcct_From, true)) + .append(" AND TRUNC(DateAcct) <= ").append(DB.TO_DATE(p_DateAcct_To, true)); + // + int no = DB.executeUpdate(sql.toString(), get_TrxName()); + if (no == 0) + log.fine(sql.toString()); + log.fine("#" + no + " (Account_ID=" + p_Account_ID + ")"); + + // Update AccountValue + String sql2 = "UPDATE T_TrialBalance tb SET AccountValue = " + + "(SELECT Value FROM C_ElementValue ev WHERE ev.C_ElementValue_ID=tb.Account_ID) " + + "WHERE tb.Account_ID IS NOT NULL"; + no = DB.executeUpdate(sql2, get_TrxName()); + if (no > 0) + log.fine("Set AccountValue #" + no); + + } // createDetailLines + +} // TrialBalance diff --git a/base/src/org/compiere/report/core/RColumn.java b/base/src/org/compiere/report/core/RColumn.java new file mode 100644 index 0000000000..2408ba3d84 --- /dev/null +++ b/base/src/org/compiere/report/core/RColumn.java @@ -0,0 +1,307 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report.core; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Report Column + * + * @author Jorg Janke + * @version $Id: RColumn.java,v 1.3 2006/08/10 01:00:13 jjanke Exp $ + */ +public class RColumn +{ + /** + * Create Report Column + * @param ctx context + * @param columnName column name + * @param displayType display type + */ + public RColumn (Properties ctx, String columnName, int displayType) + { + this (ctx, columnName, displayType, null, 0, null); + } // RColumn + + /** + * Create Report Column + * @param ctx context + * @param columnName column name + * @param displayType display type + * @param AD_Reference_Value_ID List/Table Reference + */ + public RColumn (Properties ctx, String columnName, int displayType, int AD_Reference_Value_ID) + { + this (ctx, columnName, displayType, null, AD_Reference_Value_ID, null); + } // RColumn + + /** + * Create Report Column + * @param ctx context + * @param columnName column name + * @param displayType display type + * @param sql sql (if null then columnName is used). + * Will be overwritten if TableDir or Search + */ + public RColumn (Properties ctx, String columnName, int displayType, String sql) + { + this (ctx, columnName, displayType, sql, 0, null); + } + /** + * Create Report Column + * @param ctx context + * @param columnName column name + * @param displayType display type + * @param sql sql (if null then columnName is used). + * @param AD_Reference_Value_ID List/Table Reference + * @param refColumnName UserReference column name + * Will be overwritten if TableDir or Search + */ + public RColumn (Properties ctx, String columnName, int displayType, + String sql, int AD_Reference_Value_ID, String refColumnName) + { + m_colHeader = Msg.translate(ctx, columnName); + if (refColumnName != null) + m_colHeader = Msg.translate(ctx, refColumnName); + m_displayType = displayType; + m_colSQL = sql; + if (m_colSQL == null || m_colSQL.length() == 0) + m_colSQL = columnName; + + // Strings + if (DisplayType.isText(displayType)) + m_colClass = String.class; // default size=30 + // Amounts + else if (displayType == DisplayType.Amount) + { + m_colClass = BigDecimal.class; + m_colSize = 70; + } + // Boolean + else if (displayType == DisplayType.YesNo) + m_colClass = Boolean.class; + // Date + else if (DisplayType.isDate(displayType)) + m_colClass = Timestamp.class; + // Number + else if (displayType == DisplayType.Quantity + || displayType == DisplayType.Number + || displayType == DisplayType.CostPrice) + { + m_colClass = Double.class; + m_colSize = 70; + } + // Integer + else if (displayType == DisplayType.Integer) + m_colClass = Integer.class; + // List + else if (displayType == DisplayType.List) + { + Language language = Language.getLanguage(Env.getAD_Language(ctx)); + m_colSQL = "(" + MLookupFactory.getLookup_ListEmbed( + language, AD_Reference_Value_ID, columnName) + ")"; + m_colClass = String.class; + m_isIDcol = false; + } + /** Table + else if (displayType == DisplayType.Table) + { + Language language = Language.getLanguage(Env.getAD_Language(ctx)); + m_colSQL += ",(" + MLookupFactory.getLookup_TableEmbed( + language, columnName, RModel.TABLE_ALIAS, AD_Reference_Value_ID) + ")"; + m_colClass = String.class; + m_isIDcol = false; + } **/ + // TableDir, Search,... + else + { + m_colClass = String.class; + Language language = Language.getLanguage(Env.getAD_Language(ctx)); + if (columnName.equals("Account_ID") + || columnName.equals("User1_ID") || columnName.equals("User2_ID")) + { + m_colSQL += ",(" + MLookupFactory.getLookup_TableDirEmbed( + language, "C_ElementValue_ID", RModel.TABLE_ALIAS, columnName) + ")"; + m_isIDcol = true; + } + else if (columnName.startsWith("UserElement") && refColumnName != null) + { + m_colSQL += ",(" + MLookupFactory.getLookup_TableDirEmbed( + language, refColumnName, RModel.TABLE_ALIAS, columnName) + ")"; + m_isIDcol = true; + } + else if (columnName.equals("C_LocFrom_ID") || columnName.equals("C_LocTo_ID")) + { + m_colSQL += ",(" + MLookupFactory.getLookup_TableDirEmbed( + language, "C_Location_ID", RModel.TABLE_ALIAS, columnName) + ")"; + m_isIDcol = true; + } + else if (columnName.equals("AD_OrgTrx_ID")) + { + m_colSQL += ",(" + MLookupFactory.getLookup_TableDirEmbed( + language, "AD_Org_ID", RModel.TABLE_ALIAS, columnName) + ")"; + m_isIDcol = true; + } + else if (displayType == DisplayType.TableDir) + { + m_colSQL += ",(" + MLookupFactory.getLookup_TableDirEmbed( + language, columnName, RModel.TABLE_ALIAS) + ")"; + m_isIDcol = true; + } + } + } // RColumn + + /** + * Create Info Column (r/o and not color column) + * + * @param colHeader Column Header + * @param colSQL SQL select code for column + * @param colClass class of column - determines display + */ + public RColumn (String colHeader, String colSQL, Class colClass) + { + m_colHeader = colHeader; + m_colSQL = colSQL; + m_colClass = colClass; + } // RColumn + + + /** Column Header */ + private String m_colHeader; + /** Column SQL */ + private String m_colSQL; + /** Column Display Class */ + private Class m_colClass; + + /** Display Type */ + private int m_displayType = 0; + /** Column Size im px */ + private int m_colSize = 30; + + private boolean m_readOnly = true; + private boolean m_colorColumn = false; + private boolean m_isIDcol = false; + + + /** + * Column Header + */ + public String getColHeader() + { + return m_colHeader; + } + public void setColHeader(String colHeader) + { + m_colHeader = colHeader; + } + + /** + * Column SQL + */ + public String getColSQL() + { + return m_colSQL; + } + public void setColSQL(String colSQL) + { + m_colSQL = colSQL; + } + /** + * This column is an ID Column (i.e. two values - int & String are read) + */ + public boolean isIDcol() + { + return m_isIDcol; + } + + /** + * Column Display Class + */ + public Class getColClass() + { + return m_colClass; + } + public void setColClass(Class colClass) + { + m_colClass = colClass; + } + + /** + * Column Size in px + */ + public int getColSize() + { + return m_colSize; + } // getColumnSize + + /** + * Column Size in px + */ + public void setColSize(int colSize) + { + m_colSize = colSize; + } // getColumnSize + + /** + * Get DisplayType + */ + public int getDisplayType() + { + return m_displayType; + } // getDisplayType + + /** + * Column is Readonly + */ + public boolean isReadOnly() + { + return m_readOnly; + } + public void setReadOnly(boolean readOnly) + { + m_readOnly = readOnly; + } + + /** + * This Color Determines the Color of the row + */ + public void setColorColumn(boolean colorColumn) + { + m_colorColumn = colorColumn; + } + public boolean isColorColumn() + { + return m_colorColumn; + } + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("RColumn["); + sb.append(m_colSQL).append("=").append(m_colHeader) + .append("]"); + return sb.toString(); + } // toString + +} // RColumn diff --git a/base/src/org/compiere/report/core/RModel.java b/base/src/org/compiere/report/core/RModel.java new file mode 100644 index 0000000000..0a1b725e49 --- /dev/null +++ b/base/src/org/compiere/report/core/RModel.java @@ -0,0 +1,367 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report.core; + +import java.io.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Report Model. + * Data is maintained in RModelData + * + * @author Jorg Janke + * @version $Id: RModel.java,v 1.2 2006/07/30 00:51:06 jjanke Exp $ + */ +public class RModel implements Serializable +{ + /** + * Constructor. Creates RModelData + * @param TableName + */ + public RModel (String TableName) + { + m_data = new RModelData (TableName); + } // RModel + + /** Table Alias for SQL */ + public static final String TABLE_ALIAS = "zz"; + /** Function: Count */ + public static final String FUNCTION_COUNT = "Count"; + /** Function: Sum */ + public static final String FUNCTION_SUM = "Sum"; + + /** Helper to retrieve Actual Data */ + private RModelData m_data = null; + /** Is Content editable by user */ + private boolean m_editable = false; + + /** Logger */ + private static CLogger log = CLogger.getCLogger(RModel.class); + + /************************************************************************** + * Get Column Display Name + * @param col + * @return RColumn + */ + protected RColumn getRColumn (int col) + { + if (col < 0 || col > m_data.cols.size()) + throw new java.lang.IllegalArgumentException("Column invalid"); + return (RColumn)m_data.cols.get(col); + } // getRColumn + + + /************************************************************************** + * Add Column + * @param rc + */ + public void addColumn (RColumn rc) + { + m_data.cols.add(rc); + } // addColumn + + /** + * Add Column at Index + * @param rc + * @param index + */ + public void addColumn (RColumn rc, int index) + { + m_data.cols.add(index, rc); + } // addColumn + + /** + * Add Row + */ + public void addRow () + { + m_data.rows.add(new ArrayList()); + m_data.rowsMeta.add(null); + } // addRow + + /** + * Add Row at Index + * @param index + */ + public void addRow (int index) + { + m_data.rows.add(index, new ArrayList()); + m_data.rowsMeta.add(index, null); + } // addRow + + /** + * Add Row + * @param l + */ + public void addRow (ArrayList l) + { + m_data.rows.add(l); + m_data.rowsMeta.add(null); + } // addRow + + /** + * Add Row at Index + * @param l + * @param index + */ + public void addRow (ArrayList l, int index) + { + m_data.rows.add(index, l); + m_data.rowsMeta.add(index, null); + } // addRow + + /** + * Find index for ColumnName + * @param columnName + * @return index or -1 if not found + */ + public int getColumnIndex (String columnName) + { + if (columnName == null || columnName.length() == 0) + return -1; + // + for (int i = 0; i < m_data.cols.size(); i++) + { + RColumn rc = (RColumn)m_data.cols.get(i); + // log.fine( "Column " + i + " " + rc.getColSQL() + " ? " + columnName); + if (rc.getColSQL().startsWith(columnName)) + { + log.fine( "Column " + i + " " + rc.getColSQL() + " = " + columnName); + return i; + } + } + return -1; + } // getColumnIndex + + + /************************************************************************** + * Query + * @param ctx + * @param whereClause + * @param orderClause + */ + public void query (Properties ctx, String whereClause, String orderClause) + { + m_data.query (ctx, whereClause, orderClause); + } // query + + + /************************************************************************** + * Set a group column + * @param columnName + */ + public void setGroup (String columnName) + { + setGroup(getColumnIndex(columnName)); + } // setGroup + + /** + * Set a group column - + * if the group value changes, a new row in inserted + * performing the calculations set in setGroupFunction(). + * If you set multiple groups, start with the highest level + * (e.g. Country, Region, City) + * The data is assumed to be sorted to result in meaningful groups. + *
+	 *  A AA 1
+	 *  A AB 2
+	 *  B BA 3
+	 *  B BB 4
+	 *  after setGroup (0)
+	 *  A AA 1
+	 *  A AB 2
+	 *  A
+	 *  B BA 3
+	 *  B BB 4
+	 *  B
+	 *  
+ * @param col The Group BY Column + */ + public void setGroup (int col) + { + log.config( "RModel.setGroup col=" + col); + if (col < 0 || col >= m_data.cols.size()) + return; + Integer ii = new Integer(col); + if (!m_data.groups.contains(ii)) + m_data.groups.add(ii); + } // setGroup + + /** + * Is Row a Group Row + * @param row index + * @return true if row is a group row + */ + public boolean isGroupRow (int row) + { + return m_data.isGroupRow(row); + } // isGroupRow + + /** + * Set Group Function + * @param columnName + * @param function + */ + public void setFunction (String columnName, String function) + { + setFunction(getColumnIndex(columnName), function); + } // setFunction + + /** + * Set Group Function - + * for the column, set a function like FUNCTION_SUM, FUNCTION_COUNT, ... + * @param col The column on which the function is performed + * @param function The function + */ + public void setFunction (int col, String function) + { + log.config( "RModel.setFunction col=" + col + " - " + function); + if (col < 0 || col >= m_data.cols.size()) + return; + m_data.functions.put(new Integer(col), function); + } // setFunction + + /*************************************************************************/ + // TableModel interface + + /** + * Return Total mumber of rows + * @return row count + */ + public int getRowCount() + { + return m_data.rows.size(); + } // getRowCount + + /** + * Get total number of columns + * @return column count + */ + public int getColumnCount() + { + return m_data.cols.size(); + } // getColumnCount + + /** + * Get Column Display Name + * @param col index + * @return ColumnName + */ + public String getColumnName (int col) + { + if (col < 0 || col > m_data.cols.size()) + throw new java.lang.IllegalArgumentException("Column invalid"); + RColumn rc = (RColumn)m_data.cols.get(col); + if (rc != null) + return rc.getColHeader(); + return null; + } // getColumnName + + /** + * Get Column Class + * @param col index + * @return Column Class + */ + public Class getColumnClass (int col) + { + if (col < 0 || col > m_data.cols.size()) + throw new java.lang.IllegalArgumentException("Column invalid"); + RColumn rc = (RColumn)m_data.cols.get(col); + if (rc != null) + return rc.getColClass(); + return null; + } // getColumnC;ass + + /** + * Is Cell Editable + * @param rowIndex + * @param columnIndex + * @return true, if editable + */ + public boolean isCellEditable (int rowIndex, int columnIndex) + { + return m_editable; + } // isCellEditable + + /** + * Get Value At + * @param row + * @param col + * @return value + */ + public Object getValueAt(int row, int col) + { + // invalid row + if (row < 0 || row >= m_data.rows.size()) + return null; + // throw new java.lang.IllegalArgumentException("Row invalid"); + if (col < 0 || col >= m_data.cols.size()) + return null; + // throw new java.lang.IllegalArgumentException("Column invalid"); + // + ArrayList myRow = (ArrayList)m_data.rows.get(row); + // invalid column + if (myRow == null || col >= myRow.size()) + return null; + // setValue + return myRow.get(col); + } // getValueAt + + /** + * Set Value At + * @param aValue + * @param row + * @param col + * @throws IllegalArgumentException if row/column is invalid or cell is read only + */ + public void setValueAt(Object aValue, int row, int col) + { + // invalid row + if (row < 0 || row >= m_data.rows.size()) + throw new IllegalArgumentException("Row invalid"); + if (col < 0 || col >= m_data.cols.size()) + throw new IllegalArgumentException("Column invalid"); + if (!isCellEditable(row, col)) + throw new IllegalArgumentException("Cell is read only"); + // + ArrayList myRow = m_data.rows.get(row); + // invalid row + if (myRow == null) + throw new java.lang.IllegalArgumentException("Row not initialized"); + // not enough columns - add nulls + if (col >= myRow.size()) + while (myRow.size() < m_data.cols.size()) + myRow.add(null); + // setValue + myRow.set(col, aValue); + } // setValueAt + + /** + * Move Row + * @param from index + * @param to index + */ + public void moveRow (int from, int to) + { + m_data.moveRow(from,to); + } // moveRow + + + /*************************************************************************/ + +} // RModel diff --git a/base/src/org/compiere/report/core/RModelData.java b/base/src/org/compiere/report/core/RModelData.java new file mode 100644 index 0000000000..5b9e9b3d66 --- /dev/null +++ b/base/src/org/compiere/report/core/RModelData.java @@ -0,0 +1,389 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report.core; + +import java.math.*; +import java.sql.*; +import java.util.*; +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Report Model Data - ValueObject. + * - Build SQL from RColumn info and Retrieve Data + * - owned by RModel + * + * @author Jorg Janke + * @version $Id: RModelData.java,v 1.2 2006/07/30 00:51:06 jjanke Exp $ + */ +class RModelData +{ + /** + * Constructor. Use query method to populate data + * @param TableName + */ + public RModelData (String TableName) + { + m_TableName = TableName; + } // RModelData + + /** The Rows */ + public ArrayList> rows = new ArrayList>(); + /** The temporary Rows */ + private ArrayList> m_rows = new ArrayList>(); + + /** The Row MetaData */ + public ArrayList rowsMeta = new ArrayList(); + /** The Column Definitions */ + public ArrayList cols = new ArrayList(); + + + /** Table Name */ + private String m_TableName; + + /** Functions (Integer - String) */ + public HashMap functions = new HashMap(); + /** Groups (Integer) */ + public ArrayList groups = new ArrayList(); + + /** Array with row numbers that are groups */ + private ArrayList m_groupRows = new ArrayList(); + private ArrayList m_groupRowsIndicator = null; + + /** Constant 1 */ + private static final BigDecimal ONE = new BigDecimal(1.0); + + /** Logger */ + private static CLogger log = CLogger.getCLogger(RModelData.class); + + /** + * Dispose + */ + public void dispose() + { + rows.clear(); + m_rows.clear(); + rowsMeta.clear(); + cols.clear(); + } // dispose + + /************************************************************************** + * Query + * @param ctx + * @param whereClause the SQL where clause (w/o the WHERE) + * @param orderClause + */ + public void query (Properties ctx, String whereClause, String orderClause) + { + RColumn rc = null; + // Create SQL + StringBuffer sql = new StringBuffer ("SELECT "); + int size = cols.size(); + for (int i = 0; i < size; i++) + { + rc = (RColumn)cols.get(i); + if (i > 0) + sql.append(","); + sql.append(rc.getColSQL()); + } + sql.append(" FROM ").append(m_TableName).append(" ").append(RModel.TABLE_ALIAS); + if (whereClause != null && whereClause.length() > 0) + sql.append(" WHERE ").append(whereClause); + String finalSQL = MRole.getDefault(ctx, false).addAccessSQL( + sql.toString(), RModel.TABLE_ALIAS, MRole.SQL_FULLYQUALIFIED, MRole.SQL_RO); + if (orderClause != null && orderClause.length() > 0) + finalSQL += " ORDER BY " + orderClause; + log.fine(finalSQL); + + // FillData + int index = 0; // rowset index + m_rows.clear(); + try + { + Statement stmt = DB.createStatement(); + ResultSet rs = stmt.executeQuery(finalSQL); + while (rs.next()) + { + ArrayList row = new ArrayList(size); + index = 1; + // Columns + for (int i = 0; i < size; i++) + { + rc = (RColumn)cols.get(i); + // Get ID + if (rc.isIDcol()) + row.add(new KeyNamePair (rs.getInt(index++), rs.getString(index++))); + // Null check + else if (rs.getObject(index) == null) + { + index++; + row.add(null); + } + else if (rc.getColClass() == String.class) + row.add(rs.getString(index++)); + else if (rc.getColClass() == BigDecimal.class) + row.add(rs.getBigDecimal(index++)); + else if (rc.getColClass() == Double.class) + row.add(new Double(rs.getDouble(index++))); + else if (rc.getColClass() == Integer.class) + row.add(new Integer(rs.getInt(index++))); + else if (rc.getColClass() == Timestamp.class) + row.add(rs.getTimestamp(index++)); + else if (rc.getColClass() == Boolean.class) + row.add(new Boolean("Y".equals(rs.getString(index++)))); + else // should not happen + { + row.add(rs.getString(index++)); + } + } + m_rows.add(row); + } + rs.close(); + stmt.close(); + } + catch (SQLException e) + { + if (index == 0) + log.log(Level.SEVERE, finalSQL, e); + else + log.log(Level.SEVERE, "Index=" + index + "," + rc, e); + e.printStackTrace(); + } + process(); + } // query + + /** + * Process Data + * Copy data in m_rows to rows and perform functions + */ + private void process() + { + log.fine("Start Rows=" + m_rows.size()); + + // Row level Funcions + // would come here + + // Group by Values + int gSize = groups.size(); + int[] groupBys = new int[gSize]; + Object[] groupBysValue = new Object[gSize]; + Object INITVALUE = new Object(); + for (int i = 0; i < gSize; i++) + { + groupBys[i] = ((Integer)groups.get(i)).intValue(); + groupBysValue[i] = INITVALUE; + log.fine("GroupBy level=" + i + " col=" + groupBys[i]); + } + // Add additional row to force group change + if (gSize > 0) + { + ArrayList newRow = new ArrayList(); + for (int c = 0; c < cols.size(); c++) + newRow.add(""); + m_rows.add(newRow); + } + + // Function Values - Function - GroupValue + int fSize = functions.size(); + int[] funcCols = new int[fSize]; + String[] funcFuns = new String[fSize]; + int index = 0; + Iterator it = functions.keySet().iterator(); + while (it.hasNext()) + { + Object key = it.next(); + funcCols[index] = ((Integer)key).intValue(); + funcFuns[index] = functions.get(key).toString(); + log.fine("Function " + funcFuns[index] + " col=" + funcCols[index]); + index++; + } + BigDecimal[][] funcVals = new BigDecimal [fSize][gSize+1]; + int totalIndex = gSize; // place for overall total + log.fine("FunctionValues = [ " + fSize + " * " + (gSize+1) + " ]"); + for (int f = 0; f < fSize; f++) + for (int g = 0; g < gSize+1; g++) + funcVals[f][g] = Env.ZERO; + + rows.clear(); + // Copy m_rows into rows + for (int r = 0; r < m_rows.size(); r++) + { + ArrayList row = m_rows.get(r); + // do we have a group break + boolean[] haveBreak = new boolean[groupBys.length]; + for (int level = 0; level < groupBys.length; level ++) + { + int idx = groupBys[level]; + if (groupBysValue[level] == INITVALUE) + haveBreak[level] = false; + else if (!groupBysValue[level].equals(row.get(idx))) + haveBreak[level] = true; + else + haveBreak[level] = false; + // previous level had a break + if (level > 0 && haveBreak[level-1]) + haveBreak[level] = true; + } + // create group levels - reverse order + for (int level = groupBys.length-1; level >= 0; level--) + { + int idx = groupBys[level]; + if (groupBysValue[level] == INITVALUE) + groupBysValue[level] = row.get(idx); + else if (haveBreak[level]) + { + // log.fine( "GroupBy Change level=" + level + " col=" + idx + " - " + groupBysValue[level]); + // create new row + ArrayList newRow = new ArrayList(); + for (int c = 0; c < cols.size(); c++) + { + if (c == idx) // the group column + { + if (groupBysValue[c] == null || groupBysValue[c].toString().length() == 0) + newRow.add("="); + else + newRow.add(groupBysValue[c]); + } + else + { + boolean found = false; + for (int fc = 0; fc < funcCols.length; fc++) + { + if (c == funcCols[fc]) + { + // newRow.add("fc= " + fc + " gl=" + level + " " + funcFuns[fc]); + newRow.add(funcVals[fc][level]); + funcVals[fc][level] = Env.ZERO; + found = true; + } + } + if (!found) + newRow.add(null); + } + } // for all columns + // + m_groupRows.add(new Integer(rows.size())); // group row indicator + rows.add(newRow); + groupBysValue[level] = row.get(idx); + } + } // for all groups + + // functions + for (int fc = 0; fc < funcCols.length; fc++) + { + int col = funcCols[fc]; + // convert value to big decimal + Object value = row.get(col); + BigDecimal bd = Env.ZERO; + if (value == null) + ; + else if (value instanceof BigDecimal) + bd = (BigDecimal)value; + else + { + try { + bd = new BigDecimal(value.toString()); + } catch (Exception e) { } + } + + for (int level = 0; level < gSize+1; level++) + { + if (funcFuns[fc].equals(RModel.FUNCTION_SUM)) + funcVals[fc][level] = funcVals[fc][level].add(bd); + else if (funcFuns[fc].equals(RModel.FUNCTION_COUNT)) + funcVals[fc][level] = funcVals[fc][level].add(ONE); + } // for all group levels + } // for all functions + + rows.add(row); + } // for all m_rows + + // total row + if (functions.size() > 0) + { + ArrayList newRow = new ArrayList(); + for (int c = 0; c < cols.size(); c++) + { + boolean found = false; + for (int fc = 0; fc < funcCols.length; fc++) + { + if (c == funcCols[fc]) + { + newRow.add(funcVals[fc][totalIndex]); + found = true; + } + } + if (!found) + newRow.add(null); + } // for all columns + // remove empty row added earlier to force group change + if (gSize > 0) + rows.remove(rows.size()-1); + m_groupRows.add(new Integer(rows.size())); // group row indicator + rows.add(newRow); + } + log.fine("End Rows=" + rows.size()); + m_rows.clear(); + } // process + + + /************************************************************************** + * Is Row a Group Row + * @param row row index + * @return true, if group row + */ + public boolean isGroupRow (int row) + { + // build boolean Array + if (m_groupRowsIndicator == null) + { + m_groupRowsIndicator = new ArrayList(rows.size()); + for (int r = 0; r < rows.size(); r++) + m_groupRowsIndicator.add(new Boolean(m_groupRows.contains(new Integer(r)))); + } + if (row < 0 || row >= m_groupRowsIndicator.size()) + return false; + return ((Boolean)m_groupRowsIndicator.get(row)).booleanValue(); + } // isGroupRow + + /** + * Move Row + * @param from index + * @param to index + * @throws IllegalArgumentException if row index is invalid + */ + public void moveRow (int from, int to) + { + if (from < 0 || to >= rows.size()) + throw new IllegalArgumentException("Row from invalid"); + if (to < 0 || to >= rows.size()) + throw new IllegalArgumentException("Row to invalid"); + // Move Data + ArrayList temp = rows.get(from); + rows.remove(from); + rows.add(to, temp); + // Move Description indicator >>> m_groupRows is not in sync after row move !! + if (m_groupRowsIndicator != null) + { + Boolean tempB = m_groupRowsIndicator.get(from); + m_groupRowsIndicator.remove(from); + m_groupRowsIndicator.add(to, tempB); + } + } // moveRow + +} // RModelData diff --git a/base/src/org/compiere/report/core/ResultTable.java b/base/src/org/compiere/report/core/ResultTable.java new file mode 100644 index 0000000000..8f7debd6ec --- /dev/null +++ b/base/src/org/compiere/report/core/ResultTable.java @@ -0,0 +1,260 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report.core; + +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import java.util.logging.*; +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.table.*; +import org.compiere.util.*; + +/** + * The Table to present RModel information + * + * @author Jorg Janke + * @version $Id: ResultTable.java,v 1.2 2006/07/30 00:51:06 jjanke Exp $ + */ +public class ResultTable extends JTable implements MouseListener +{ + /** + * Constructor + */ + public ResultTable() + { + super(); + setCellSelectionEnabled(false); + setColumnSelectionAllowed(false); + setRowSelectionAllowed(false); + setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + + // Default Editor + ResultTableCellEditor rtce = new ResultTableCellEditor(); + setCellEditor(rtce); + + // Mouse Listener + addMouseListener(this); + getTableHeader().addMouseListener(this); + } // ResultTable + + /** Last model index sorted */ + private int m_lastSortIndex = -1; + /** Sort direction */ + private boolean m_asc = true; + + /** Logger */ + private static CLogger log = CLogger.getCLogger(ResultTable.class); + + /** + * Create a JTable Model from ReportModel + * @param reportModel + */ + public ResultTable (RModel reportModel) + { + this(); + setModel(reportModel); + } // ResultTable + + /** + * Set Model + * @param reportModel + */ + public void setModel (RModel reportModel) + { + log.config(reportModel.toString()); + super.setModel(new ResultTableModel(reportModel)); + // + TableColumnModel tcm = getColumnModel(); + // Set Editor/Renderer + for (int i = 0; i < tcm.getColumnCount(); i++) + { + TableColumn tc = tcm.getColumn(i); + RColumn rc = reportModel.getRColumn(i); + if (rc.getColHeader().equals(tc.getHeaderValue())) + { + ResultTableCellRenderer rtcr = new ResultTableCellRenderer(reportModel, rc); + tc.setCellRenderer(rtcr); + // + } + else + log.log(Level.SEVERE, "RColumn=" + rc.getColHeader() + " <> TableColumn=" + tc.getHeaderValue()); + } + autoSize(); + } // setModel + + /** + * Set Model + * @param ignored + */ + public void setModel (TableModel ignored) + { + // throw new IllegalArgumentException("Requires RModel"); // default construvtor calls this + super.setModel(ignored); + } // setModel + + /** + * Table Model Listener + * @param e + */ + public void tableChanged(TableModelEvent e) + { + super.tableChanged(e); + log.fine("Type=" + e.getType()); + } // tableChanged + + /*************************************************************************/ + + /** + * Mouse Clicked + * @param e + */ + public void mouseClicked(MouseEvent e) + { + int col = getColumnModel().getColumnIndexAtX(e.getX()); + log.fine("Column " + col + " = " + getColumnModel().getColumn(col).getHeaderValue() + + ", Table r=" + this.getSelectedRow() + " c=" + this.getSelectedColumn()); + + // clicked Cell + if (e.getSource() == this) + { + } + // clicked Header + else + { + int mc = convertColumnIndexToModel(col); + sort(mc); + } + } // mouseClicked + + public void mousePressed(MouseEvent e) + { + } + public void mouseReleased(MouseEvent e) + { + } + public void mouseEntered(MouseEvent e) + { + } + public void mouseExited(MouseEvent e) + { + } + + + /************************************************************************** + * Size Columns + */ + private void autoSize() + { + log.config(""); + // + final int SLACK = 8; // making sure it fits in a column + final int MAXSIZE = 300; // max size of a column + // + TableColumnModel tcm = getColumnModel(); + // For all columns + for (int col = 0; col < tcm.getColumnCount(); col++) + { + TableColumn tc = tcm.getColumn(col); + // log.config( "Column=" + col, tc.getHeaderValue()); + int width = 0; + + // Header + TableCellRenderer renderer = tc.getHeaderRenderer(); + if (renderer == null) + renderer = new DefaultTableCellRenderer(); + Component comp = renderer.getTableCellRendererComponent + (this, tc.getHeaderValue(), false, false, 0, 0); + // log.fine( "Hdr - preferred=" + comp.getPreferredSize().width + ", width=" + comp.getWidth()); + width = comp.getPreferredSize().width + SLACK; + + // Cells + int maxRow = Math.min(30, getRowCount()); // first 30 rows + for (int row = 0; row < maxRow; row++) + { + renderer = getCellRenderer(row, col); + comp = renderer.getTableCellRendererComponent + (this, getValueAt(row, col), false, false, row, col); + int rowWidth = comp.getPreferredSize().width + SLACK; + width = Math.max(width, rowWidth); + } + // Width not greater .. + width = Math.min(MAXSIZE, width); + tc.setPreferredWidth(width); + // log.fine( "width=" + width); + } // for all columns + } // autoSize + + /** + * Sort Table + * @param modelColumnIndex + */ + @SuppressWarnings("unchecked") + private void sort (int modelColumnIndex) + { + int rows = getRowCount(); + if (rows == 0) + return; + // other column + if (modelColumnIndex != m_lastSortIndex) + m_asc = true; + else + m_asc = !m_asc; + + m_lastSortIndex = modelColumnIndex; + // + log.config("#" + modelColumnIndex + + " - rows=" + rows + ", asc=" + m_asc); + ResultTableModel model = (ResultTableModel)getModel(); + + // Prepare sorting + MSort sort = new MSort(0, null); + sort.setSortAsc(m_asc); + // while something to sort + sorting: + while (true) + { + // Create sortList + ArrayList sortList = new ArrayList(rows); + // fill with data entity + for (int i = 0; i < rows; i++) + { + Object value = model.getValueAt(i, modelColumnIndex); + sortList.add(new MSort(i, value)); + } + // sort list it + Collections.sort(sortList, sort); + // move out of sequence row + for (int i = 0; i < rows; i++) + { + int index = ((MSort)sortList.get(i)).index; + if (i != index) + { + // log.config( "move " + i + " to " + index); + model.moveRow (i, index); + continue sorting; + } + } + // we are done + // log.config( "done"); + break; + } // while something to sort + } // sort + +} // ResultTable diff --git a/base/src/org/compiere/report/core/ResultTableCellEditor.java b/base/src/org/compiere/report/core/ResultTableCellEditor.java new file mode 100644 index 0000000000..48c943dee6 --- /dev/null +++ b/base/src/org/compiere/report/core/ResultTableCellEditor.java @@ -0,0 +1,91 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report.core; + +import java.util.*; +import java.awt.*; +import javax.swing.*; +import javax.swing.table.*; + +/** + * Cell Editor for Report Result Table + * + * @author Jorg Janke + * @version $Id: ResultTableCellEditor.java,v 1.2 2006/07/30 00:51:06 jjanke Exp $ + */ +public class ResultTableCellEditor extends AbstractCellEditor implements TableCellEditor +{ + /** + * Constructor (read only) + */ + public ResultTableCellEditor() + { + } // ResultTableCellEditor + + /** + * Constructor + */ + public ResultTableCellEditor(RColumn rc) + { + m_rc = rc; + } // ResultTableCellEditor + + /** Report Column */ + private RColumn m_rc = null; + + /** + * Return Editor + */ + public Component getTableCellEditorComponent (JTable table, Object value, + boolean isSelected, int row, int col) + { + if (m_rc == null) + return null; + return null; + } // getTableCellEditorComponent + + /** + * Get Value + */ + public Object getCellEditorValue() + { + if (m_rc == null) + return null; + return null; + } // getCellEditorValue + + /** + * Is Cell editable + */ + public boolean isCellEditable(EventObject anEvent) + { + if (m_rc == null) + return false; + return !m_rc.isReadOnly(); + } // isCellEditable + + /** + * Should Cell be selected + */ + public boolean shouldSelectCell(EventObject anEvent) + { + if (m_rc == null) + return false; + return !m_rc.isReadOnly(); + } // shouldSelectCell + +} // ResultTableCellEditor diff --git a/base/src/org/compiere/report/core/ResultTableCellRenderer.java b/base/src/org/compiere/report/core/ResultTableCellRenderer.java new file mode 100644 index 0000000000..193f36e55b --- /dev/null +++ b/base/src/org/compiere/report/core/ResultTableCellRenderer.java @@ -0,0 +1,148 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report.core; + +import java.awt.*; +import java.text.*; +import javax.swing.*; +import javax.swing.table.*; +import org.compiere.plaf.*; +import org.compiere.util.*; + +/** + * Cell Renderer for Report Result Table + * + * @author Jorg Janke + * @version $Id: ResultTableCellRenderer.java,v 1.2 2006/07/30 00:51:06 jjanke Exp $ + */ +class ResultTableCellRenderer extends DefaultTableCellRenderer implements TableCellRenderer +{ + /** + * Constructor (extends Label) + * @param rm + * @param rc + */ + public ResultTableCellRenderer(RModel rm, RColumn rc) + { + m_rm = rm; + m_rc = rc; + int dt = m_rc.getDisplayType(); + // Numbers + if (DisplayType.isNumeric(dt)) + { + super.setHorizontalAlignment(JLabel.TRAILING); + m_nFormat = DisplayType.getNumberFormat(dt); + } + // Dates + else if (DisplayType.isDate(m_rc.getDisplayType())) + { + super.setHorizontalAlignment(JLabel.TRAILING); + m_dFormat = DisplayType.getDateFormat(dt); + } + // + else if (dt == DisplayType.YesNo) + { + m_check = new JCheckBox(); + m_check.setMargin(new Insets(0,0,0,0)); + m_check.setHorizontalAlignment(JLabel.CENTER); + } + } // ResultTableCellRenderer + + /** Report Column */ + private RModel m_rm = null; + /** Report Column */ + private RColumn m_rc = null; + /** Number Format */ + private DecimalFormat m_nFormat = null; + /** Date Format */ + private SimpleDateFormat m_dFormat = null; + /** Boolean renderer */ + private JCheckBox m_check; + + + /** + * Return Renderer Component + * @param table + * @param value + * @param isSelected + * @param hasFocus + * @param row + * @param col + * @return renderer component + */ + public Component getTableCellRendererComponent(JTable table, Object value, + boolean isSelected, boolean hasFocus, int row, int col) + { + // Get Component + Component c = m_check; + if (c == null) // default JLabel + c = super.getTableCellRendererComponent(table,value, isSelected,hasFocus, row,col); + // Background + if (m_rm.isCellEditable(row, col)) + c.setBackground(AdempierePLAF.getFieldBackground_Normal()); + else + c.setBackground(AdempierePLAF.getFieldBackground_Inactive()); + // + if (m_rm.isGroupRow(row)) + c.setFont(c.getFont().deriveFont(Font.BOLD)); + // Value + setValue (value); + return c; + } // getTableCellRendererComponent + + /** + * Set Value + * @param value + */ + protected void setValue (Object value) + { + // Boolean + if (m_check != null) + { + boolean sel = false; + if (value != null && ((Boolean)value).booleanValue()) + sel = true; + m_check.setSelected(sel); + return; + } + + // JLabel + if (value == null) + setText(""); + else if (m_nFormat != null) + try + { + setText(m_nFormat.format(value)); + } + catch (Exception e) + { + setText(value.toString()); + } + else if (m_dFormat != null) + try + { + setText(m_dFormat.format(value)); + } + catch (Exception e) + { + setText(value.toString()); + } + else + setText(value.toString()); + } // setValue + +} // ResultTableCellRenderer diff --git a/base/src/org/compiere/report/core/ResultTableModel.java b/base/src/org/compiere/report/core/ResultTableModel.java new file mode 100644 index 0000000000..f437ae3cfd --- /dev/null +++ b/base/src/org/compiere/report/core/ResultTableModel.java @@ -0,0 +1,124 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.report.core; + +import javax.swing.event.*; +import javax.swing.table.*; + +/** + * The TableModel for JTable to present RModel information + * + * @author Jorg Janke + * @version $Id: ResultTableModel.java,v 1.2 2006/07/30 00:51:06 jjanke Exp $ + */ +class ResultTableModel extends AbstractTableModel +{ + /** + * Create a JTable Model from ReportModel + * @param reportModel + */ + public ResultTableModel (RModel reportModel) + { + m_model = reportModel; + } // ResultTableModel + + /** The Report Model */ + private RModel m_model; + + /** + * Get Row Count + * @return row count + */ + public int getRowCount() + { + return m_model.getRowCount(); + } // getRowCount + + /** + * Get ColumnCount + * @return column count + */ + public int getColumnCount() + { + return m_model.getColumnCount(); + } // getColumnCount + + /** + * Get Column Name + * @param columnIndex + * @return Column Name + */ + public String getColumnName(int columnIndex) + { + return m_model.getColumnName(columnIndex); + } // getColumnIndex + + /** + * Get Column Class + * @param columnIndex + * @return Column Class + */ + public Class getColumnClass(int columnIndex) + { + return m_model.getColumnClass(columnIndex); + } // getColumnClass + + /** + * Is Cell Editable + * @param rowIndex + * @param columnIndex + * @return true, if editable + */ + public boolean isCellEditable(int rowIndex, int columnIndex) + { + return false; + } // isCellEditable + + /** + * Get Value At + * @param row + * @param col + * @return value + */ + public Object getValueAt(int row, int col) + { + return m_model.getValueAt(row, col); + } // getValueAt + + /** + * Set Value At + * @param aValue + * @param row + * @param col + */ + public void setValueAt(Object aValue, int row, int col) + { + m_model.setValueAt(aValue, row, col); + fireTableChanged(new TableModelEvent (this, row, row, col, TableModelEvent.UPDATE)); + } // setValueAt + + /** + * Move Row + * @param from index + * @param to index + */ + public void moveRow (int from, int to) + { + m_model.moveRow (from, to); + } // moveRow + +} // ResultTableModel diff --git a/base/src/org/compiere/sla/DeliveryAccuracy.java b/base/src/org/compiere/sla/DeliveryAccuracy.java new file mode 100644 index 0000000000..4ef74b4ec1 --- /dev/null +++ b/base/src/org/compiere/sla/DeliveryAccuracy.java @@ -0,0 +1,154 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.sla; + +import java.math.*; +import java.sql.*; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * SLA Delivery Accuracy. + * How accurate is the promise date? + *

+ * The measure are the average days between promise date (PO/SO) and delivery date + * (Material receipt/shipment) It is positive if before, negative if later. + * The lower the number, the better + * + * @author Jorg Janke + * @version $Id: DeliveryAccuracy.java,v 1.2 2006/07/30 00:51:06 jjanke Exp $ + */ +public class DeliveryAccuracy extends SLACriteria +{ + + /** + * DeliveryAccuracy + */ + public DeliveryAccuracy () + { + super (); + } // DeliveryAccuracy + + /** Logger */ + protected CLogger log = CLogger.getCLogger(getClass()); + + + /** + * Create new Measures for the Goal + * @param goal the goal + * @return number created + */ + public int createMeasures (MSLAGoal goal) + { + String sql = "SELECT M_InOut_ID, io.MovementDate-o.DatePromised," // 1..2 + + " io.MovementDate, o.DatePromised, o.DocumentNo " + + "FROM M_InOut io" + + " INNER JOIN C_Order o ON (io.C_Order_ID=o.C_Order_ID) " + + "WHERE io.C_BPartner_ID=?" + + " AND NOT EXISTS " + + "(SELECT * FROM PA_SLA_Measure m " + + "WHERE m.PA_SLA_Goal_ID=?" + + " AND m.AD_Table_ID=" + MInOut.Table_ID + + " AND m.Record_ID=io.M_InOut_ID)"; + int counter = 0; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, goal.getC_BPartner_ID()); + pstmt.setInt (2, goal.getPA_SLA_Goal_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + int M_InOut_ID = rs.getInt(1); + BigDecimal MeasureActual = rs.getBigDecimal(2); + Timestamp MovementDate = rs.getTimestamp(3); + String Description = rs.getString(5) + ": " + rs.getTimestamp(4); + if (goal.isDateValid(MovementDate)) + { + MSLAMeasure measure = new MSLAMeasure(goal, MovementDate, + MeasureActual, Description); + measure.setLink(MInOut.Table_ID, M_InOut_ID); + if (measure.save()) + counter++; + } + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "createMeasures", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return counter; + } // createMeasures + + + /************************************************************************** + * Calculate Goal Actual from unprocessed Measures + * @return goal actual measure + */ + public BigDecimal calculateMeasure (MSLAGoal goal) + { + // Average + BigDecimal retValue = Env.ZERO; + BigDecimal total = Env.ZERO; + int count = 0; + // + MSLAMeasure[] measures = goal.getAllMeasures(); + for (int i = 0; i < measures.length; i++) + { + MSLAMeasure measure = measures[i]; + if (!measure.isActive() + || (goal.getValidFrom() != null && measure.getDateTrx().before(goal.getValidFrom())) + || (goal.getValidTo() != null && measure.getDateTrx().after(goal.getValidTo()))) + continue; + // + total = total.add(measure.getMeasureActual()); + count++; + // + if (!measure.isProcessed()) + { + measure.setProcessed(true); + measure.save(); + } + } + // Goal Expired + if (goal.getValidTo() != null + && goal.getValidTo().after(new Timestamp(System.currentTimeMillis()))) + goal.setProcessed(true); + + // Calculate with 2 digits precision + if (count != 0) + retValue = total.divide(new BigDecimal(count), 2, BigDecimal.ROUND_HALF_UP); + return retValue; + } // calculateMeasure + +} // DeliveryAccuracy diff --git a/base/src/org/compiere/sla/SLACriteria.java b/base/src/org/compiere/sla/SLACriteria.java new file mode 100644 index 0000000000..d93ce2fbcc --- /dev/null +++ b/base/src/org/compiere/sla/SLACriteria.java @@ -0,0 +1,84 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.sla; + +import java.math.*; +import java.sql.*; + +import org.compiere.model.*; + +/** + * Service Level Agreement Criteria + * + * @author Jorg Janke + * @version $Id: SLACriteria.java,v 1.3 2006/07/30 00:51:06 jjanke Exp $ + */ +public abstract class SLACriteria +{ + /** + * Create new Measures for the Goal + * @param goal the goal + * @return number created + */ + public abstract int createMeasures (MSLAGoal goal); + + /** + * Calculate Goal Actual from unprocessed Measures of the Goal + * @param goal the goal + * @return new Actual Measure + */ + public abstract BigDecimal calculateMeasure (MSLAGoal goal); + + + /** + * Create new Measures for the Criteria + * @param criteria the criteria + * @return measures created + */ + public int createMeasures (MSLACriteria criteria) + { + int counter = 0; + MSLAGoal[] goals = criteria.getGoals(); + for (int i = 0; i < goals.length; i++) + { + MSLAGoal goal = goals[i]; + if (goal.isActive()) + counter += createMeasures (goal); + } + return counter; + } // createMeasures + + /** + * Calculate Goal Actual from unprocessed Measures of the Goal + * @param criteria SLA criteria + */ + public void calculateMeasures (MSLACriteria criteria) + { + MSLAGoal[] goals = criteria.getGoals(); + for (int i = 0; i < goals.length; i++) + { + MSLAGoal goal = goals[i]; + if (goal.isActive()) + { + goal.setMeasureActual(calculateMeasure(goal)); + goal.setDateLastRun(new Timestamp(System.currentTimeMillis())); + goal.save(); + } + } + } // calculateMeasures + +} // SLACriteria diff --git a/base/src/org/compiere/sla/SLAGoalProcess.java b/base/src/org/compiere/sla/SLAGoalProcess.java new file mode 100644 index 0000000000..bc88673e2e --- /dev/null +++ b/base/src/org/compiere/sla/SLAGoalProcess.java @@ -0,0 +1,82 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.sla; + +import java.sql.*; + +import org.compiere.model.*; +import org.compiere.process.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Service Level Agreement Goal. + * If automatic, capture measures - and calculate/update the actual measure. + * + * @author Jorg Janke + * @version $Id: SLAGoalProcess.java,v 1.2 2006/07/30 00:51:06 jjanke Exp $ + */ +public class SLAGoalProcess extends SvrProcess +{ + /** Goal */ + private int p_PA_SLA_Goal_ID; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + p_PA_SLA_Goal_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info ("PA_SLA_Goal_ID=" + p_PA_SLA_Goal_ID); + MSLAGoal goal = new MSLAGoal(getCtx(), p_PA_SLA_Goal_ID, get_TrxName()); + if (goal.get_ID() == 0) + throw new AdempiereUserError("@PA_SLA_Goal_ID@ " + p_PA_SLA_Goal_ID); + + MSLACriteria criteria = MSLACriteria.get(getCtx(), goal.getPA_SLA_Criteria_ID(), get_TrxName()); + if (criteria.get_ID() == 0) + throw new AdempiereUserError("@PA_SLA_Criteria_ID@ " + goal.getPA_SLA_Criteria_ID()); + + SLACriteria pgm = criteria.newInstance(); + int no = pgm.createMeasures(goal); + // + goal.setMeasureActual(pgm.calculateMeasure(goal)); + goal.setDateLastRun(new Timestamp(System.currentTimeMillis())); + goal.save(); + // + return "@Created@ " + no + " - @MeasureActual@=" + goal.getMeasureActual(); + } // doIt + +} // SLAGoalProcess diff --git a/base/src/org/compiere/sla/SLAMeasureProcess.java b/base/src/org/compiere/sla/SLAMeasureProcess.java new file mode 100644 index 0000000000..585255a333 --- /dev/null +++ b/base/src/org/compiere/sla/SLAMeasureProcess.java @@ -0,0 +1,85 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.sla; + +import java.sql.*; + +import org.compiere.model.*; +import org.compiere.process.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Service Level Agreement Measure. + * Calculate/update the actual measure. + * + * @author Jorg Janke + * @version $Id: SLAMeasureProcess.java,v 1.2 2006/07/30 00:51:06 jjanke Exp $ + */ +public class SLAMeasureProcess extends SvrProcess +{ + /** Goal */ + private int p_PA_SLA_Measure_ID; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + p_PA_SLA_Measure_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info ("PA_SLA_Measure_ID=" + p_PA_SLA_Measure_ID); + MSLAMeasure measure = new MSLAMeasure (getCtx(), p_PA_SLA_Measure_ID, get_TrxName()); + if (measure.get_ID() == 0) + throw new AdempiereUserError("@PA_SLA_Measure_ID@ " + p_PA_SLA_Measure_ID); + + MSLAGoal goal = new MSLAGoal(getCtx(), measure.getPA_SLA_Goal_ID(), get_TrxName()); + if (goal.get_ID() == 0) + throw new AdempiereUserError("@PA_SLA_Goal_ID@ " + measure.getPA_SLA_Goal_ID()); + + MSLACriteria criteria = MSLACriteria.get(getCtx(), goal.getPA_SLA_Criteria_ID(), get_TrxName()); + if (criteria.get_ID() == 0) + throw new AdempiereUserError("@PA_SLA_Criteria_ID@ " + goal.getPA_SLA_Criteria_ID()); + + SLACriteria pgm = criteria.newInstance(); + // + goal.setMeasureActual(pgm.calculateMeasure(goal)); + goal.setDateLastRun(new Timestamp(System.currentTimeMillis())); + goal.save(); + // + return "@MeasureActual@=" + goal.getMeasureActual(); + } // doIt + +} // SLAMeasureProcess diff --git a/base/src/org/compiere/tools/FileUtil.java b/base/src/org/compiere/tools/FileUtil.java new file mode 100644 index 0000000000..e762f7a70a --- /dev/null +++ b/base/src/org/compiere/tools/FileUtil.java @@ -0,0 +1,389 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.tools; + +import java.io.*; +import org.compiere.util.*; + +/** + * File Utilities + * + * @author Jorg Janke + * @version $Id: FileUtil.java,v 1.4 2006/08/03 04:03:22 jjanke Exp $ + */ +public class FileUtil +{ + /** + * File Utility + * @param file input file or directory + * @param filter filter + * @param action action + * @param p1 parameter 1 + * @param p2 parameter 2 + */ + public FileUtil (String file, String filter, String action, String p1, String p2) + { + this (new File(file), filter, action, p1, p2); + } // FileUtil + + /** + * File Utility + * @param file input file or directory + * @param filter filter + * @param action action + * @param p1 parameter 1 + * @param p2 parameter 2 + */ + public FileUtil (File file, String filter, String action, String p1, String p2) + { + if (action == null || action.length() == 0) + System.err.println("FileUtil: No Action"); + else if (!validAction(action)) + System.err.println("FileUtil: Action not valid: " + action + ACTIONS); + else if (file == null) + System.err.println("FileUtil: No Input file"); + else if (!file.exists()) + System.err.println("FileUtil: Input file does not exist: " + file); + else + { + System.out.println("FileUtil (" + file + ", Filter=" + filter + ", Action=" + action + ")"); + m_filterString = filter; + processFile (file, p1, p2); + System.out.println("FileUtil Process count = " + m_count + " actions=" + m_actions); + } + } // FileUtil + + private String m_filterString = null; + private FileUtilFilter m_filter = new FileUtilFilter(); + /** File Count */ + private int m_count = 0; + /** Action Count */ + private int m_actions = 0; + private int m_actionIndex = -1; + + static final String[] ACTIONS = new String[] + {"List", "Replace", "Latex", "License"}; + + + /** + * Is Action Valid + * @param action action + * @return true if supported + */ + private boolean validAction (String action) + { + for (int i = 0; i < ACTIONS.length; i++) + { + if (ACTIONS[i].equals (action)) + { + m_actionIndex = i; + return true; + } + } + return false; + } // validAction + + /** + * Process File + * @param file file + * @param p1 parameter 1 + * @param p2 parameter 2 + */ + private void processFile (File file, String p1, String p2) + { + if (file == null) + return; + else if (!file.exists()) + return; + else if (file.isDirectory()) + { + File[] dirFiles = file.listFiles(m_filter); + for (int i = 0; i < dirFiles.length; i++) + processFile(dirFiles[i], p1, p2); + } + else + { + System.out.println(" ProcessFile=" + file.getAbsolutePath()); + m_count++; + processFileAction(file, p1, p2); + } + } // processFile + + /** + * File Action + * @param file file to be processed + * @param p1 parameter 1 + * @param p2 parameter 2 + */ + void processFileAction(File file, String p1, String p2) + { + try + { + if (m_actionIndex == 0) // List + ; + else if (m_actionIndex == 1) // Replace + replaceString (file, p1, p2); + else if (m_actionIndex == 2) // Latex + latex (file); + else if (m_actionIndex == 3) // License + license (file); + } + catch (Exception ex) + { + } + } // processFileAction + + + /************************************************************************** + * Replace String in File. + * @param file file + * @param from old String + * @param to new String + * @throws IOException + */ + private void replaceString (File file, String from, String to) throws IOException + { + String fileName = file.getAbsolutePath(); + BufferedReader in = new BufferedReader(new FileReader(file)); + // + File tmpFile = new File(fileName + ".tmp"); + BufferedWriter out = new BufferedWriter (new FileWriter(tmpFile, false)); + boolean found = false; + + String line = null; + int lineNo = 0; + while ((line = in.readLine()) != null) + { + lineNo++; + if (line.indexOf(from) != -1) + { + found = true; + System.out.println(" " + lineNo + ": " + line); + line = Util.replace(line, from, to); + m_actions++; + } + out.write(line); + out.newLine(); + } // while reading file + // + in.close(); + out.close(); + // + if (found) + { + File oldFile = new File (fileName + ".old"); + if (file.renameTo(oldFile)) + { + if (tmpFile.renameTo (new File (fileName))) + { + if (oldFile.delete ()) + System.out.println (" - File updated: " + fileName); + else + System.err.println (" - Old File not deleted - " + fileName); + } + else + System.err.println (" - New File not renamed - " + fileName); + } + else + System.err.println(" - Old File not renamed - " + fileName); + } + else + { + if (!tmpFile.delete()) + System.err.println(" - Temp file not deleted - " + tmpFile.getAbsolutePath()); + } + } // replaceString + + + + /************************************************************************** + * Strip Latex specifics. + * \textsl{\colorbox{yellow}{\textbf{Important:}}} For more information on the + installation of the Adempiere Server and the Adempiere Client please refer to + \href{http://www.adempiere.org/support/index.html}{Adempiere Support} for more details and the latest + update. + * @param file file + * @throws IOException + */ + private void latex (File file) throws IOException + { + String fileName = file.getAbsolutePath(); + BufferedReader in = new BufferedReader(new FileReader(file)); + // + File outFile = new File(fileName + ".txt"); + BufferedWriter out = new BufferedWriter (new FileWriter(outFile, false)); + + String line = null; + int lineNo = 0; + + while ((line = in.readLine()) != null) + { + lineNo++; + boolean ignore = false; + // + char[] inLine = line.toCharArray(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < inLine.length; i++) + { + char c = inLine[i]; + if (c == '\\') + ignore = true; + else if (c == '{') + ignore = false; + else if (c == '}') + ; + else if (!ignore) + sb.append(c); + } + // + out.write(sb.toString()); + out.newLine(); + } // while reading file + // + in.close(); + out.close(); + System.out.println("File " + fileName + " - lines=" + lineNo); + } // latex + + + /************************************************************************** + * Replace License info. + * @param file file + * @throws IOException + */ + private void license (File file) throws IOException + { + String fileName = file.getAbsolutePath(); + boolean isJava = fileName.endsWith(".java"); + boolean isJSP = fileName.endsWith(".jsp"); + boolean other = !(isJava || isJSP); + BufferedReader in = new BufferedReader(new FileReader(file)); + // + File tmpFile = new File(fileName + ".tmp"); + BufferedWriter out = new BufferedWriter (new FileWriter(tmpFile, false)); + + out.write(GenerateModel.COPY); + boolean found = false; + + String line = null; + int lineNo = 0; + while ((line = in.readLine()) != null) + { + lineNo++; + if (!found) + { + if (line.startsWith("package ") && isJava) + found = true; + } + if (found) + { + out.write(line); + out.newLine(); + } + } // while reading file + // + in.close(); + out.close(); + // + if (found) + { + File oldFile = new File (fileName + ".old"); + if (file.renameTo(oldFile)) + { + if (tmpFile.renameTo (new File (fileName))) + { + if (oldFile.delete ()) + { + // System.out.println (" - File updated: " + fileName); + } + else + System.err.println (" - Old File not deleted - " + fileName); + } + else + System.err.println (" - New File not renamed - " + fileName); + } + else + System.err.println(" - Old File not renamed - " + fileName); + } + else + { + System.err.println(" - No Copyright - " + fileName); + if (!tmpFile.delete()) + System.err.println(" - Temp file not deleted - " + tmpFile.getAbsolutePath()); + } + } // license + + + /************************************************************************** + * File Filter. + * Accept directories and files matching filter + */ + class FileUtilFilter implements FilenameFilter + { + /** + * Accept directories and files matching filter. + * + * @param dir the directory in which the file was found. + * @param name the name of the file. + * @return Accept directories and files matching filter + */ + public boolean accept (File dir, String name) + { + // System.out.println(" Dir=" + dir + ", Name=" + name); + File file = new File (dir, name); + if (file.isDirectory()) + return true; + if (m_filterString == null || m_filterString.length() == 0) + return true; + if (name == null) + return false; + // ignore files with ~ and this file + if (name.indexOf("~") != -1 || name.equals("FileUtil.java")) + return false; + // + return name.indexOf(m_filterString) != -1; + } // accept + + } // FileUtilFilter + + + /************************************************************************** + * Start + * @param args fileName filter action + */ + public static void main (String[] args) + { + String directory = "C:\\Adempiere\\adempiere-all2"; + String filter = ".java"; + // String action = "License"; // Replace + // String from = null; + // String to = null; + String action = "Replace"; + String from = "$Id: FileUtil.java,v 1.4 2006/08/03 04:03:22 jjanke Exp $"; + String to = "$Id: FileUtil.java,v 1.4 2006/08/03 04:03:22 jjanke Exp $"; + + if (args.length == 1) + directory = args[0]; + if (args.length == 2) + filter = args[1]; + if (filter == null) + filter = ""; + // + new FileUtil(directory, filter, action, from, to); + } // main + +} // FileUtil diff --git a/base/src/org/compiere/tools/RMIUtil.java b/base/src/org/compiere/tools/RMIUtil.java new file mode 100644 index 0000000000..0d2667f2da --- /dev/null +++ b/base/src/org/compiere/tools/RMIUtil.java @@ -0,0 +1,106 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.tools; + +import java.rmi.*; +import java.rmi.registry.*; +//import java.rmi.server.*; +import java.net.*; +import java.io.*; + +/** + * Test/List RMI Registry + * + * @author Jorg Janke + * @version $Id: RMIUtil.java,v 1.3 2006/07/30 00:51:06 jjanke Exp $ + */ +public class RMIUtil +{ + /** + * RMIUtil + */ + public RMIUtil() + { + // testPort(); + try + { + System.out.println("Registry ------------------------------------"); + Registry registry = LocateRegistry.getRegistry(); + System.out.println("- " + registry); + String[] list = registry.list(); + System.out.println("- size=" + list.length); + for (int i = 0; i < list.length; i++) + { + System.out.println("-- " + list[i]); + } + } + catch (Exception ex) + { + ex.printStackTrace(); + } + + try + { + System.out.println("Server --------------------------------------"); + // System.out.println("- " + RemoteServer.getClientHost()); + String[] list = Naming.list ("rmi://localhost:1099"); + System.out.println("- size=" + list.length); + for (int i = 0; i < list.length; i++) + { + System.out.println("-- " + list[i]); + } + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } // RMIUtil + + private void testPort() + { + try + { + System.out.println("Test Port -----------------------------------"); + Socket socket = new Socket ("localhost", 1099); + System.out.println("- Socket=" + socket); + // + InputStream in = socket.getInputStream(); + int i = 0; + while (i >= 0) + { + i = in.read(); + if (i >= 0) + System.out.println((char)i); + } + } + catch (IOException ex) + { + ex.printStackTrace(); + } + + } + + /** + * Test + * @param args args + */ + public static void main (String[] args) + { + new RMIUtil(); + } // main + +} // RMIUtil diff --git a/base/src/org/compiere/tools/Strip.java b/base/src/org/compiere/tools/Strip.java new file mode 100644 index 0000000000..c7c05447fd --- /dev/null +++ b/base/src/org/compiere/tools/Strip.java @@ -0,0 +1,234 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.tools; + +import java.io.*; + +/** + * Strip Windows (cr/lf) Text files to Unix (cr) Text files + * + * @author Jorg Janke + * @version $Id: Strip.java,v 1.2 2006/07/30 00:51:06 jjanke Exp $ + */ +public class Strip +{ + /** print more info if set to true */ + private static final boolean VERBOSE = false; + + /** + * Constructor + */ + public Strip() + { + } // Strip + + /*************************************************************************/ + + /** + * Strip a directory (and its subdirectories recursively) + * @param directory directory + * @param nameMustContain file name must include characters - e.g. .sh + * (do not include wildcards like *). If null, all files are stripped + */ + public void stripDirectory (String directory, String nameMustContain) + { + if (directory == null) + throw new NullPointerException("Strip: directory cannot be null"); + File dir = new File (directory); + if (!dir.exists() || !dir.isDirectory()) + throw new IllegalArgumentException ("Strip: directory does not exist or is not a directory: " + dir); + + File[] list = dir.listFiles(); + if (list == null) + return; + if (VERBOSE) + System.out.println("Stripping directory: " + dir); + for (int i = 0; i < list.length; i++) + { + String name = list[i].getAbsolutePath(); + if (list[i].isDirectory()) + stripDirectory (name, nameMustContain); + else if (nameMustContain == null || name.indexOf(nameMustContain) != -1) + strip (list[i], null); + } + } // stripDirectory + + + /** + * Strip infile to outfile + * @param infile input file + * @param outfile (can be null) + * @return true if copied + */ + public boolean strip (String infile, String outfile) + { + if (infile == null) + throw new NullPointerException("Strip: infile cannot be null"); + File in = new File (infile); + File out = null; + if (outfile != null) + out = new File (outfile); + // + return strip (in, out); + } // strip + + /** + * Strip infile to outfile + * @param infile input file + * @param outfile if the output file is null, the infile is renamed to ".bak" + * @return true if copied + */ + public boolean strip (File infile, File outfile) + { + if (infile == null) + throw new NullPointerException ("Strip: infile cannot ne null"); + // infile + if (!infile.exists() || !infile.isFile()) + throw new IllegalArgumentException ("Strip: infile does not exist or is not a file: " + infile); + System.out.println("Stripping file: " + infile); + + // outfile + if (infile.equals(outfile)) + outfile = null; + boolean tempfile = false; + if (outfile == null) + { + try + { + outfile = File.createTempFile("strip", ".txt"); + } + catch (IOException ioe) + { + System.err.println(ioe); + return false; + } + tempfile = true; + } + // + try + { + if (VERBOSE) + System.out.println("Creating: " + outfile); + outfile.createNewFile(); + } + catch (IOException ioe) + { + System.err.println(ioe); + return false; + } + if (!outfile.exists() || !outfile.canWrite()) + throw new IllegalArgumentException ("Strip output file cannot be created or written: " + outfile); + + // copy it + if (!copy (infile, outfile)) + return false; + + // rename outfile + if (tempfile) + { + if (VERBOSE) + System.out.print("Renaming original: " + infile); + if (!infile.renameTo(new File(infile.getAbsolutePath() + ".bak"))) + System.err.println("Could not rename original file: " + infile); + if (VERBOSE) + System.out.println(" - Renaming: " + outfile + " to: " + infile); + if (!outfile.renameTo(infile)) + System.err.println("Could not rename " + outfile + " to: " + infile); + } + return true; + } // strip + + /** + * Copy the file and strip + * @param infile input file + * @param outfile output file + * @return true if success + */ + private boolean copy (File infile, File outfile) + { + FileInputStream fis = null; + try + { + fis = new FileInputStream(infile); + } + catch (FileNotFoundException fnfe) + { + System.err.println(fnfe); + return false; + } + // + FileOutputStream fos = null; + try + { + fos = new FileOutputStream(outfile, false); // no append + } + catch (FileNotFoundException fnfe) + { + System.err.println(fnfe); + return false; + } + + int noIn = 0; + int noOut = 0; + int noLines = 1; + try + { + int c; + while ((c = fis.read()) != -1) + { + noIn++; + if (c != 10) // lf + { + fos.write(c); + noOut++; + } + if (c == 13) // cr + noLines++; + } + fis.close(); + fos.close(); + } + catch (IOException ioe) + { + System.err.println(ioe); + return false; + } + System.out.println(" read: " + noIn + ", written: " + noOut + " - lines: " + noLines); + return true; + } // stripIt + + /*************************************************************************/ + + /** + * Strip file in args + * @param args infile outfile + */ + public static void main(String[] args) + { + if (args.length == 0) + { + System.err.println("Syntax: Strip infile outfile"); + System.exit(-1); + } + String p2 = null; + if (args.length > 1) + p2 = args[1]; + // + new Strip().strip(args[0], p2); + } // main + +} // Strip diff --git a/base/src/org/compiere/util/ASyncProcess.java b/base/src/org/compiere/util/ASyncProcess.java new file mode 100644 index 0000000000..0c623985ba --- /dev/null +++ b/base/src/org/compiere/util/ASyncProcess.java @@ -0,0 +1,68 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.util; + +import org.compiere.process.*; + +/** + * Async Process Interface. + *

+ * The Process implements the methods. + * The Worker is started like + * MyWorker.start() + *

+ * The worker's run method basically executes + *

+ *      process.lockUI(pi);
+ *      process.executeAsync(pi);
+ *      process.unlockUI(pi);
+ *  
+ * The isUILocked() method is used internally (not called by worker). + * + * @author Jorg Janke + * @version $Id: ASyncProcess.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public interface ASyncProcess +{ + /** + * Lock User Interface. + * Called from the Worker before processing + * @param pi process info + */ + public void lockUI (ProcessInfo pi); + + /** + * Unlock User Interface. + * Called from the Worker when processing is done + * @param pi result of execute ASync call + */ + public void unlockUI (ProcessInfo pi); + + /** + * Is the UI locked (Internal method) + * @return true, if UI is locked + */ + boolean isUILocked(); + + /** + * Method to be executed async. + * Called from the Worker + * @param pi ProcessInfo + */ + public void executeASync (ProcessInfo pi); + +} // ASyncProcess diff --git a/base/src/org/compiere/util/ASyncWorker.java b/base/src/org/compiere/util/ASyncWorker.java new file mode 100644 index 0000000000..4760d36112 --- /dev/null +++ b/base/src/org/compiere/util/ASyncWorker.java @@ -0,0 +1,104 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.util; + +import java.util.logging.*; +import javax.swing.*; +import org.compiere.process.*; + +/** + * ASync Worker for starting methods in classes implementing ASyncProcess + * + * @author Jorg Janke + * @version $Id: ASyncWorker.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class ASyncWorker extends Thread +{ + /** + * Execute method Synchronously + * @param parent parent + * @param pi process info + * @return result + */ + public static ProcessInfo executeSync (ASyncProcess parent, ProcessInfo pi) + { + ASyncWorker worker = new ASyncWorker (parent, pi); + worker.start(); + try + { + worker.join(); + } + catch (InterruptedException e) + { + log.log(Level.SEVERE, "executeSync", e); + } + return worker.getResult(); + } // executeSync + + /** Logger */ + private static CLogger log = CLogger.getCLogger(ASyncWorker.class); + + /** + * Constructor + * @param parent Parent Process + * @param pi process info + */ + public ASyncWorker (ASyncProcess parent, ProcessInfo pi) + { + m_parent = parent; + m_pi = pi; + } // ASuncWorker + + private ProcessInfo m_pi; + private ASyncProcess m_parent; + + /** + * The Worker Method + */ + public void run() + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + m_parent.lockUI(m_pi); + } + }); + + // + m_parent.executeASync(m_pi); + // + + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + m_parent.unlockUI (m_pi); + } + }); + } // run + + /** + * Get Result (usually not used as result is returned via unlockUI + * @return result + */ + public ProcessInfo getResult() + { + return m_pi; + } // getResult + +} // ASyncWorker diff --git a/base/src/org/compiere/util/EnvLoader.java b/base/src/org/compiere/util/EnvLoader.java new file mode 100644 index 0000000000..10bba079da --- /dev/null +++ b/base/src/org/compiere/util/EnvLoader.java @@ -0,0 +1,149 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.util; + +import java.io.*; +import java.util.*; + +/** + * Environment Loader - loads system environment variables int System.properties + * + * @author Jorg Janke + * @version $Id: EnvLoader.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class EnvLoader +{ + private static final boolean DEBUG = false; + + /** + * Load System environment variables into System.properies + *

+ * Prints error messages on System.err + * @param prefix String to prefix variable names + * @return true if success + */ + public static boolean load (String prefix) + { + Properties prop = getEnv(prefix); + if (prop == null) + return false; + // load + Object[] pp = prop.keySet().toArray(); + for (int i = 0; i < pp.length; i++) + { + String key = pp[i].toString(); + String value = prop.getProperty(key); + System.setProperty(key, value); + } + CLogMgt.printProperties(System.getProperties(), "System with Environment", false); + return true; + } // load + + /** + * Ger Environment variables + * @param prefix String to prefix variable names + * @return Properties with prefixed system environment variables or null if not successful + */ + public static Properties getEnv (String prefix) + { + String cmd = "cmd /c set"; // Windows + if (!System.getProperty("os.name", "").startsWith("Win")) + cmd = "set"; // Unix/Linux + String result = execCommand (cmd); + if (result == null || result.length() == 0) + return null; + // + if (prefix == null) + prefix = ""; + return parseEnv (result, prefix); + } // getEnv + + /** + * Execute command and return output + * @param command command + * @return command output + */ + private static String execCommand (String command) + { + Process cmd; + try + { + cmd = Runtime.getRuntime().exec(command); + } + catch (Exception e) + { + System.err.println("-- Error executing command: " + command + " - " + e.toString()); + return null; + } + if (DEBUG) + System.out.println("** Command executed: " + command); + + StringBuffer bufOut = new StringBuffer(); + StringBuffer bufErr = new StringBuffer(); + try + { + InputStream in = cmd.getInputStream(); + InputStream err = cmd.getErrorStream(); + // + int c; + while ((c = in.read()) != -1) + bufOut.append((char)c); + in.close(); + // + while ((c = err.read()) != -1) + bufErr.append((char)c); + err.close(); + } + catch (Exception e) + { + System.err.println("-- Error reading output: " + e.toString()); + return null; + } + if (DEBUG) + { + System.out.println("** Command result: " + bufOut.toString()); + System.out.println("** Command error: " + bufErr.toString()); + } + return bufOut.toString(); + } // execCommand + + /** + * Parse Env and return it in properties + * @param input environment info + * @param prefix prefix for env + * @return properties + */ + private static Properties parseEnv (String input, String prefix) + { + Properties prop = new Properties (); + // + String separator = System.getProperty("line.separator", "\n"); + StringTokenizer st = new StringTokenizer(input, separator); + while (st.hasMoreTokens()) + { + String s = st.nextToken(); + // System.out.println(">" + s + "<"); + int pos = s.indexOf("="); // first "=" + if (pos > 0) + prop.setProperty(prefix + s.substring(0, pos), s.substring(pos+1)); + } + if (DEBUG) + System.out.println("** Loaded " + prop.size() + " Properties"); + return prop; + } // parseEnv + +} // EnvLoader diff --git a/base/src/org/compiere/util/ExtensionFileFilter.java b/base/src/org/compiere/util/ExtensionFileFilter.java new file mode 100644 index 0000000000..e53b079848 --- /dev/null +++ b/base/src/org/compiere/util/ExtensionFileFilter.java @@ -0,0 +1,167 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.util; + +import javax.swing.filechooser.*; +import java.io.File; +import java.io.Serializable; + + +/** + * Extension File Chooser + * + * @author Jorg Janke + * @version $Id: ExtensionFileFilter.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class ExtensionFileFilter extends FileFilter + implements Serializable +{ + /** + * Constructor + */ + public ExtensionFileFilter() + { + this ("",""); + } // ExtensionFileFilter + + /** + * Constructor + * @param extension extension + * @param description description + */ + public ExtensionFileFilter(String extension, String description) + { + setDescription (description); + setExtension (extension); + } // ExtensionFileFilter + + /** Extension */ + private String m_extension; + // + private String m_description; + + + /** + * Description + * @return description + */ + public String getDescription() + { + return m_description; + } + /** + * Set Description + * @param newDescription description + */ + public void setDescription(String newDescription) + { + m_description = newDescription; + } // setDescription + + /** + * Extension + * @param newExtension ext + */ + public void setExtension(String newExtension) + { + m_extension = newExtension; + } + /** + * Get Extension + * @return extension + */ + public String getExtension() + { + return m_extension; + } + + /** + * Accept File + * @param file file to be tested + * @return true if OK + */ + public boolean accept(File file) + { + // Need to accept directories + if (file.isDirectory()) + return true; + + String ext = file.getName(); + int pos = ext.lastIndexOf('.'); + + // No extension + if (pos == -1) + return false; + + ext = ext.substring(pos+1); + + if (m_extension.equalsIgnoreCase(ext)) + return true; + + return false; + } // accept + + + /** + * Verify file name with filer + * @param file file + * @param filter filter + * @return file name + */ + public static String getFileName(File file, FileFilter filter) + { + return getFile(file, filter).getAbsolutePath(); + } // getFileName + + /** + * Verify file with filter + * @param file file + * @param filter filter + * @return file + */ + public static File getFile(File file, FileFilter filter) + { + String fName = file.getAbsolutePath(); + if (fName == null || fName.equals("")) + fName = "Adempiere"; + // + ExtensionFileFilter eff = null; + if (filter instanceof ExtensionFileFilter) + eff = (ExtensionFileFilter)filter; + else + return file; + // + int pos = fName.lastIndexOf('.'); + + // No extension + if (pos == -1) + { + fName += '.' + eff.getExtension(); + return new File(fName); + } + + String ext = fName.substring(pos+1); + + // correct extension + if (ext.equalsIgnoreCase(eff.getExtension())) + return file; + + fName += '.' + eff.getExtension(); + return new File(fName); + } // getFile + +} // ExtensionFileFilter diff --git a/base/src/org/compiere/util/FileUpload.java b/base/src/org/compiere/util/FileUpload.java new file mode 100644 index 0000000000..3ca7cb61cd --- /dev/null +++ b/base/src/org/compiere/util/FileUpload.java @@ -0,0 +1,271 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.util; + +import java.io.*; +import java.util.logging.*; +import javax.servlet.*; +import javax.servlet.http.*; +import org.apache.ecs.xhtml.*; + +/** + * Web File Upload utility. + * Based on code like: + * +

+ + + + + + *
+ * @author Jorg Janke + * @version $Id: FileUpload.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class FileUpload +{ + /** + * Create Upload Form. + * You need to add the (hidden) parameter + * @param action form action + * @return form + */ + public static form createForm (String action) + { + form upload = new form(action, form.METHOD_POST, form.ENC_UPLOAD); + upload.addElement(new label ("File").setFor("file")); + upload.addElement(new input (input.TYPE_FILE, "file", "").setSize(40)); + upload.addElement(new input (input.TYPE_SUBMIT, "upload", "Upload")); + return upload; + } // createForm + + + /************************************************************************** + * Upload File from requesr + * @param request request + */ + public FileUpload (HttpServletRequest request) + { + super (); + try + { + m_error = upload (request); + } + catch (Exception e) + { + log.log(Level.SEVERE, "FileUpload", e); + m_error = e.getLocalizedMessage(); + if (m_error == null || m_error.length() == 0) + m_error = e.toString(); + } + } // FileUpload + + /** Logger */ + protected CLogger log = CLogger.getCLogger(getClass()); + /** File Name */ + private String m_fileName = null; + /* File Data */ + private byte[] m_data = null; + /** Error Message */ + private String m_error = null; + + /** Request Info as Data String */ + private String m_requestDataString = null; + + /** + * @return Returns the data. + */ + public byte[] getData () + { + return m_data; + } // getData + + /** + * @return Returns the actual fileName (without path). + */ + public String getFileName () + { + if (m_fileName != null) // eliminate path + { + int index = Math.max(m_fileName.lastIndexOf('/'), m_fileName.lastIndexOf('\\')); + if (index > 0) + return m_fileName.substring(index+1); + } + return m_fileName; + } // getFileName + + /** + * @return Returns the error message or null. + */ + public String getError () + { + return m_error; + } // getError + + /************************************************************************** + * Upload File + * @param request request + * @throws ServletException + * @throws IOException + * @return error message or null + */ + private String upload (HttpServletRequest request) + throws ServletException, IOException + { + final int MAX_KB = 250; // Max Upload Size in kB + // + int formDataLength = request.getContentLength(); + String contentType = request.getContentType(); + int index = contentType.lastIndexOf("="); + String boundary = contentType.substring(index+1); + log.fine(formDataLength + " - " + boundary); + int sizeKB = formDataLength/1024; + if (sizeKB > MAX_KB) // 250k + { + log.warning("File too large " + sizeKB); + return "File too large = " + sizeKB + + "kB - Allowed = " + MAX_KB + "kB"; + } + + DataInputStream in = new DataInputStream (request.getInputStream()); + byte[] data = new byte[formDataLength]; + int bytesRead = 0; + int totalBytesRead = 0; + while (totalBytesRead < formDataLength) + { + bytesRead = in.read(data, totalBytesRead, formDataLength); + totalBytesRead += bytesRead; + } + + // Convert to String for easy manipulation + m_requestDataString = new String (data, "ISO-8859-1"); + if (m_requestDataString.length() != data.length) + return "Internal conversion Error"; + + // File Name: + // Content-Disposition: form-data; name="file"; filename="C:\Documents and Settings\jjanke\My Documents\desktop.ini" + index = m_requestDataString.indexOf("filename=\""); + m_fileName = m_requestDataString.substring(index+10); + index = m_fileName.indexOf('"'); + if (index < 1) + return "No File Name"; + m_fileName = m_fileName.substring(0, index); + log.fine("upload - " + m_fileName); + + + // Content: + // Content-Disposition: form-data; name="file"; filename="C:\Documents and Settings\jjanke\My Documents\desktop.ini" + // Content-Type: application/octet-stream + // + // [DeleteOnCopy] + // Owner=jjanke + // Personalized=5 + // PersonalizedName=My Documents + // + // -----------------------------7d433475038e + int posStart = m_requestDataString.indexOf("filename=\""); + posStart = m_requestDataString.indexOf("\n",posStart)+1; // end of Context-Disposition + posStart = m_requestDataString.indexOf("\n",posStart)+1; // end of Content-Type + posStart = m_requestDataString.indexOf("\n",posStart)+1; // end of empty line + int posEnd = m_requestDataString.indexOf(boundary, posStart)-4; + int length = posEnd-posStart; + // + log.fine("uploadFile - Start=" + posStart + ", End=" + posEnd + ", Length=" + length); + + // Final copy + m_data = new byte[length]; + for (int i = 0; i < length; i++) + m_data[i] = data[posStart+i]; + return null; + } // uploadFile + + /** + * Get MultiPart Form Parameter. + * Assumes single line (no cr) + * + Request + -----------------------------7d433475038e + Content-Disposition: form-data; name="R_Request_ID" + + 1000000 + -----------------------------7d433475038e-- + + * @param parameterName name of parameter + * @return parameter or null of mot found + */ + public String getParameter (String parameterName) + { + if (m_requestDataString == null) + return null; + String retValue = null; + String search = "name=\"" + parameterName + "\""; + int index = m_requestDataString.indexOf(search); + if (index > 0) + { + retValue = m_requestDataString.substring(index); + retValue = retValue.substring(retValue.indexOf("\n")+1); // eol + retValue = retValue.substring(retValue.indexOf("\n")+1); // empty line + retValue = retValue.substring(0,retValue.indexOf("\n")); // cr + retValue = retValue.trim(); + } + else + { + log.warning("getParameter Not found - " + parameterName); + return null; + } + log.fine("getParameter = " + parameterName + "=" + retValue); + return retValue; + } // getMultiPartParameter + + /** + * Get Multi Part Parameter As Int + * @param parameterName name + * @return result or 0 + */ + public int getParameterAsInt (String parameterName) + { + String result = getParameter (parameterName); + try + { + if (result != null && result.length() > 0) + return Integer.parseInt(result); + } + catch (Exception e) + { + log.log(Level.SEVERE, "getParameterAsInt - " + parameterName + "=" + result, e); + } + return 0; + } // getParameterAsInt + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("FileUpload["); + if (m_fileName != null) + sb.append(m_fileName); + if (m_error != null) + sb.append(";Error=").append(m_error); + if (m_data != null) + sb.append(";Length=").append(m_data.length); + sb.append ("]"); + return sb.toString (); + } // toString + +} // FileUpload diff --git a/base/src/org/compiere/util/HtmlCode.java b/base/src/org/compiere/util/HtmlCode.java new file mode 100644 index 0000000000..c4d88dbde4 --- /dev/null +++ b/base/src/org/compiere/util/HtmlCode.java @@ -0,0 +1,100 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.util; + +import org.apache.ecs.*; + +/** + * ECS Component Collection. + * + * @author Jorg Janke + * @version $Id: HtmlCode.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class HtmlCode extends MultiPartElement + implements Printable +{ + /** + * HtmlCode + */ + public HtmlCode () + { + setNeedClosingTag (false); + setTagText (""); + setStartTagChar (' '); + setEndTagChar (' '); + } // HtmlCode + + /** + Adds an Element to the element. + @param hashcode name of element for hash table + @param element Adds an Element to the element. + @return this + */ + public HtmlCode addElement (String hashcode, Element element) + { + addElementToRegistry (hashcode, element); + return (this); + } + + + /** + Adds an Element to the element. + @param hashcode name of element for hash table + @param element Adds an Element to the element. + @return this + */ + public HtmlCode addElement (String hashcode, String element) + { + addElementToRegistry (hashcode, element); + return (this); + } + + + /** + Adds an Element to the element. + @param element Adds an Element to the element. + @return this + */ + public HtmlCode addElement (Element element) + { + addElementToRegistry (element); + return (this); + } + + /** + Adds an Element to the element. + @param element Adds an Element to the element. + @return this + */ + public HtmlCode addElement (String element) + { + addElementToRegistry (element); + return (this); + } + + /** + Removes an Element from the element. + @param hashcode the name of the element to be removed. + @return this + */ + public HtmlCode removeElement (String hashcode) + { + removeElementFromRegistry (hashcode); + return (this); + } + +} // HtmlCode diff --git a/base/src/org/compiere/util/Queue.java b/base/src/org/compiere/util/Queue.java new file mode 100644 index 0000000000..d9429247f8 --- /dev/null +++ b/base/src/org/compiere/util/Queue.java @@ -0,0 +1,444 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.util; + +import java.io.*; +//import oracle.AQ.*; + +//import org.compiere.db.CConnection; + +/** + * Message Queuing + * + * @author Jorg Janke + * @version $Id: Queue.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public final class Queue implements Serializable +{ +/* + private static Connection s_connection; + private static AQSession s_session; + private static AQQueue s_queueS; + private static AQQueue s_queueC; + // + private static String s_queueName = "AQ_"; + private static String s_toServer = "S"; + private static String s_toClient = "C"; + private static String s_table_extension = "_Tab"; + + + /** + * Create AQ Session + * + private static AQSession createSession() + { + log.config( "Queue.createSession"); + if (s_connection == null) // autoCommit + // get dedicated + s_connection = DB.createConnection(true, Connection.TRANSACTION_READ_COMMITTED); + + AQSession aq_sess = null; + try + { + Class.forName("oracle.AQ.AQOracleDriver"); + } + catch (ClassNotFoundException e) + { + log.log(Level.SEVERE, "Queue.createSession (Driver)", e); + } + try + { + aq_sess = AQDriverManager.createAQSession(s_connection); + } + catch (Exception e) + { + log.log(Level.SEVERE, "Queue.createSession", e); + } + + return aq_sess; + } // createSession + + /** + * Get AQ Session + * + private static AQSession getSession() + { + if (s_session == null) + s_session = createSession(); + return s_session; + } // getSession + + /** + * Create Queue + * + private static AQQueue createQueue(String name) + { + log.config( "Queue.createQueue - " + name); + // + AQSession session = getSession(); + if (session == null) + return null; + + AQQueue queue = null; + try + { + // Payload type: raw - Age Ordered + AQQueueTableProperty t_property = new AQQueueTableProperty("RAW"); + t_property.setComment("Adempiere Client/Server Communication Table"); + t_property.setSortOrder("ENQ_TIME"); + t_property.setMultiConsumer(false); + // t_property.setCompatible("8.1"); + // Create table in the Adempiere scheme + String tabName = name + s_table_extension; + AQQueueTable table = session.createQueueTable(CConnection.get().getDbUid(), + tabName, t_property); + log.fine( "Queue Table created - " + tabName); + + // Create Queue property + AQQueueProperty q_property = new AQQueueProperty(); + q_property.setComment("Adempiere Client/Server Communication Queue"); + q_property.setRetentionTime(AQQueueProperty.INFINITE); + queue = session.createQueue(table, name, q_property); + log.fine( "Queue created - " + name); + } + catch (Exception e) + { + log.log(Level.SEVERE, "Queue.createQueue", e); + } + // + return queue; + } // createQueue + + /** + * Get Queue "Test" + * + protected static AQQueue getQueue(boolean toServer, boolean reset) + { + if (reset) + close(false); + // Server Queue + if (toServer && s_queueS == null) + { + AQSession session = getSession(); + try + { + s_queueS = session.getQueue(CConnection.get().getDbUid(), + s_queueName+s_toServer); + } + catch (AQException e) + { + try + { + // No Queue - So create it + s_queueS = createQueue(s_queueName+s_toServer); + s_queueS.start(); + } + catch (Exception e2) + { + log.log(Level.SEVERE, "Queue.getQueue (create1)", e2); + } + } + } + // Client Queue + if (!toServer && s_queueC == null) + { + AQSession session = getSession(); + try + { + s_queueC = session.getQueue(CConnection.get().getDbUid(), + s_queueName+s_toClient); + } + catch (AQException e) + { + try + { + // No Queue - So create it + s_queueC = createQueue(s_queueName+s_toClient); + s_queueC.start(); + } + catch (Exception e2) + { + log.log(Level.SEVERE, "Queue.getQueue (create2)", e2); + } + } + } + if (toServer) + return s_queueS; + return s_queueC; + } // getQueue + + /** + * Drop Queue + * + private static void dropQueues() + { + log.config( "Queue.dropQueues"); + // + String tabNameS = s_queueName + s_toServer + s_table_extension; + String tabNameC = s_queueName + s_toClient + s_table_extension; + try + { + AQQueueTable tableS = getSession().getQueueTable(CConnection.get().getDbUid(), tabNameS); + AQQueueTable tableC = getSession().getQueueTable(CConnection.get().getDbUid(), tabNameC); + tableS.drop(true); + tableC.drop(true); + } + catch (Exception e) + { + log.log(Level.SEVERE, "Queue.dropQueues - " + e.getMessage()); + } + } // dropQueues + + /** + * Close Queues & Session + * + public static void close (boolean closeConnection) + { + s_queueC = null; + s_queueS = null; + s_session = null; + if (closeConnection && s_connection != null) + { + try + { + s_connection.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, "Queue.close", e); + } + s_connection = null; + } + } // close + + + /** + * Send Message + * + protected static boolean send (Serializable info, boolean toServer) + { + if (info == null) + return false; + + // Serialize info + byte[] data = null; + try + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream (baos); + oos.writeObject(info); + oos.flush(); + oos.close(); + data = baos.toByteArray(); + baos.close(); + } + catch (IOException ioe) + { + log.log(Level.SEVERE, "Queue.send IO - " + ioe.getMessage()); + return false; + } + + try + { + // create Message + AQQueue queue = getQueue(toServer, false); + AQMessage message = queue.createMessage(); + // populate payload + AQRawPayload rawPayload = message.getRawPayload(); + rawPayload.setStream(data, data.length); + + // Standard enqueue Options + AQEnqueueOption option = new AQEnqueueOption(); + + // Enqueue + queue.enqueue(option, message); + } + catch (Exception e) + { + log.log(Level.SEVERE, "Queue.send", e); + return false; + } + log.config( "Queue.send " + info.getClass() + + (toServer ? " ToServer" : " ToClient") + + ", Size=" + data.length); + return true; + } // send + + /** + * Receive message + * + protected static Serializable receive (boolean fromServer) + { + // Get Queue + AQQueue queue = getQueue(!fromServer, false); + + // Get Message + AQMessage message = null; + try + { + // Set Dequeue Option + AQDequeueOption option = new AQDequeueOption(); + option.setWaitTime(1); // one second wait + // option.setDequeueMode(AQDequeueOption.DEQUEUE_REMOVE); + // + message = queue.dequeue(option); + } + catch (AQOracleSQLException e) + { + if (e.getErrorCode() == 25228) // timeout + return null; + log.log(Level.SEVERE, "Queue.receive", e); + return null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "Queue.receive", e); + return null; + } + + Serializable info = deserialize (message); + + log.config( "Queue.receive " + info.getClass() + + (fromServer ? " FromServer" : " FromClient")); + return info; + } // receive + + /** + * De-Serialize + * + private static Serializable deserialize (AQMessage message) + { + // Deserialize + Serializable info = null; + try + { + // get Payload + AQRawPayload raw_payload = message.getRawPayload(); + byte[] data = raw_payload.getBytes(); + // + ByteArrayInputStream bais = new ByteArrayInputStream(data); + ObjectInputStream ois = new ObjectInputStream (bais); + info = (Serializable)ois.readObject(); + ois.close(); + bais.close(); + } + catch (Exception e) + { + log.log(Level.SEVERE, "Queue.deserialize", e); + return null; + } + return info; + } // deserialize + + /** + * List message + * + protected static ArrayList listMessages (boolean fromServer) + { + // Get Queue + AQQueue queue = getQueue(!fromServer, true); + AQDequeueOption option = new AQDequeueOption(); + try + { + log.config( "Queue.listMessages - " + queue.getName()); + + // Set Dequeue Option + option.setWaitTime(0); // no wait + option.setDequeueMode(AQDequeueOption.DEQUEUE_BROWSE); + } + catch (Exception e) + { + log.log(Level.SEVERE, "Queue.lsiMessages", e); + } + + ArrayList list = new ArrayList(); + + // Get Messages + AQMessage message = null; + do + { + try + { + message = queue.dequeue(option); + Serializable info = deserialize (message); + list.add(info); + log.config( "> " + info.toString()); + } + catch (AQOracleSQLException e) + { + if (e.getErrorCode() != 25228) // timeout + log.log(Level.SEVERE, "Queue.receive", e); + message = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "Queue.receive", e); + } + } while (message != null); + return list; + } // listMessages + + + + + public static boolean sendToServer(Serializable info) + { + return send (info, true); + } + + public static boolean sendToClient(Serializable info) + { + return send (info, false); + } + + public static Serializable receiveFromServer() + { + return receive (true); + } + + public static Serializable receiveFromClient() + { + return receive (false); + } + + /************************************************************************** + * Main Test + * + public static void main (String[] args) + { + Env.initTest(9, true); // run as Client + + // dropQueues(); + Timestamp t = new Timestamp(System.currentTimeMillis()); + + sendToServer ("This is a new test " + t.toString()); + sendToClient (new KeyNamePair (21, "Twenty-one " + t.toString())); + sendToServer ("This is a second test " + t.toString()); + sendToClient (new KeyNamePair (22, "Twenty-two " + t.toString())); + listMessages(true); + listMessages(false); + System.out.println(receiveFromClient()); + System.out.println(receiveFromServer()); + listMessages(true); + listMessages(false); + + System.out.println("Fini"); + System.exit(0); + // AEnv.exit(0); + } // Main +*/ +} // Queue diff --git a/base/src/org/compiere/util/ReplenishInterface.java b/base/src/org/compiere/util/ReplenishInterface.java new file mode 100644 index 0000000000..e675bf8c3a --- /dev/null +++ b/base/src/org/compiere/util/ReplenishInterface.java @@ -0,0 +1,39 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.util; + +import java.math.*; +import org.compiere.model.*; + +/** + * Custom Replenishment Interface + * + * @author Jorg Janke + * @version $Id: ReplenishInterface.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public interface ReplenishInterface +{ + + /** + * Return the Qty To Order + * @param wh warehouse + * @param replenish temporary replenishment + * @return qty to order + */ + public BigDecimal getQtyToOrder (MWarehouse wh, X_T_Replenish replenish); + +} // ReplenishmentInterface diff --git a/base/src/org/compiere/util/Task.java b/base/src/org/compiere/util/Task.java new file mode 100644 index 0000000000..86485fd769 --- /dev/null +++ b/base/src/org/compiere/util/Task.java @@ -0,0 +1,216 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.util; + +import java.io.*; +import java.util.logging.*; + +/** + * Execute OS Task + * + * @author Jorg Janke + * @version $Id: Task.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class Task extends Thread +{ + /** + * Create Process with cmd + * @param cmd o/s command + */ + public Task (String cmd) + { + m_cmd = cmd; + } // Task + + private String m_cmd; + private Process m_child = null; + + private StringBuffer m_out = new StringBuffer(); + private StringBuffer m_err = new StringBuffer(); + + /** The Output Stream of process */ + private InputStream m_outStream; + /** The Error Output Stream of process */ + private InputStream m_errStream; + /** The Input Stream of process */ + private OutputStream m_inStream; + + /** Logger */ + private static CLogger log = CLogger.getCLogger(Task.class); + + /** Read Out */ + private Thread m_outReader = new Thread() + { + public void run() + { + log.fine("outReader"); + try + { + int c; + while ((c = m_outStream.read()) != -1 && !isInterrupted()) + { + // System.out.print((char)c); + m_out.append((char)c); + } + m_outStream.close(); + } + catch (IOException ioe) + { + log.log(Level.SEVERE, "outReader", ioe); + } + log.fine("outReader - done"); + } // run + }; // m_outReader + + /** Read Out */ + private Thread m_errReader = new Thread() + { + public void run() + { + log.fine("errReader"); + try + { + int c; + while ((c = m_errStream.read()) != -1 && !isInterrupted()) + { + // System.err.print((char)c); + m_err.append((char)c); + } + m_errStream.close(); + } + catch (IOException ioe) + { + log.log(Level.SEVERE, "errReader", ioe); + } + log.fine("errReader - done"); + } // run + }; // m_errReader + + + /** + * Execute it + */ + public void run() + { + log.info(m_cmd); + try + { + m_child = Runtime.getRuntime().exec(m_cmd); + // + m_outStream = m_child.getInputStream(); + m_errStream = m_child.getErrorStream(); + m_inStream = m_child.getOutputStream(); + // + if (checkInterrupted()) + return; + m_outReader.start(); + m_errReader.start(); + // + try + { + if (checkInterrupted()) + return; + m_errReader.join(); + if (checkInterrupted()) + return; + m_outReader.join(); + if (checkInterrupted()) + return; + m_child.waitFor(); + } + catch (InterruptedException ie) + { + log.log(Level.INFO, "(ie) - " + ie); + } + // ExitValue + try + { + if (m_child != null) + log.fine("run - ExitValue=" + m_child.exitValue()); + } + catch (Exception e) {} + log.config("done"); + } + catch (IOException ioe) + { + log.log(Level.SEVERE, "(ioe)", ioe); + } + } // run + + /** + * Check if interrupted + * @return true if interrupted + */ + private boolean checkInterrupted() + { + if (isInterrupted()) + { + log.config("interrupted"); + // interrupt child processes + if (m_child != null) + m_child.destroy(); + m_child = null; + if (m_outReader != null && m_outReader.isAlive()) + m_outReader.interrupt(); + m_outReader = null; + if (m_errReader != null && m_errReader.isAlive()) + m_errReader.interrupt(); + m_errReader = null; + // close Streams + if (m_inStream != null) + try { m_inStream.close(); } catch (Exception e) {} + m_inStream = null; + if (m_outStream != null) + try { m_outStream.close(); } catch (Exception e) {} + m_outStream = null; + if (m_errStream != null) + try { m_errStream.close(); } catch (Exception e) {} + m_errStream = null; + // + return true; + } + return false; + } // checkInterrupted + + /** + * Get Out Info + * @return StringBuffer + */ + public StringBuffer getOut() + { + return m_out; + } // getOut + + /** + * Get Err Info + * @return StringBuffer + */ + public StringBuffer getErr() + { + return m_err; + } // getErr + + /** + * Get The process input stream - i.e. we output to it + * @return OutputStream + */ + public OutputStream getInStream() + { + return m_inStream; + } // getInStream + +} // Task diff --git a/base/src/org/compiere/util/WebDoc.java b/base/src/org/compiere/util/WebDoc.java new file mode 100644 index 0000000000..d6b8f0ccbd --- /dev/null +++ b/base/src/org/compiere/util/WebDoc.java @@ -0,0 +1,367 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.util; + +import java.io.*; +import org.apache.ecs.*; +import org.apache.ecs.xhtml.*; + + +/** + * XHTML Document. + * + * @author Jorg Janke + * @version $Id: WebDoc.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class WebDoc +{ + /** + * Create styled Document with Title + * @param plain if true adds standard.css and standard.js + * @param title optional header title and h1 + * @param javaClient true if Java Client - browser otherwise + * @return Document + */ + public static WebDoc create (boolean plain, String title, boolean javaClient) + { + WebDoc doc = new WebDoc(); + doc.setUp (plain, javaClient, title); + return doc; + } // create + + /** + * Create Document + * @param plain if true adds stylesheet and standard js + * @return Document + */ + public static WebDoc create (boolean plain) + { + return create (plain, null, false); + } // create + + /** + * Create styled popup Document with Title + * @param title header title and h1 + * @return Document + */ + public static WebDoc createPopup (String title) + { + WebDoc doc = create (title); + doc.getHead().addElement(new script((Element)null, "window.js")); + doc.getHead().addElement(new link("popup.css", link.REL_STYLESHEET, link.TYPE_CSS)); + doc.setClasses ("popupTable", "popupHeader"); + doc.getTable().setCellSpacing(5); + return doc; + } // createPopup + + /** + * Create styled window Document with Title + * @param title header title and h1 + * @return Document + */ + public static WebDoc createWindow (String title) + { + WebDoc doc = create (title); + doc.getHead().addElement(new link("window.css", link.REL_STYLESHEET, link.TYPE_CSS)); + doc.getHead().addElement(new script((Element)null, "window.js")); + doc.setClasses ("windowTable", "windowHeader"); + doc.getTable().setCellSpacing(5); + return doc; + } // createWindow + + /** + * Create styled web Document with Title + * @param title optional header title and h1 + * @return Document + */ + public static WebDoc create (String title) + { + return create (false, title, false); + } // create + + /** Non brealing Space */ + public static final String NBSP = " "; + + + /************************************************************************** + * Create new XHTML Document structure + */ + private WebDoc () + { + } // WDoc + + private html m_html = new html(); + private head m_head = new head(); + private body m_body = new body(); + private table m_table = null; + private tr m_topRow = null; + private td m_topRight = null; + private td m_topLeft = null; + + /** + * Set up Document + * @param plain if true adds stylesheet and standard js + * @param javaClient true if Java Client - browser otherwise + * @param title header title and h1 + */ + private void setUp (boolean plain, boolean javaClient, String title) + { + m_html.addElement(m_head); + m_html.addElement(m_body); + m_body.addElement(new a().setName("top")); + if (title != null) + m_head.addElement(new title(title)); + if (plain) + return; + + // css, js + if (javaClient) + m_head.addElement(new link("http://www.adempiere.org/standard.css", link.REL_STYLESHEET, link.TYPE_CSS)); + else + { + m_head.addElement(new link(WebEnv.getStylesheetURL(), link.REL_STYLESHEET, link.TYPE_CSS)); + m_head.addElement(new script((Element)null, WebEnv.getBaseDirectory("standard.js"))); + } + m_head.addElement(new meta().setHttpEquiv("Content-Type", "text/html; charset=UTF-8")); + m_head.addElement(new meta().setName("description", "adempiere HTML UI")); + + m_table = new table("0", "2", "0", "100%", null); // spacing 2 + m_topRow = new tr(); + // Title + m_topLeft = new td(); + if (title == null) + m_topLeft.addElement(NBSP); + else + m_topLeft.addElement(new h1(title)); + m_topRow.addElement(m_topLeft); + // Logo + m_topRight = new td().setAlign("right"); + /** Removing/modifying the adempiere logo is a violation of the license */ + if (javaClient) + m_topRight.addElement(new img("http://www.adempiere.org/images/adempiere64x32.png") + // Changing the copyright notice in any way violates the license + // and you'll be held liable for any damage claims + .setAlign(AlignType.RIGHT).setAlt("© Jorg Janke/adempiere")); + else + m_topRight.addElement(WebEnv.getLogo()); + m_topRow.addElement(m_topRight); + m_table.addElement(m_topRow); + // + m_body.addElement(m_table); + } // setUp + + /** + * Set css Classes + * @param tableClass optional class for table + * @param tdClass optional class for left/right td + */ + public void setClasses (String tableClass, String tdClass) + { + if (m_table != null && tableClass != null) + m_table.setClass(tableClass); + if (m_topLeft != null && tdClass != null) + m_topLeft.setClass(tdClass); + if (m_topRight != null && tdClass != null) + m_topRight.setClass(tdClass); + } // setClasses + + + /** + * Get Body + * @return Body + */ + public body getBody() + { + return m_body; + } // getBody + + /** + * Get Head + * @return Header + */ + public head getHead() + { + return m_head; + } // getHead + + /** + * Get Table (no class set) + * @return table + */ + public table getTable() + { + return m_table; + } // getTable + + /** + * Get Table Row (no class set) + * @return table row + */ + public tr getTopRow() + { + return m_topRow; + } // getTopRow + /** + * Get Table Data Left (no class set) + * @return table data + */ + public td getTopLeft() + { + return m_topLeft; + } // getTopLeft + + /** + * Get Table Data Right (no class set) + * @return table data + */ + public td getTopRight() + { + return m_topRight; + } // getTopRight + + /** + * String representation + * @return String + */ + public String toString() + { + return m_html.toString(); + } // toString + + /** + * Output Document + * @param out out + */ + public void output (OutputStream out) + { + m_html.output(out); + } // output + + /** + * Output Document + * @param out out + */ + public void output (PrintWriter out) + { + m_html.output(out); + } // output + + /** + * Add Popup Center + * @param nowrap set nowrap in td + * @return null or center single td + */ + public td addPopupCenter(boolean nowrap) + { + if (m_table == null) + return null; + // + td center = new td ("popupCenter", AlignType.CENTER, AlignType.MIDDLE, nowrap); + center.setColSpan(2); + m_table.addElement(new tr() + .addElement(center)); + return center; + } // addPopupCenter + + /** + * Add Popup Close Footer + * @return null or array with left/right td + */ + public td[] addPopupClose() + { + input button = WebUtil.createClosePopupButton(); + if (m_table == null) + { + m_body.addElement(button); + return null; + } + // + td left = new td("popupFooter", AlignType.LEFT, AlignType.MIDDLE, false, null); + td right = new td("popupFooter", AlignType.RIGHT, AlignType.MIDDLE, false, button); + m_table.addElement(new tr() + .addElement(left) + .addElement(right)); + return new td[] {left, right}; + } // addPopupClose + + + /** + * Add Window Center + * @param nowrap set nowrap in td + * @return empty single center td + */ + public td addWindowCenter(boolean nowrap) + { + if (m_table == null) + return null; + // + td center = new td ("windowCenter", AlignType.CENTER, AlignType.MIDDLE, nowrap); + center.setColSpan(2); + m_table.addElement(new tr() + .addElement(center)); + return center; + } // addWindowCenter + + /** + * Add Window Footer + * @return null or array with empty left/right td + */ + public td[] addWindowFooters() + { + if (m_table == null) + return null; + // + td left = new td("windowFooter", AlignType.LEFT, AlignType.MIDDLE, false); + td right = new td("windowFooter", AlignType.RIGHT, AlignType.MIDDLE, false); + m_table.addElement(new tr() + .addElement(left) + .addElement(right)); + return new td[] {left, right}; + } // addWindowFooters + + /** + * Add Window Footer + * @return empty single center td + */ + public td addWindowFooter() + { + if (m_table == null) + return null; + // + td center = new td("windowFooter", AlignType.CENTER, AlignType.MIDDLE, false); + m_table.addElement(new tr() + .addElement(center)); + return center; + } // addWindowFooter + + /************************************************************************** + * Test Class + * @param args args + */ + public static void main (String[] args) + { + WebDoc doc = WebDoc.create("Test"); + doc.getBody().addElement(new b("111 <<< >>> &&& \\\\ \u0100 �")); + form f = new form("myaction"); + f.addElement(new input()); + doc.getBody().addElement(f); + System.out.println(doc.toString()); + System.out.println("---------"); + doc.output(System.out); + System.out.println("---------"); + } // main +} // WDoc diff --git a/base/src/org/compiere/util/WebEnv.java b/base/src/org/compiere/util/WebEnv.java new file mode 100644 index 0000000000..b9e9a5dfd5 --- /dev/null +++ b/base/src/org/compiere/util/WebEnv.java @@ -0,0 +1,725 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.util; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import javax.servlet.*; +import javax.servlet.http.*; +import org.apache.ecs.*; +import org.apache.ecs.xhtml.*; + +import org.compiere.*; +import org.compiere.model.*; + +/** + * Web Environment and debugging + * + * @author Jorg Janke + * @version $Id: WebEnv.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class WebEnv +{ + /** Add HTML Debug Info */ + public static boolean DEBUG = true; + /** Logging */ + private static CLogger log = CLogger.getCLogger(WebEnv.class); + + /** + * Base Directory links http://localhost:8080/adempiere + * to the physical %adempiere_HOME%/tomcat/webroot/adempiere directory + */ + public static final String DIR_BASE = "/adempiere"; // /adempiere + /** Image Sub-Directory under BASE */ + private static final String DIR_IMAGE = "images"; // /adempiere/images + /** Stylesheet Name */ + private static final String STYLE_STD = "standard.css"; // /adempiere/standard.css + /** Small Logo. + /** Removing/modifying the adempiere logo is a violation of the license */ + private static final String LOGO = "LogoSmall.gif"; // /adempiere/LogoSmall.gif + /** Store Sub-Directory under BASE */ + private static final String DIR_STORE = "store"; // /adempiere/store + + /** Frame name for Commands - WCmd */ + public static final String TARGET_CMD = "WCmd"; + /** Frame name for Menu - WMenu */ + public static final String TARGET_MENU = "WMenu"; + /** Frame name for Apps Window - WWindow */ + public static final String TARGET_WINDOW = "WWindow"; + /** Frame name for Apps PopUp - WPopUp */ + public static final String TARGET_POPUP = "WPopUp"; + + /** Character Set (iso-8859-1 - utf-8) */ + public static final String CHARSET = "UTF-8"; // Default: UNKNOWN + /** Encoding (ISO-8859-1 - UTF-8) */ + public static final String ENCODING = "UTF-8"; + /** Cookie Name */ + public static final String COOKIE_INFO = "adempiereInfo"; + + /** Timeout - 15 Minutes */ + public static final int TIMEOUT = 15*60; + + + /** Initialization OK? */ + private static boolean s_initOK = false; + /** Not Braking Space */ + public static String NBSP = " "; + + /** + * Init Web Environment. + * To be called from every Servlet in the init method + * or any other Web resource to make sure that the + * environment is properly set. + * @param config config + * @return false if initialization problems + */ + public static boolean initWeb (ServletConfig config) + { + if (s_initOK) + { + log.info(config.getServletName()); + return true; + } + + Enumeration en = config.getInitParameterNames(); + StringBuffer info = new StringBuffer("Servlet Init Parameter: ") + .append(config.getServletName()); + while (en.hasMoreElements()) + { + String name = en.nextElement().toString(); + String value = config.getInitParameter(name); + System.setProperty(name, value); + info.append("\n").append(name).append("=").append(value); + } + + boolean retValue = initWeb (config.getServletContext()); + + // Logging now initiated + log.info(info.toString()); + return retValue; + } // initWeb + + /** + * Init Web. + * Only call directly for Filters, etc. + * @param context servlet context + * @return false if initialization problems + */ + public static boolean initWeb (ServletContext context) + { + if (s_initOK) + { + log.info(context.getServletContextName()); + return true; + } + + // Load Environment Variables (serverApps/src/web/WEB-INF/web.xml) + Enumeration en = context.getInitParameterNames(); + StringBuffer info = new StringBuffer("Servlet Context Init Parameters: ") + .append(context.getServletContextName()); + while (en.hasMoreElements()) + { + String name = en.nextElement().toString(); + String value = context.getInitParameter(name); + System.setProperty(name, value); + info.append("\n").append(name).append("=").append(value); + } + + try + { + s_initOK = Adempiere.startup(false); + } + catch (Exception ex) + { + log.log(Level.SEVERE, "startup", ex); + } + if (!s_initOK) + return false; + + // Logging now initiated + log.info(info.toString()); + // + Properties ctx = new Properties(); + MClient client = MClient.get(ctx, 0); + MSystem system = MSystem.get(ctx); + client.sendEMail(client.getRequestEMail(), + "Server started: " + system.getName(), + "ServerInfo: " + context.getServerInfo(), null); + + return s_initOK; + } // initWeb + + + /************************************************************************** + * Get Base Directory entrry. + *
+ * /adempiere/ + * @param entry file entry or path + * @return url to entry in base directory + */ + public static String getBaseDirectory (String entry) + { + StringBuffer sb = new StringBuffer (DIR_BASE); + if (!entry.startsWith("/")) + sb.append("/"); + sb.append(entry); + return sb.toString(); + } // getBaseDirectory + + /** + * Get Image Directory entry. + *
+ * /adempiere/images + * @param entry file entry or path + * @return url to entry in image directory + */ + public static String getImageDirectory(String entry) + { + StringBuffer sb = new StringBuffer (DIR_BASE); + sb.append("/").append(DIR_IMAGE); + if (!entry.startsWith("/")) + sb.append("/"); + sb.append(entry); + return sb.toString(); + } // getImageDirectory + + /** + * Get Store Directory entry. + *
+ * /adempiere/store + * @param entry file entry or path + * @return url to entry in store directory + */ + public static String getStoreDirectory(String entry) + { + StringBuffer sb = new StringBuffer (DIR_BASE); + sb.append("/").append(DIR_STORE); + if (!entry.startsWith("/")) + sb.append("/"); + sb.append(entry); + return sb.toString(); + } // getStoreDirectory + + /** + * Get Logo Path. + * Removing/modifying the adempiere logo is a violation of the license + *

+ * /adempiere/LogoSmall.gif + * @return url to logo + */ + public static String getLogoURL() + { + return getBaseDirectory(LOGO); + } // getLogoPath + + /** + * Get Logo Image HTML tag. + * Removing/modifying the adempiere logo or copyright notice is a violation of the license + * @return Image + */ + public static img getLogo() + { + /** Removing/modifying the adempiere logo is a violation of the license */ + return new img(getLogoURL()).setAlign(AlignType.RIGHT) + // Changing the copyright notice in any way violates the license + // and you'll be held liable for any damage claims + .setAlt("© Jorg Janke/adempiere"); + } // getLogo + + /** + * Get Stylesheet Path. + *

+ * /adempiere/standard.css + * @return url of Stylesheet + */ + public static String getStylesheetURL() + { + return getBaseDirectory(STYLE_STD); + } // getStylesheetURL + + /** + * Get Cell Content + * @param content optional content + * @return string content or non breaking space + */ + public static String getCellContent (Object content) + { + if (content == null) + return NBSP; + String str = content.toString(); + if (str.length() == 0) + return NBSP; + return str; + } // getCellContent + + /** + * Get Cell Content + * @param content optional content + * @return string content + */ + public static String getCellContent (int content) + { + return String.valueOf(content); + } // getCellContent + + /************************************************************************** + * Dump Servlet Config + * @param config config + */ + public static void dump (ServletConfig config) + { + log.config("ServletConfig " + config.getServletName()); + log.config("- Context=" + config.getServletContext()); + if (!CLogMgt.isLevelFiner()) + return; + boolean first = true; + Enumeration e = config.getInitParameterNames(); + while (e.hasMoreElements()) + { + if (first) + log.finer("InitParameter:"); + first = false; + String key = (String)e.nextElement(); + Object value = config.getInitParameter(key); + log.finer("- " + key + " = " + value); + } + } // dump (ServletConfig) + + /** + * Dump Session + * @param ctx servlet context + */ + public static void dump (ServletContext ctx) + { + log.config("ServletContext " + ctx.getServletContextName()); + log.config("- ServerInfo=" + ctx.getServerInfo()); + if (!CLogMgt.isLevelFiner()) + return; + boolean first = true; + Enumeration e = ctx.getInitParameterNames(); + while (e.hasMoreElements()) + { + if (first) + log.finer("InitParameter:"); + first = false; + String key = (String)e.nextElement(); + Object value = ctx.getInitParameter(key); + log.finer("- " + key + " = " + value); + } + first = true; + e = ctx.getAttributeNames(); + while (e.hasMoreElements()) + { + if (first) + log.finer("Attributes:"); + first = false; + String key = (String)e.nextElement(); + Object value = ctx.getAttribute(key); + log.finer("- " + key + " = " + value); + } + } // dump + + /** + * Dump Session + * @param session session + */ + public static void dump (HttpSession session) + { + log.config("Session " + session.getId()); + log.config("- Created=" + new Timestamp(session.getCreationTime())); + if (!CLogMgt.isLevelFiner()) + return; + boolean first = true; + Enumeration e = session.getAttributeNames(); + while (e.hasMoreElements()) + { + if (first) + log.finer("Attributes:"); + first = false; + String key = (String)e.nextElement(); + Object value = session.getAttribute(key); + log.finer("- " + key + " = " + value); + } + } // dump (session) + + /** + * Dump Request + * @param request request + */ + public static void dump (HttpServletRequest request) + { + log.config("Request " + request.getProtocol() + " " + request.getMethod()); + if (!CLogMgt.isLevelFiner()) + return; + log.finer("- Server=" + request.getServerName() + ", Port=" + request.getServerPort()); + log.finer("- ContextPath=" + request.getContextPath() + + ", ServletPath=" + request.getServletPath() + + ", Query=" + request.getQueryString()); + log.finer("- From " + request.getRemoteHost() + "/" + request.getRemoteAddr() + // + ":" + request.getRemotePort() + + " - User=" + request.getRemoteUser()); + log.finer("- URI=" + request.getRequestURI() + ", URL=" + request.getRequestURL()); + log.finer("- AuthType=" + request.getAuthType()); + log.finer("- Secure=" + request.isSecure()); + log.finer("- PathInfo=" + request.getPathInfo() + " - " + request.getPathTranslated()); + log.finer("- UserPrincipal=" + request.getUserPrincipal()); + // + boolean first = true; + Enumeration e = request.getHeaderNames(); + /** Header Names */ + while (e.hasMoreElements()) + { + if (first) + log.finer("- Header:"); + first = false; + String key = (String)e.nextElement(); + Object value = request.getHeader(key); + log.finer(" - " + key + " = " + value); + } + /** **/ + first = true; + /** Parameter */ + try + { + String enc = request.getCharacterEncoding(); + if (enc == null) + request.setCharacterEncoding(WebEnv.ENCODING); + } + catch (Exception ee) + { + log.log(Level.SEVERE, "Set CharacterEncoding=" + WebEnv.ENCODING, ee); + } + e = request.getParameterNames(); + while (e.hasMoreElements()) + { + if (first) + log.finer("- Parameter:"); + first = false; + String key = (String)e.nextElement(); + String value = WebUtil.getParameter (request, key); + log.finer(" - " + key + " = " + value); + } + first = true; + /** Attributes */ + e = request.getAttributeNames(); + while (e.hasMoreElements()) + { + if (first) + log.finer("- Attributes:"); + first = false; + String key = (String)e.nextElement(); + Object value = request.getAttribute(key); + log.finer(" - " + key + " = " + value); + } + /** Cookies */ + Cookie[] ccc = request.getCookies(); + if (ccc != null) + { + for (int i = 0; i < ccc.length; i++) + { + if (i == 0) + log.finer("- Cookies:"); + log.finer (" - " + ccc[i].getName () + + ", Domain=" + ccc[i].getDomain () + + ", Path=" + ccc[i].getPath () + + ", MaxAge=" + ccc[i].getMaxAge ()); + } + } + log.finer("- Encoding=" + request.getCharacterEncoding()); + log.finer("- Locale=" + request.getLocale()); + first = true; + e = request.getLocales(); + while (e.hasMoreElements()) + { + if (first) + log.finer("- Locales:"); + first = false; + log.finer(" - " + e.nextElement()); + } + log.finer("- Class=" + request.getClass().getName()); + } // dump (Request) + + + /************************************************************************** + * Add Footer (with diagnostics) + * @param request request + * @param response response + * @param servlet servlet + * @param body - Body to add footer + */ + public static void addFooter(HttpServletRequest request, HttpServletResponse response, + HttpServlet servlet, body body) + { + body.addElement(new hr()); + body.addElement(new comment(" --- Footer Start --- ")); + // Command Line + p footer = new p(); + footer.addElement(org.compiere.Adempiere.DATE_VERSION + ": "); + footer.addElement(new a("javascript:diag_window();", "Window Info")); + footer.addElement(" - "); + footer.addElement(new a("javascript:diag_navigator();", "Browser Info")); + footer.addElement(" - "); + footer.addElement(new a("javascript:diag_request();", "Request Info")); + footer.addElement(" - "); + footer.addElement(new a("javascript:diag_document();", "Document Info")); + footer.addElement(" - "); + footer.addElement(new a("javascript:diag_form();", "Form Info")); + footer.addElement(" - "); + footer.addElement(new a("javascript:toggle('DEBUG');", "Servlet Info")); + footer.addElement(" - "); + footer.addElement(new a("javascript:diag_source();", "Show Source")); + footer.addElement("\n"); + body.addElement(footer); + + // Add ServletInfo + body.addElement(new br()); + body.addElement(getServletInfo(request, response, servlet)); + body.addElement(new script("hide('DEBUG');")); + body.addElement(new comment(" --- Footer End --- ")); + } // getFooter + + /** + * Get Information and put it in a HTML table + * @param request request + * @param response response + * @param servlet servlet + * @return Table + */ + private static table getServletInfo (HttpServletRequest request, + HttpServletResponse response, HttpServlet servlet) + { + table table = new table(); + table.setID("DEBUG"); + Enumeration e; + + tr space = new tr().addElement(new td().addElement(".")); + // Request Info + table.addElement(space); + table.addElement(new tr().addElement(new td().addElement(new h3("Request Info")) )); + table.addElement(new tr().addElement(new td().addElement("Method")) + .addElement(new td().addElement(request.getMethod() ))); + table.addElement(new tr().addElement(new td().addElement("Protocol")) + .addElement(new td().addElement(request.getProtocol() ))); + table.addElement(new tr().addElement(new td().addElement("URI")) + .addElement(new td().addElement(request.getRequestURI() ))); + table.addElement(new tr().addElement(new td().addElement("Context Path")) + .addElement(new td().addElement(request.getContextPath() ))); + table.addElement(new tr().addElement(new td().addElement("Servlet Path")) + .addElement(new td().addElement(request.getServletPath() ))); + table.addElement(new tr().addElement(new td().addElement("Path Info")) + .addElement(new td().addElement(request.getPathInfo() ))); + table.addElement(new tr().addElement(new td().addElement("Path Translated")) + .addElement(new td().addElement(request.getPathTranslated() ))); + table.addElement(new tr().addElement(new td().addElement("Query String")) + .addElement(new td().addElement(request.getQueryString() ))); + table.addElement(new tr().addElement(new td().addElement("Content Length")) + .addElement(new td().addElement("" + request.getContentLength() ))); + table.addElement(new tr().addElement(new td().addElement("Content Type")) + .addElement(new td().addElement(request.getContentType() ))); + table.addElement(new tr().addElement(new td().addElement("Character Encoding")) + .addElement(new td().addElement(request.getCharacterEncoding() ))); + table.addElement(new tr().addElement(new td().addElement("Locale")) + .addElement(new td().addElement(request.getLocale().toString() ))); + table.addElement(new tr().addElement(new td().addElement("Schema")) + .addElement(new td().addElement(request.getScheme() ))); + table.addElement(new tr().addElement(new td().addElement("Server Name")) + .addElement(new td().addElement(request.getServerName() ))); + table.addElement(new tr().addElement(new td().addElement("Server Port")) + .addElement(new td().addElement("" + request.getServerPort() ))); + table.addElement(new tr().addElement(new td().addElement("Remote User")) + .addElement(new td().addElement(request.getRemoteUser() ))); + table.addElement(new tr().addElement(new td().addElement("Remote Address")) + .addElement(new td().addElement(request.getRemoteAddr() ))); + table.addElement(new tr().addElement(new td().addElement("Remote Host")) + .addElement(new td().addElement(request.getRemoteHost() ))); + table.addElement(new tr().addElement(new td().addElement("Authorization Type")) + .addElement(new td().addElement(request.getAuthType() ))); + table.addElement(new tr().addElement(new td().addElement("User Principal")) + .addElement(new td().addElement(request.getUserPrincipal()==null ? "" : request.getUserPrincipal().toString()))); + table.addElement(new tr().addElement(new td().addElement("IsSecure")) + .addElement(new td().addElement(request.isSecure() ? "true" : "false" ))); + + // Request Attributes + table.addElement(space); + table.addElement(new tr().addElement(new td().addElement(new h3("Request Attributes")) )); + e = request.getAttributeNames(); + while (e.hasMoreElements()) + { + String name = e.nextElement().toString(); + String attrib = request.getAttribute(name).toString(); + table.addElement(new tr().addElement(new td().addElement(name)) + .addElement(new td().addElement(attrib))); + } + + // Request Parameter + table.addElement(space); + table.addElement(new tr().addElement(new td().addElement(new h3("Req Parameters")) )); + try + { + String enc = request.getCharacterEncoding(); + if (enc == null) + request.setCharacterEncoding(WebEnv.ENCODING); + } + catch (Exception ee) + { + log.log(Level.SEVERE, "Set CharacterEncoding=" + WebEnv.ENCODING, ee); + } + e = request.getParameterNames(); + while (e.hasMoreElements()) + { + String name = (String)e.nextElement(); + String para = WebUtil.getParameter (request, name); + table.addElement(new tr().addElement(new td().addElement(name)) + .addElement(new td().addElement(para))); + } + + // Request Header + table.addElement(space); + table.addElement(new tr().addElement(new td().addElement(new h3("Req Header")) )); + e = request.getHeaderNames(); + while (e.hasMoreElements()) + { + String name = (String)e.nextElement(); + if (!name.equals("Cockie")) + { + String hdr = request.getHeader(name); + table.addElement(new tr().addElement(new td().addElement(name)) + .addElement(new td().addElement(hdr))); + } + } + + // Request Cookies + table.addElement(space); + table.addElement(new tr().addElement(new td().addElement(new h3("Req Cookies")) )); + Cookie[] cc = request.getCookies(); + if (cc != null) + { + for (int i = 0; i < cc.length; i++) + { + // Name and Comment + table.addElement(new tr().addElement(new td().addElement(cc[i].getName() )) + .addElement(new td().addElement(cc[i].getValue()) )); + table.addElement(new tr().addElement(new td().addElement(cc[i].getName()+": Comment" )) + .addElement(new td().addElement(cc[i].getComment()) )); + table.addElement(new tr().addElement(new td().addElement(cc[i].getName()+": Domain" )) + .addElement(new td().addElement(cc[i].getDomain()) )); + table.addElement(new tr().addElement(new td().addElement(cc[i].getName()+": Max Age" )) + .addElement(new td().addElement(""+ cc[i].getMaxAge()) )); + table.addElement(new tr().addElement(new td().addElement(cc[i].getName()+": Path" )) + .addElement(new td().addElement(cc[i].getPath()) )); + table.addElement(new tr().addElement(new td().addElement(cc[i].getName()+": Is Secure" )) + .addElement(new td().addElement(cc[i].getSecure() ? "true" : "false") )); + table.addElement(new tr().addElement(new td().addElement(cc[i].getName()+": Version" )) + .addElement(new td().addElement("" + cc[i].getVersion()) )); + } + } // Cookies + + // Request Session Info + table.addElement(space); + table.addElement(new tr().addElement(new td().addElement(new h3("Req Session")) )); + HttpSession session = request.getSession(true); + table.addElement(new tr().addElement(new td().addElement("Session ID")) + .addElement(new td().addElement(session.getId() ))); + Timestamp ts = new Timestamp(session.getCreationTime()); + table.addElement(new tr().addElement(new td().addElement("Created")) + .addElement(new td().addElement(ts.toString() ))); + ts = new Timestamp(session.getLastAccessedTime()); + table.addElement(new tr().addElement(new td().addElement("Accessed")) + .addElement(new td().addElement(ts.toString() ))); + table.addElement(new tr().addElement(new td().addElement("Request Session ID")) + .addElement(new td().addElement(request.getRequestedSessionId() ))); + table.addElement(new tr().addElement(new td().addElement(".. via Cookie")) + .addElement(new td().addElement("" + request.isRequestedSessionIdFromCookie() ))); + table.addElement(new tr().addElement(new td().addElement(".. via URL")) + .addElement(new td().addElement("" + request.isRequestedSessionIdFromURL() ))); + table.addElement(new tr().addElement(new td().addElement("Valid")) + .addElement(new td().addElement("" + request.isRequestedSessionIdValid() ))); + + // Request Session Attributes + table.addElement(space); + table.addElement(new tr().addElement(new td().addElement(new h3("Session Attributes")) )); + e = session.getAttributeNames(); + while (e.hasMoreElements()) + { + String name = (String)e.nextElement(); + String attrib = session.getAttribute(name).toString(); + table.addElement(new tr().addElement(new td().addElement(name)) + .addElement(new td().addElement(attrib))); + } + + // Response Info + table.addElement(space); + table.addElement(new tr().addElement(new td().addElement(new h3("Response")) )); + table.addElement(new tr().addElement(new td().addElement("Buffer Size")) + .addElement(new td().addElement(String.valueOf(response.getBufferSize()) ))); + table.addElement(new tr().addElement(new td().addElement("Character Encoding")) + .addElement(new td().addElement(response.getCharacterEncoding() ))); + table.addElement(new tr().addElement(new td().addElement("Locale")) + .addElement(new td().addElement(response.getLocale()==null ? "null" : response.getLocale().toString()))); + + // Servlet + table.addElement(space); + table.addElement(new tr().addElement(new td().addElement(new h3("Servlet")) )); + table.addElement(new tr().addElement(new td().addElement("Name")) + .addElement(new td().addElement(servlet.getServletName()))); + table.addElement(new tr().addElement(new td().addElement("Info")) + .addElement(new td().addElement(servlet.getServletInfo()))); + + // Servlet Init + table.addElement(space); + table.addElement(new tr().addElement(new td().addElement(new h3("Servlet Init Parameter")) )); + e = servlet.getInitParameterNames(); + // same as: servlet.getServletConfig().getInitParameterNames(); + while (e.hasMoreElements()) + { + String name = (String)e.nextElement(); + String para = servlet.getInitParameter(name); + table.addElement(new tr().addElement(new td().addElement(name)) + .addElement(new td().addElement(para))); + } + + // Servlet Context + table.addElement(space); + table.addElement(new tr().addElement(new td().addElement(new h3("Servlet Context")) )); + ServletContext servCtx = servlet.getServletContext(); + e = servCtx.getAttributeNames(); + while (e.hasMoreElements()) + { + String name = (String)e.nextElement(); + String attrib = servCtx.getAttribute(name).toString(); + table.addElement(new tr().addElement(new td().addElement(name)) + .addElement(new td().addElement(attrib))); + } + + // Servlet Context + table.addElement(space); + table.addElement(new tr().addElement(new td().addElement(new h3("Servlet Context Init Parameter")) )); + e = servCtx.getInitParameterNames(); + while (e.hasMoreElements()) + { + String name = (String)e.nextElement(); + String attrib = servCtx.getInitParameter(name).toString(); + table.addElement(new tr().addElement(new td().addElement(name)) + .addElement(new td().addElement(attrib))); + } + + /* */ + return table; + } // getServletInfo + +} // WEnv diff --git a/base/src/org/compiere/util/WebInfo.java b/base/src/org/compiere/util/WebInfo.java new file mode 100644 index 0000000000..becfe9f70b --- /dev/null +++ b/base/src/org/compiere/util/WebInfo.java @@ -0,0 +1,1440 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.util; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.wf.*; + + +/** + * Information Storage. + * Container for JSP Information, added in InfoLinkTag + * + * @author Jorg Janke + * @version $Id$ + */ +public class WebInfo +{ + /** + * Get general Info + * @return info + */ + public static WebInfo getGeneral() + { + if (m_general == null) + m_general = new WebInfo (new Properties(), null); + return m_general; + } // getGeneral + + /** General Info */ + private static WebInfo m_general = null; + + /** + * Constructor + * @param ctx context + * @param wu BPartner + */ + public WebInfo (Properties ctx, WebUser wu) + { + m_ctx = ctx; + m_wu = wu; + } // Info + + + /** JSP Name */ + static public final String NAME = "info"; + + /** Logging */ + private static CLogger log = CLogger.getCLogger(WebInfo.class); + /** Context */ + private Properties m_ctx = null; + /** Business Partner */ + private WebUser m_wu = null; + /** Info Message */ + private String m_infoMessage = null; + /** Info ID */ + private int m_id = 0; + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("WebInfo["); + sb.append(getC_BPartner_ID()); + sb.append("]"); + return sb.toString(); + } // toString + + /** + * Get Info Message & reset + * @return info message + */ + public String getMessage() + { + String retValue = m_infoMessage; + m_infoMessage = null; + return retValue; + } // getMessage + + /** + * Get Info Message - do not reset + * @return info message + */ + public String getInfo() + { + return m_infoMessage; + } // getInfo + + /** + * Set Info Message + * @param msg info message + */ + public void setMessage (String msg) + { + m_infoMessage = msg; + } // setMessage + + /** + * Get Info Message + * @return info id + */ + public int getId() + { + return m_id; + } // getId + + /** + * Set Info Message + * @param id info id + */ + public void setId (String id) + { + try + { + setId (Integer.parseInt (id)); + } + catch (NumberFormatException ex) + { + log.log(Level.SEVERE, "ID=" + id + " - " + ex.toString()); + m_id = 0; + } + } // setId + + /** + * Set Info Message + * @param id info id + */ + public void setId (int id) + { + log.info("ID=" + id); + m_id = id; + } // setId + + /** + * Get Client + * @return AD_Client_ID + */ + public int getAD_Client_ID() + { + if (m_wu == null) + return -1; + return m_wu.getAD_Client_ID(); + } // getC_BPartner_ID + + /** + * Get BPartner + * @return C_BPartner_ID + */ + public int getC_BPartner_ID() + { + if (m_wu == null) + return -1; + return m_wu.getC_BPartner_ID(); + } // getC_BPartner_ID + + /** + * Get BPartner Contact/User + * @return AD_User_ID + */ + public int getAD_User_ID() + { + if (m_wu == null) + return -1; + return m_wu.getAD_User_ID(); + } // getAD_User_ID + + /** + * Get BPartner Contact/User + * @return AD_User_ID + */ + public int getUser_ID() + { + return getAD_User_ID(); + } // getAD_User_ID + + /** + * Get WebUser + * @return WebUser + */ + public WebUser getWebUser() + { + return m_wu; + } + + /************************************************************************** + * Get Orders + * @return invoices of BP + */ + public ArrayList getOrders() + { + m_infoMessage = null; + ArrayList list = new ArrayList(); + if (m_wu != null && + !m_wu.hasBPAccess(X_AD_UserBPAccess.BPACCESSTYPE_BusinessDocuments, + new Object[] {MDocType.DOCBASETYPE_PurchaseOrder, MDocType.DOCBASETYPE_SalesOrder})) + { + log.info("No Access"); + return list; + } + + String sql = "SELECT * FROM C_Order WHERE Bill_BPartner_ID=?" + + " AND DocStatus NOT IN ('DR','IN') " + + "ORDER BY DocumentNo DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MOrder (m_ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("#" + list.size()); + return list; + } // getOrders + + /** + * Get Order. + * Needs to have ID set first + * @return invoice of BP with ID + */ + public MOrder getOrder() + { + m_infoMessage = null; + MOrder retValue = null; + if (m_wu != null && + !m_wu.hasBPAccess(X_AD_UserBPAccess.BPACCESSTYPE_BusinessDocuments, + new Object[] {MDocType.DOCBASETYPE_PurchaseOrder, MDocType.DOCBASETYPE_SalesOrder})) + { + log.info("No Access"); + return null; + } + String sql = "SELECT * FROM C_Order WHERE Bill_BPartner_ID=? AND C_Order_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_BPartner_ID()); + pstmt.setInt(2, m_id); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + retValue = new MOrder (m_ctx, rs, null); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "C_Order_ID=" + m_id, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("C_Order_ID=" + m_id + " - " + retValue); + return retValue; + } // getOrder + + + /** + * Get Shipments + * @return shipments of BP + */ + public ArrayList getShipments() + { + m_infoMessage = null; + ArrayList list = new ArrayList(); + if (m_wu != null && + !m_wu.hasBPAccess(X_AD_UserBPAccess.BPACCESSTYPE_BusinessDocuments, + new Object[] {MDocType.DOCBASETYPE_MaterialReceipt, MDocType.DOCBASETYPE_MaterialDelivery})) + { + log.info("No Access"); + return list; + } + + String sql = "SELECT * FROM M_InOut WHERE C_BPartner_ID=?" + + " AND DocStatus NOT IN ('DR','IN') " + + " ORDER BY DocumentNo DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MInOut (m_ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("#" + list.size()); + return list; + } // getShipments + + /** + * Get Own Requests + * @return Array of Own Requests + */ + public ArrayList getRequestsOwn () + { + return getRequests(true); + } // getRequestsOwn + + /** + * Get Own Requests + * @return Array of Assigned Requests + */ + public ArrayList getRequestsAssigned () + { + return getRequests(false); + } // getRequestsAssigned + + /** + * Get Requests + * @param own if true its own requests otherwise or + * @return Array of Requests + */ + public ArrayList getRequests (boolean own) + { + m_infoMessage = null; + ArrayList list = new ArrayList(); + String sql = null; + if (own) // All Requests + sql = "SELECT * FROM R_Request r " + + "WHERE r.C_BPartner_ID=?" // #1 + + " AND (r.AD_User_ID=?" // #2 + + " OR EXISTS (SELECT * FROM AD_User u " + + "WHERE u.AD_User_ID=? AND r.C_BPartner_ID=u.C_BPartner_ID AND IsFullBPAccess='Y')" // #3 + + " OR EXISTS (SELECT * FROM AD_User u INNER JOIN AD_UserBPAccess a ON (u.AD_User_ID=a.AD_User_ID) " + + "WHERE u.AD_User_ID=? AND r.C_BPartner_ID=u.C_BPartner_ID" // #4 + + " AND a.BPAccessType='R' AND (a.R_RequestType_ID IS NULL OR a.R_RequestType_ID=r.R_RequestType_ID)) ) " + + "ORDER BY r.DocumentNo DESC"; + else // Open Requests of Sales Rep + sql = "SELECT * FROM R_Request " + + "WHERE SalesRep_ID IN (SELECT AD_User_ID FROM AD_User WHERE C_BPartner_ID=?)" + + " AND R_Status_ID IN (SELECT R_Status_ID FROM R_Status WHERE IsClosed='N')" + + "ORDER BY DocumentNo DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_BPartner_ID()); + if (own) + { + pstmt.setInt(2, getAD_User_ID()); + pstmt.setInt(3, getAD_User_ID()); + pstmt.setInt(4, getAD_User_ID()); + } + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add (new MRequest (m_ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("Own=" + own +" #" + list.size()); + return list; + } // getRequests + + /** + * Get Request. + * Needs to have ID set first; Check that it is owned / created by requestor + * @return invoice of BP with ID + */ + public MRequest getRequest() + { + m_infoMessage = null; + MRequest retValue = null; + String sql = "SELECT * FROM R_Request " + + "WHERE R_Request_ID=?" + + " AND (C_BPartner_ID=?" + + " OR SalesRep_ID IN (SELECT AD_User_ID FROM AD_User WHERE C_BPartner_ID=?))"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, m_id); + pstmt.setInt(2, getC_BPartner_ID()); + pstmt.setInt(3, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + retValue = new MRequest (m_ctx, rs, null); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "R_Request_ID=" + m_id, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("R_Request_ID=" + m_id + " - " + retValue); + return retValue; + } // getRequest + + + /** + * Get Request Types + * @return Array of Request Types + */ + public ArrayList getRequestTypes () + { + m_infoMessage = null; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM R_RequestType " + + "WHERE IsSelfService='Y' AND AD_Client_ID=? ORDER BY Name"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getAD_Client_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add (new MRequestType (m_ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("#" + list.size()); + return list; + } // getRequestTypes + + /** + * Get Request Type + * @return Request Type + */ + public MRequestType getRequestType () + { + m_infoMessage = null; + MRequestType retValue = null; + String sql = "SELECT * FROM R_RequestType WHERE IsSelfService='Y' AND R_RequestType_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, m_id); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + retValue = new MRequestType (m_ctx, rs, null); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("R_RequestType_ID=" + m_id + " - " + retValue); + return retValue; + } // getRequestType + + + /** + * Get Invoices + * @return invoices of BP + */ + public ArrayList getInvoices() + { + m_infoMessage = null; + ArrayList list = new ArrayList(); + if (m_wu != null && + !m_wu.hasBPAccess(X_AD_UserBPAccess.BPACCESSTYPE_BusinessDocuments, + new Object[] {MDocType.DOCBASETYPE_APInvoice, MDocType.DOCBASETYPE_APCreditMemo, + MDocType.DOCBASETYPE_ARInvoice, MDocType.DOCBASETYPE_ARCreditMemo})) + { + log.info("No Access"); + return list; + } + String sql = "SELECT * FROM C_Invoice WHERE C_BPartner_ID=?" + + " AND DocStatus NOT IN ('DR','IN') " + + "ORDER BY DocumentNo DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MInvoice (m_ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("#" + list.size()); + return list; + } // getInvoices + + /** + * Get Invoice. + * Needs to have ID set first + * @return invoice with ID of BP + */ + public MInvoice getInvoice() + { + m_infoMessage = null; + MInvoice retValue = null; + if (m_wu != null && + !m_wu.hasBPAccess(X_AD_UserBPAccess.BPACCESSTYPE_BusinessDocuments, + new Object[] {MDocType.DOCBASETYPE_APInvoice, MDocType.DOCBASETYPE_APCreditMemo, + MDocType.DOCBASETYPE_ARInvoice, MDocType.DOCBASETYPE_ARCreditMemo})) + { + log.info("No Access"); + return null; + } + String sql = "SELECT * FROM C_Invoice WHERE C_BPartner_ID=? AND C_Invoice_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_BPartner_ID()); + pstmt.setInt(2, m_id); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + retValue = new MInvoice (m_ctx, rs, null); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "C_Invoice_ID=" + m_id, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("C_Invoice_ID=" + m_id + " - " + retValue); + return retValue; + } // getInvoice + + /** + * Get Payments + * @return payments of BP + */ + public ArrayList getPayments() + { + m_infoMessage = null; + ArrayList list = new ArrayList(); + if (m_wu != null && + !m_wu.hasBPAccess(X_AD_UserBPAccess.BPACCESSTYPE_BusinessDocuments, + new Object[] {MDocType.DOCBASETYPE_APPayment, MDocType.DOCBASETYPE_ARReceipt})) + { + log.info("No Access"); + return list; + } + String sql = "SELECT * FROM C_Payment WHERE C_BPartner_ID=?" + + " AND DocStatus NOT IN ('DR','IN') " + + "ORDER BY DocumentNo DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MPayment (m_ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("#" + list.size()); + return list; + } // getPayments + + /** + * Get Active Assets if not Credit Stop and EMail is verified + * @return payments of BP + */ + public ArrayList getAssets() + { + m_infoMessage = null; + ArrayList list = new ArrayList(); + if (m_wu != null) + { + if (m_wu.isCreditStopHold()) + return list; + if (!m_wu.isEMailVerified()) + return list; + } + if (m_wu != null && + !m_wu.hasBPAccess(X_AD_UserBPAccess.BPACCESSTYPE_AssetsDownload, null)) + { + log.info("No Access"); + return list; + } + String sql = "SELECT * FROM A_Asset WHERE C_BPartner_ID=? AND IsActive='Y' ORDER BY Name"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MAsset (m_ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("#" + list.size()); + return list; + } // getAssets + + /** + * Get Interest Areas + * @return interest areas of BPC + */ + public ArrayList getInterests() + { + m_infoMessage = null; + int AD_Client_ID = Env.getAD_Client_ID(m_ctx); + // + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM R_InterestArea " + + "WHERE IsActive='Y' AND IsSelfService='Y'" + + " AND AD_Client_ID=? " + + "ORDER BY Name"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, AD_Client_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + MInterestArea ia = new MInterestArea (m_ctx, rs, null); + ia.setSubscriptionInfo(getAD_User_ID()); + list.add (ia); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("#" + list.size()); + return list; + } // getInterests + + /** + * Get Advertisements + * @return advertisements of BP + */ + public ArrayList getAdvertisements() + { + m_infoMessage = null; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM W_Advertisement WHERE C_BPartner_ID=? ORDER BY ValidFrom DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MAdvertisement (m_ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("#" + list.size()); + return list; + } // getAdvertisement + + /** + * Get All Advertisements + * @return all advertisements + */ + public ArrayList getAllAds() + { + m_infoMessage = null; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM W_Advertisement WHERE IsActive='Y' ORDER BY Description"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MAdvertisement (m_ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("#" + list.size()); + return list; + } // getAllAds + + /** + * Get Commissioned Invoices + * @return commissioned invoices + */ + public ArrayList getCommissionedInvoices() + { + m_infoMessage = null; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_Invoice " + + "WHERE (C_Invoice.SalesRep_ID=?" // #1 + + " OR EXISTS (SELECT * FROM C_BPartner bp WHERE C_Invoice.C_BPartner_ID=bp.C_BPartner_ID AND bp.SalesRep_ID=?)" + + " OR EXISTS (SELECT * FROM C_InvoiceLine il INNER JOIN M_Product p ON (il.M_Product_ID=p.M_Product_ID) WHERE C_Invoice.C_Invoice_ID=il.C_Invoice_ID AND p.SalesRep_ID=?))" + + " AND DocStatus NOT IN ('DR','IN') " + + "ORDER BY DocumentNo DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getAD_User_ID()); + pstmt.setInt(2, getAD_User_ID()); + pstmt.setInt(3, getAD_User_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MInvoice (m_ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("#" + list.size()); + return list; + } // getCommissionedInvoices + + /** + * Get Commission Runs + * @return commissioned invoices + */ + public ArrayList getCommissionRuns() + { + m_infoMessage = null; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_CommissionRun " + + "WHERE EXISTS (SELECT * FROM C_Commission c " + + "WHERE C_CommissionRun.C_Commission_ID=c.C_Commission_ID AND c.C_BPartner_ID=?) " + + "ORDER BY DocumentNo"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MCommissionRun (m_ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("#" + list.size()); + return list; + } // getCommissionRuns + + + /** + * Get Notices + * @return notices + */ + public ArrayList getNotes() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM AD_Note " + + "WHERE AD_User_ID=?" + + " AND (Processed='N' OR Processed IS NULL) " + + "ORDER BY Created DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getAD_User_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MNote (m_ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("#" + list.size()); + return list; + } // getNotes + + + /** + * Get Notification. + * Needs to have ID set first + * @return notification of User with ID + */ + public MNote getNote() + { + m_infoMessage = null; + MNote retValue = null; + String sql = "SELECT * FROM AD_Note WHERE AD_User_ID=? AND AD_Note_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getAD_User_ID()); + pstmt.setInt(2, m_id); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + retValue = new MNote (m_ctx, rs, null); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "AD_Note_ID=" + m_id, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("AD_Note_ID=" + m_id + " - " + retValue); + return retValue; + } // getNote + + + /** + * Get Workflow Activities + * @return activities + */ + public ArrayList getActivities() + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM AD_WF_Activity " + + "WHERE AD_User_ID=?" + + " AND Processed='N' " + + "ORDER BY Priority DESC, Created"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getAD_User_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MWFActivity (m_ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("#" + list.size()); + return list; + } // getActivities + + + /** + * Get Acitivity. + * Needs to have ID set first + * @return notification of User with ID + */ + public MWFActivity getActivity() + { + m_infoMessage = null; + MWFActivity retValue = null; + String sql = "SELECT * FROM AD_WF_Activity WHERE AD_User_ID=? AND AD_WF_Activity_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getAD_User_ID()); + pstmt.setInt(2, m_id); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + retValue = new MWFActivity (m_ctx, rs, null); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "AD_WF_Activity_ID=" + m_id, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("AD_WF_Activity_ID=" + m_id + " - " + retValue); + return retValue; + } // getActivity + + + /** + * Get Expenses + * @return expense reports + */ + public ArrayList getExpenses() + { + m_infoMessage = null; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM S_TimeExpense " + + "WHERE C_BPartner_ID=? " + + "ORDER BY Created DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MTimeExpense (m_ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("#" + list.size()); + return list; + } // getExpenses + + /** + * Get Expense Report. + * Needs to have ID set first + * @return invoice of BP with ID + */ + public MTimeExpense getExpense() + { + m_infoMessage = null; + MTimeExpense retValue = null; + String sql = "SELECT * FROM S_TimeExpense WHERE C_BPartner_ID=? AND S_TimeExpense_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_BPartner_ID()); + pstmt.setInt(2, m_id); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + retValue = new MTimeExpense (m_ctx, rs, null); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "S_TimeExpense_ID=" + m_id, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + if (retValue == null) + retValue = new MTimeExpense (m_ctx, 0, null); + log.fine("S_TimeExpense_ID=" + m_id + " - " + retValue); + return retValue; + } // getExpense + + + /** + * Get Registrations + * @return registrations + */ + public ArrayList getRegistrations() + { + m_infoMessage = null; + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM A_Registration " + + "WHERE C_BPartner_ID=? " + + "ORDER BY Created DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MRegistration (m_ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("#" + list.size()); + return list; + } // getRegistrations + + /** + * Get Registration. + * Needs to have ID set first + * @return invoice of BP with ID + */ + public MRegistration getRegistration() + { + m_infoMessage = null; + MRegistration retValue = null; + String sql = "SELECT * FROM A_Registration WHERE C_BPartner_ID=? AND A_Registration_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_BPartner_ID()); + pstmt.setInt(2, m_id); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + retValue = new MRegistration (m_ctx, rs, null); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "A_Registration_ID=" + m_id, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + // new registration + if (retValue == null) + retValue = new MRegistration (m_ctx, 0, null); + log.fine("A_Registration_ID=" + m_id + " - " + retValue); + return retValue; + } // getRegistration + + + /** + * Get RfQs. + * Where Response is Accepted, Self Service and either + * all vendors or this vendor is selected. + * @return request for quotations + */ + public ArrayList getRfQs() + { + m_infoMessage = null; + ArrayList list = new ArrayList(); + String sql = "SELECT * " + + "FROM C_RfQ r " + + "WHERE r.IsRfQResponseAccepted='Y'" + + " AND r.IsSelfService='Y' AND r.IsActive='Y' AND r.Processed='N'" + + " AND (r.IsInvitedVendorsOnly='N'" + + " OR EXISTS (SELECT * FROM C_RfQResponse rr " + + " WHERE r.C_RfQ_ID=rr.C_RfQ_ID AND rr.C_BPartner_ID=?)) " + + "ORDER BY r.Name"; + + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MRfQ (m_ctx, rs, null)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + log.fine("#" + list.size()); + return list; + } // getRfQs + + /** + * Get RfQ Response. + * Needs to have ID set first + * @return rfq of BP with ID + */ + public MRfQResponse getRfQResponse() + { + m_infoMessage = null; + MRfQResponse retValue = null; + String sql = "SELECT * FROM C_RfQResponse " + + "WHERE C_RfQ_ID=?" + + " AND C_BPartner_ID=? AND IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, m_id); + pstmt.setInt(2, getC_BPartner_ID()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + retValue = new MRfQResponse (m_ctx, rs, null); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "C_RfQResponse_ID=" + m_id, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + // No Response existing + if (retValue == null) + { + MRfQ rfq = new MRfQ (m_ctx, m_id, null); + // We can create a Response ? + if (rfq.get_ID() != 0 && rfq.isSelfService() + && rfq.isRfQResponseAccepted() && !rfq.isInvitedVendorsOnly() + && getC_BPartner_ID() > 0 && getAD_User_ID() > 0) + { + MBPartner bp = new MBPartner (m_ctx, getC_BPartner_ID(), null); + bp.setPrimaryAD_User_ID(getAD_User_ID()); + retValue = new MRfQResponse (rfq, bp); // may have no lines + retValue.save(); + } + } + // + log.fine("C_RfQResponse_ID=" + m_id + " - " + retValue); + return retValue; + } // getRfQResponse + +} // Info diff --git a/base/src/org/compiere/util/WebLogin.java b/base/src/org/compiere/util/WebLogin.java new file mode 100644 index 0000000000..ab834c34d4 --- /dev/null +++ b/base/src/org/compiere/util/WebLogin.java @@ -0,0 +1,643 @@ +/****************************************************************************** + * 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. + * 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. + * You may reach us at: ComPiere, Inc. - http://www.adempiere.org/license.html + * 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA or info@adempiere.org + *****************************************************************************/ +package org.compiere.util; + +import java.io.IOException; +import java.util.*; +import javax.servlet.http.*; +import javax.servlet.*; +import org.compiere.model.*; +import java.util.logging.*; + + +/** + * WebLogin provides a standard interface to login from Webapps like WStore or M + * + * @author Yves Sandfort + * @version $Id$ + */ +public class WebLogin +{ + /** Logging */ + private CLogger log = CLogger.getCLogger(getClass()); + private final static String COOKIE_NAME = "adempiereWebUser"; + /** Forward Parameter */ + private String P_ForwardTo = "ForwardTo"; + /** SalesRep Parameter */ + private String P_SalesRep_ID = "SalesRep_ID"; + /** EMail Parameter */ + private String P_EMail = "EMail"; + /** Password Parameter */ + private String P_Password = "Password"; + /** Mode/Action Parameter */ + private String P_Action = "Mode"; + /** Login Page */ + private String LOGIN_RelURL = "/login.jsp"; + /** Update Page */ + private String update_page = "/update.jsp"; + /** Message */ + private String message = null; + /** Context */ + private Properties ctx; + /** HttpServletRequest */ + private HttpServletRequest request; + /** HttpServletResponse */ + private HttpServletResponse response; + /** HttpSession */ + private HttpSession session; + /** adressConfirm */ + private boolean addressConfirm; + /** forward */ + private String forward; + /** SalesRep */ + private String salesRep; + /** EMail */ + private String email; + /** Password */ + private String password; + /** WebUser */ + private WebUser wu; + + /** + * WebLogin + * @param t_request + * @param t_response + * @param t_ctx + */ + public WebLogin (HttpServletRequest t_request, HttpServletResponse t_response, Properties t_ctx) + { + request = t_request; + response = t_response; + ctx = t_ctx; + // We will check the Request to see whether Parameters are overwritten + if (request.getParameter ("P_ForwardTo")!=null) + setP_ForwardTo (request.getParameter("P_ForwardTo")); + if (request.getParameter ("SalesRep_ID")!=null) + setP_SalesRep_ID (request.getParameter ("SalesRep_ID")); + if (request.getParameter ("P_EMail")!=null) + setP_EMail (request.getParameter ("P_EMail")); + if (request.getParameter ("P_Password")!=null) + setP_Password (request.getParameter ("P_Password")); + if (request.getParameter ("P_Action")!=null) + setP_Action (request.getParameter ("P_Action")); + if (request.getParameter ("LOGIN_RelURL")!=null) + setLogin_RelURL (request.getParameter ("LOGIN_RelURL")); + if (request.getParameter ("update_page")!=null) + setLogin_RelURL (request.getParameter ("update_page")); + } + + /** + * init will initialize the WebLogin Object for further use + * @return true if init was successfull + */ + public boolean init() + { + session = request.getSession(true); // create new + forward = WebUtil.getParameter (request, P_ForwardTo); // get forward from request + if (forward != null) + session.setAttribute(P_ForwardTo, forward); + salesRep = WebUtil.getParameter (request, P_SalesRep_ID); // get SalesRep from request + if (salesRep != null) + session.setAttribute(P_SalesRep_ID, salesRep); + + // Get Base Info + email = WebUtil.getParameter (request, P_EMail); + if (email == null) + email = ""; + email = email.trim(); + if (email != null) + session.setAttribute (P_EMail, email); + password = WebUtil.getParameter (request, P_Password); + if (password == null) + password = ""; // null loads w/o check + password = password.trim(); + if (session.getAttribute (WebInfo.NAME)!=null) + { + WebInfo wi = (WebInfo)session.getAttribute(WebInfo.NAME); + wu = wi.getWebUser (); + } + return true; + } + + /** + * action run functions against the Login process + * @return true if successfull + * @throws IOException + * @throws ServletException + */ + public boolean action() throws IOException, ServletException + { + // Mode + String mode = WebUtil.getParameter (request, P_Action); + boolean deleteCookie = "deleteCookie".equals(mode); + if (deleteCookie) + { + log.fine("** deleteCookie"); + WebUtil.deleteCookieWebUser (request, response, COOKIE_NAME); + } + boolean logout = "logout".equals(mode); + if (logout || deleteCookie) + { + log.fine("** logout"); + if (session != null) + { + MSession cSession = MSession.get (ctx, false); + if (cSession != null) + cSession.logout(); + // + wu = (WebUser)session.getAttribute(WebUser.NAME); + if (wu != null) + wu.logout(); + + session.removeAttribute(WebUser.NAME); + session.setMaxInactiveInterval(1); + session.invalidate (); + } + // Forward to unsecure / + WebUtil.createForwardPage(response, "Logout", "http://" + request.getServerName() + "/", 2); + } + // Send EMail *** Send Password EMail Request + else if ("SendEMail".equals(mode)) + { + log.info("** send mail"); + wu = WebUser.get (ctx, email); // find it + if (!wu.isEMailValid()) + wu.setPasswordMessage("EMail not found in system"); + else + { + wu.setPassword(); // set password to current + // + String msg = WebUtil.sendEMail (request, wu, + MMailMsg.MAILMSGTYPE_UserPassword, new Object[]{ + request.getServerName(), + wu.getName(), + WebUtil.getFrom(request), + wu.getPassword()}); + if (EMail.SENT_OK.equals(msg)) + wu.setPasswordMessage ("EMail sent"); + else + wu.setPasswordMessage ("Problem sending EMail: " + msg); + } + forward = getLogin_RelURL (); + } // SendEMail + // Login + else if ("Login".equals(mode)) + { + log.info("** login " + email + "/" + password); + // add Cookie + WebUtil.addCookieWebUser(request, response, email, COOKIE_NAME); + + // Always re-query + wu = WebUser.get (ctx, email, password, false); + wu.login(password); + // Password valid + if (wu.isLoggedIn()) + { + if (forward==null || forward.equals(getLogin_RelURL ())) + forward = "/index.jsp"; + // Create Session with User ID + MSession cSession = MSession.get (ctx, request.getRemoteAddr(), + request.getRemoteHost(), session.getId()); + if (cSession != null) + cSession.setWebStoreSession(true); + } + else + { + forward = getLogin_RelURL (); + log.fine("- PasswordMessage=" + wu.getPasswordMessage()); + } + // If no session exists or is not loaded, load or create it + if (session==null) + session = request.getSession (true); + + session.setAttribute (WebInfo.NAME, new WebInfo (ctx, wu)); + } // Login + + // Login New + else if ("LoginNew".equals(mode)) + { + log.info("** loginNew"); + WebUtil.addCookieWebUser(request, response, "", COOKIE_NAME); + wu = WebUser.get (ctx, ""); + forward = getLogin_RelURL (); + } + + // Submit - update/new Contact + else if ("Submit".equals(mode)) + { + log.info("** submit " + email + "/" + password + " - AddrConf=" + addressConfirm); + // we have a record for address update + if (wu != null && wu.isLoggedIn() && addressConfirm) // address update + ; + else // Submit - always re-load user record + wu = WebUser.get (ctx, email, null, false); // load w/o password check direct + // + if (wu.getAD_User_ID() != 0) // existing BPC + { + String passwordNew = WebUtil.getParameter (request, "PasswordNew"); + if (passwordNew == null) + passwordNew = ""; + boolean passwordChange = passwordNew.length() > 0 && !passwordNew.equals(password); + if (addressConfirm || wu.login (password)) + { + // Create / set session + if (wu.isLoggedIn()) + { + MSession cSession = MSession.get (ctx, request.getRemoteAddr(), + request.getRemoteHost(), session.getId()); + if (cSession != null) + cSession.setWebStoreSession(true); + } + // + if (passwordChange) + log.fine("- update Pwd " + email + ", Old=" + password + ", DB=" + wu.getPassword() + ", New=" + passwordNew); + if (WebUtil.updateFields(request, wu, passwordChange)) + { + if (passwordChange) + session.setAttribute(WebSessionCtx.HDR_MESSAGE, "Password changed"); + } + else + { + forward = getLogin_RelURL (); + log.warning(" - update not done"); + } + } + else + { + forward = getLogin_RelURL (); + session.setAttribute(WebSessionCtx.HDR_MESSAGE, "Email/Password not correct"); + log.warning(" - update not confirmed"); + } + } + else // new + { + log.fine("** new " + email + "/" + password); + wu.setEmail (email); + wu.setPassword (password); + if (WebUtil.updateFields (request, wu, true)) + { + if (wu.login(password)) + { + session.setAttribute (WebInfo.NAME, new WebInfo (ctx, wu)); + // Create / set session + MSession cSession = MSession.get (ctx, request.getRemoteAddr(), + request.getRemoteHost(), session.getId()); + if (cSession != null) + cSession.setWebStoreSession(true); + } + else + forward = getLogin_RelURL (); + } + else + { + log.fine("- failed - " + wu.getSaveErrorMessage() + " - " + wu.getPasswordMessage()); + forward = getLogin_RelURL (); + } + } // new + if (wu!=null) + session.setAttribute (WebInfo.NAME, new WebInfo (ctx, wu)); + } // Submit + + else if("email".equals(mode)) + { + String email = WebUtil.getParameter (request, "EMail"); + if (email == null) + email = ""; + email = email.trim(); + + String emailNew = WebUtil.getParameter (request, "EMailNew"); + if (emailNew == null) + emailNew = ""; + + email = email.trim(); + if((emailNew.length() == 0)||(emailNew.equals(email))) + { + setMessage("New EMail invalid."); + return false; + } + + if(!WebUtil.isEmailValid(emailNew)) + { + setMessage("New EMail invalid."); + return false; + } + + wu.setEmail(emailNew); + wu.save(); + session.setAttribute(WebSessionCtx.HDR_MESSAGE, "EMail Address Changed"); + session.setAttribute(WebInfo.NAME, new WebInfo(ctx, wu)); + } + + else if("password".equals(mode)) + { + if (wu == null) + { + log.warning("No web user"); + return false; + } + + String password = WebUtil.getParameter (request, "Password"); + if (password == null) + password = ""; // null loads w/o check + password = password.trim(); + + if(!wu.login(password)) + { + setMessage("Email/Password not correct"); + return false; + } + + MSession cSession = MSession.get (ctx, request.getRemoteAddr(), request.getRemoteHost(), session.getId()); + if (cSession != null) + cSession.setWebStoreSession(true); + + String passwordNew = WebUtil.getParameter (request, "PasswordNew"); + if (passwordNew == null) + passwordNew = ""; + + password = password.trim(); + if( (passwordNew.length() == 0) || (passwordNew.equals(password))) + { + setMessage("New Password invalid."); + return false; + } + + wu.setPasswordMessage(null); + wu.setPassword(passwordNew); + if(wu.getPasswordMessage() != null) + { + setMessage("New Password invalid."); + return false; + } + wu.save(); + session.setAttribute(WebSessionCtx.HDR_MESSAGE, "Password Changed"); + session.setAttribute(WebInfo.NAME, new WebInfo(ctx, wu)); + } + + else if("address".equals(mode)) + { + wu.setC_Country_ID(WebUtil.getParamOrNull(request, "C_Country_ID")); + wu.setC_Region_ID(WebUtil.getParamOrNull(request, "C_Region_ID")); + wu.setRegionName(WebUtil.getParamOrNull(request, "RegionName")); + wu.setName(WebUtil.getParamOrNull(request, "Name")); + wu.setCompany(WebUtil.getParamOrNull(request, "Company")); + wu.setTitle(WebUtil.getParamOrNull(request, "Title")); + wu.setAddress(WebUtil.getParamOrNull(request, "Address")); + wu.setAddress2(WebUtil.getParamOrNull(request, "Address2")); + wu.setCity(WebUtil.getParamOrNull(request, "City")); + wu.setPostal(WebUtil.getParamOrNull(request, "Postal")); + wu.setPhone(WebUtil.getParamOrNull(request, "Phone")); + wu.setFax(WebUtil.getParamOrNull(request, "Fax")); + wu.save(); + session.setAttribute(WebSessionCtx.HDR_MESSAGE, "Contact Information Changed"); + session.setAttribute(WebInfo.NAME, new WebInfo(ctx, wu)); + } + + else if ("EMailVerify".equals(mode)) + { + if (wu == null) + { + log.warning("No web user"); + return false; + } + + log.info(forward + " - " + wu.toString()); + + String cmd = WebUtil.getParameter(request, "ReSend"); + if (cmd != null && cmd.length() > 1) + WebUtil.resendCode(request, wu); + else + wu.setEMailVerifyCode(WebUtil.getParameter(request, "VerifyCode"), request.getRemoteAddr()); + + } + + else if ("bankaccountach".equals(mode)) + { + if (wu == null) + { + log.warning("No web user"); + return false; + } + + log.info(forward + " - " + wu.toString()); + + MBPBankAccount thisBPBankAccount = wu.getBankAccount (true); + // As this sets bankaccountach + thisBPBankAccount.setIsACH (true); + thisBPBankAccount.setA_City (WebUtil.getParamOrNull (request, "A_City")); + thisBPBankAccount.setA_Name (WebUtil.getParamOrNull (request, "A_Name")); + thisBPBankAccount.setAccountNo (WebUtil.getParamOrNull (request, "AccountNo")); + thisBPBankAccount.setRoutingNo (WebUtil.getParamOrNull (request, "RoutingNo")); + thisBPBankAccount.save (); + } + else + log.log(Level.WARNING, "Unknown request='" + mode + "'"); + + return true; + } + + /** + * setMessage to set a Message + * @param newVal + */ + public void setMessage(String newVal) + { + if (newVal!=null) + message = newVal; + } + + /** + * getMessage back + * @return Message + */ + public String getMessage() + { + return message; + } + + /** + * setP_ForwardTo to overwrite default "ForwardTo" Parameter + * @param newVal new value to look for + */ + public void setP_ForwardTo(String newVal) + { + if (newVal!=null) + P_ForwardTo = newVal; + } + + /** + * getP_ForwardTo + * @return ForwardTo request parameter + */ + public String getP_ForwardTo() { + return P_ForwardTo; + } + + /** + * setP_EMail to overwrite default "EMail" Parameter + * @param newVal new value to look for + */ + public void setP_EMail(String newVal) + { + if (newVal!=null) + P_EMail = newVal; + } + + /** + * getP_EMail + * @return EMail request parameter + */ + public String getP_EMail() { + return P_EMail; + } + + /** + * setP_Password to overwrite default "Password" Parameter + * @param newVal new value to look for + */ + public void setP_Password(String newVal) + { + if (newVal!=null) + P_Password = newVal; + } + + /** + * getP_Password + * @return Password request parameter + */ + public String getP_Password() { + return P_Password; + } + + /** + * setP_SalesRep_ID to overwrite default "SalesRep_ID" Parameter + * @param newVal new value to look for + */ + public void setP_SalesRep_ID(String newVal) + { + if (newVal!=null) + P_SalesRep_ID = newVal; + } + + /** + * getP_SalesRep_ID + * @return SalesRep_ID request parameter + */ + public String getP_SalesRep_ID() { + return P_SalesRep_ID; + } + + /** + * setP_Action to overwrite default "Action/Mode" Parameter + * @param newVal new value to look for + */ + public void setP_Action(String newVal) + { + if (newVal!=null) + P_Action = newVal; + } + + /** + * getP_SalesRep_ID + * @return SalesRep_ID request parameter + */ + public String getP_Action() { + return P_Action; + } + + /** + * setLogin_RelURL to overwrite default Login Relative URL + * @param newVal new relative URL inside Domain to goto + */ + public void setLogin_RelURL(String newVal) + { + if (newVal!=null) + LOGIN_RelURL = newVal; + } + + /** + * getLogin_RelURL + * @return Login_RelURL request parameter + */ + public String getLogin_RelURL() { + return LOGIN_RelURL; + } + + /** + * setLogin_RelURL to overwrite default Login Relative URL + * @param newVal new relative URL inside Domain to goto + */ + public void setUpdate_page(String newVal) + { + if (newVal!=null) + update_page = newVal; + } + + /** + * getLogin_RelURL + * @return Login_RelURL request parameter + */ + public String getUpdate_page() { + return update_page; + } + + /** + * setForward updates Forward URL + * @param newVal + */ + public void setForward(String newVal) + { + if (newVal!=null) + forward = newVal; + } + + /** + * getForward + * @return URL to forward request on to + */ + public String getForward() { + return forward; + } + + /** + * getSalesRep_ID + * @return SalesRep_ID of the SalesRep_ID in the Request + */ + public String getSalesRep_ID() { + return salesRep; + } + + /** + * setAddressConfirm + * @param newVal new addressConfirm + */ + public void setAddressConfirm(boolean newVal) + { + addressConfirm = newVal; + } + + /** + * getAdressConfirm + * @return boolean addressConfirm + */ + public boolean getAddressConfirm() { + return addressConfirm; + } + + public WebUser getWebUser() { + return wu; + } +} \ No newline at end of file diff --git a/base/src/org/compiere/util/WebSessionCtx.java b/base/src/org/compiere/util/WebSessionCtx.java new file mode 100644 index 0000000000..2231a4aa13 --- /dev/null +++ b/base/src/org/compiere/util/WebSessionCtx.java @@ -0,0 +1,425 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.util; + +import java.io.*; +import java.text.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import org.compiere.model.*; + + +/** + * Web Session Context Value Object + * + * @author Jorg Janke + * @version $Id: WebSessionCtx.java,v 1.6 2006/09/23 11:04:19 comdivision Exp $ + */ +public class WebSessionCtx implements Serializable +{ + /** SV */ + private static final long serialVersionUID = -5069858671373130221L; + + /** + * Get/create Web Session Context + * @param request request + * @return ctx or null + */ + public static WebSessionCtx get (HttpServletRequest request, int W_Store_ID) + { + HttpSession session = request.getSession(false); + if (session == null) + session = request.getSession(true); + if (session == null) + return null; + WebSessionCtx wsc = (WebSessionCtx)session.getAttribute(NAME); + // Create New + if (wsc == null) + { + wsc = new WebSessionCtx(request, W_Store_ID); + session.setAttribute(NAME, wsc); + } + return wsc; + } // get + + /** + * Get/create Web Session Context + * @param request request + * @return ctx or null + */ + public static WebSessionCtx get (HttpServletRequest request) + { + HttpSession session = request.getSession(false); + if (session == null) + session = request.getSession(true); + if (session == null) + return null; + WebSessionCtx wsc = (WebSessionCtx)session.getAttribute(NAME); + // Create New + if (wsc == null) + { + wsc = new WebSessionCtx (request); + session.setAttribute(NAME, wsc); + } + return wsc; + } // get + + /** Context */ + public final static String CTX_SERVER_CONTEXT = "context"; + /** Dodument Directory */ + public final static String CTX_DOCUMENT_DIR = "documentDir"; + /** Header (Error) Message */ + public final static String HDR_MESSAGE = "hdrMessage"; + /** Header Info Message */ + public final static String HDR_INFO = "hdrInfo"; + + /** Logger */ + static private CLogger log = CLogger.getCLogger (WebSessionCtx.class); + /** Cache 60 minutes */ + static private CCache s_cacheCtx = new CCache("WebSessionCtx", 30, 60); + + /************************************************************************** + * Web Session Context + * @param request request + */ + private WebSessionCtx (HttpServletRequest request) + { + log.info (request.getContextPath() + " (" + request.getRemoteAddr() + + " - " + request.getLocale() + ") #" + counter); + ctx = new Properties(); + setLanguage(request); + + HttpSession session = request.getSession(false); + + // Add Servlet Init Parameters (webStore/src/web/WEB-INF/web.xml) + ServletContext sc = session.getServletContext(); + Enumeration en = sc.getInitParameterNames(); + while (en.hasMoreElements()) + { + String key = (String)en.nextElement(); + String value = sc.getInitParameter(key); + ctx.setProperty(key, value); + log.config (key + "=" + value); + } + + setWStore (request.getContextPath()); + ctx = getDefaults (); + + // ServerContext - dev2/wstore + ctx.put(CTX_SERVER_CONTEXT, request.getServerName() + request.getContextPath()); + // Make Context directly availabe to jsp's + session.setAttribute("ctx", ctx); + // + log.fine("#" + ctx.size()); + } // WebSessionCtx + + /************************************************************************** + * Web Session Context + * @param request request + */ + private WebSessionCtx (HttpServletRequest request, int W_Store_ID) + { + log.info (request.getContextPath() + " (" + request.getRemoteAddr() + + " - " + request.getLocale() + ") #" + counter); + ctx = new Properties(); + setLanguage(request); + + HttpSession session = request.getSession(false); + + // Add Servlet Init Parameters (webStore/src/web/WEB-INF/web.xml) + ServletContext sc = session.getServletContext(); + Enumeration en = sc.getInitParameterNames(); + while (en.hasMoreElements()) + { + String key = (String)en.nextElement(); + String value = sc.getInitParameter(key); + ctx.setProperty(key, value); + log.config (key + "=" + value); + } + + setWStore (W_Store_ID); + ctx = getDefaults (); + + // ServerContext - dev2/wstore + ctx.put(CTX_SERVER_CONTEXT, request.getServerName() + request.getContextPath()); + // Make Context directly availabe to jsp's + session.setAttribute("ctx", ctx); + // + log.fine("#" + ctx.size()); + } // WebSessionCtx + + /** Sessition Attribute Name */ + public static final String NAME = "WebSessionCtx"; + + /** Static counter */ + public static int s_counter = 0; + /** Instance Counter */ + public int counter = ++s_counter; + + + /** Session Context */ + public Properties ctx = null; + /** Session Language */ + public Language language = null; + + /** Localized Date format */ + public SimpleDateFormat dateFormat = null; + /** Localized Timestamp format */ + public SimpleDateFormat dateTimeFormat = null; + + /** Localized Amount format */ + public DecimalFormat amountFormat = null; + /** Localized Integer format */ + public DecimalFormat integerFormat = null; + /** Localized Number format */ + public DecimalFormat numberFormat = null; + /** Localized Quantity format */ + public DecimalFormat quantityFormat = null; + + /** Login Info */ + public String loginInfo = ""; + /** Web Store */ + public MStore wstore = null; + + /** + * Set Web Store + * @param contextPath web server context path + */ + private void setWStore (String contextPath) + { + // get from context + int W_Store_ID = Env.getContextAsInt(ctx, "W_Store_ID"); + if (W_Store_ID != 0) + { + wstore = MStore.get(ctx, W_Store_ID); + if (wstore.getW_Store_ID() != 0) + { + log.info("From web.xml - " + wstore); + return; + } + } + if ("/adempiere".equals(contextPath)) // HTML UI + return; + // + wstore = MStore.get(ctx, contextPath); + if (wstore == null) + throw new IllegalStateException("No Web Store found - " + contextPath); + } // setWStore + + + /** + * Set Web Store + * @param W_Store_ID Web Store ID + */ + public void setWStore (int W_Store_ID) + { + // get from context + if (W_Store_ID != 0) + { + wstore = MStore.get(ctx, W_Store_ID); + if (wstore.getW_Store_ID() != 0) + { + log.info("From web.xml - " + wstore); + return; + } + } + if (wstore == null) + throw new IllegalStateException("No Web Store found - ID: " + W_Store_ID); + } // setWStore + + /** + * Get Web Store Defaults + * @return context + */ + private Properties getDefaults () + { + // No Web Store + if (wstore == null) + return new Properties(); + // + Integer key = new Integer (wstore.getW_Store_ID()); + Properties newCtx = (Properties)s_cacheCtx.get(key); + + /** Create New Context */ + if (newCtx == null) + { + log.info(wstore.getWebContext()); + newCtx = new Properties(); + // copy explicitly + Enumeration e = ctx.keys(); + while (e.hasMoreElements()) + { + String pKey = (String)e.nextElement(); + newCtx.setProperty(pKey, ctx.getProperty(pKey)); + } + + Env.setContext(newCtx, "#AD_Client_ID", wstore.getAD_Client_ID()); + Env.setContext(newCtx, "#AD_Org_ID", wstore.getAD_Org_ID()); + // + Env.setContext(newCtx, "#SalesRep_ID", wstore.getSalesRep_ID()); + Env.setContext(newCtx, "#M_PriceList_ID", wstore.getM_PriceList_ID()); + Env.setContext(newCtx, "#M_Warehouse_ID", wstore.getM_Warehouse_ID()); + // + String s = wstore.getWebParam1(); + Env.setContext(newCtx, "webParam1", s == null ? "" : s); + s = wstore.getWebParam2(); + Env.setContext(newCtx, "webParam2", s == null ? "" : s); + s = wstore.getWebParam3(); + Env.setContext(newCtx, "webParam3", s == null ? "" : s); + s = wstore.getWebParam4(); + Env.setContext(newCtx, "webParam4", s == null ? "" : s); + s = wstore.getWebParam5(); + Env.setContext(newCtx, "webParam5", s == null ? "" : s); + s = wstore.getWebParam6(); + Env.setContext(newCtx, "webParam6", s == null ? "" : s); + s = wstore.getStylesheet(); + if (s == null) + s = "standard"; + else + { + int index = s.lastIndexOf('.'); + if (index != -1) + s = s.substring(0, index); + } + Env.setContext(newCtx, "Stylesheet", s); + // + s = wstore.getWebInfo(); + if (s != null && s.length() > 0) + Env.setContext(newCtx, HDR_INFO, s); + + // Payment Term + Env.setContext(newCtx, "#M_PriceList_ID", wstore.getM_PriceList_ID()); + + // Default User - SalesRep + if (Env.getContextAsInt(newCtx, "#AD_User_ID") == 0) + Env.setContext(newCtx, "#AD_User_ID", wstore.getSalesRep_ID()); + + // Default Role for access + if (Env.getContextAsInt(newCtx, "#AD_Role_ID") == 0) + { + int AD_Role_ID = 0; // HARDCODED - System + Env.setContext(newCtx, "#AD_Role_ID", AD_Role_ID); + } + + // Client + MClient client = MClient.get (newCtx, wstore.getAD_Client_ID()); + // Name,Description, SMTPHost,RequestEMail,RequestUser, RequestUserPw + Env.setContext(newCtx, "name", client.getName()); + Env.setContext(newCtx, "description", client.getDescription()); + + // AD_Language + if (newCtx.getProperty("#AD_Language") == null && client.getAD_Language() != null) + Env.setContext(newCtx, "#AD_Language", client.getAD_Language()); + // DocumentDir + String docDir = client.getDocumentDir(); + Env.setContext(newCtx, CTX_DOCUMENT_DIR, docDir == null ? "" : docDir); + + // Default Language + if (newCtx.getProperty("#AD_Language") == null) + Env.setContext(newCtx, "#AD_Language", "en_US"); + + // Save Context - Key is AD_Client_ID + s_cacheCtx.put(key, newCtx); + } + // return new Properties (pp); seems not to work with JSP + Enumeration e = newCtx.keys(); + while (e.hasMoreElements()) + { + String pKey = (String)e.nextElement(); + ctx.setProperty(pKey, newCtx.getProperty(pKey)); + } + return ctx; + } // getDefaults + + + /************************************************************************** + * Set Language from request or session in. + * - Properties + * - Cookie + * - Session + * @param request request + */ + private void setLanguage (HttpServletRequest request) + { + // Get Cookie + Properties cProp = WebUtil.getCookieProprties(request); + + // Get/set Parameter: Language + String AD_Language = WebUtil.getParameter (request, Env.LANGUAGE); + if (AD_Language == null) + { + // Check Cookie + AD_Language = cProp.getProperty(Env.LANGUAGE); + if (AD_Language == null) + { + // Check Request Locale + Locale locale = request.getLocale(); + AD_Language = Language.getAD_Language (locale); + } + } + if (AD_Language != null) + { + Language lang = Language.getLanguage(AD_Language); + Env.verifyLanguage (ctx, lang); + Env.setContext(ctx, Env.LANGUAGE, lang.getAD_Language()); + Msg.getMsg(ctx, "0"); + cProp.setProperty(Env.LANGUAGE, lang.getAD_Language()); + setLanguage(lang); + } + else if (language == null) // set base language + setLanguage (Language.getBaseLanguage()); + } // setLanguage + + /** + * Set Language and init formats + * @param lang language + */ + private void setLanguage (Language lang) + { + language = lang; + // + dateFormat = DisplayType.getDateFormat(DisplayType.Date, language); + dateTimeFormat = DisplayType.getDateFormat(DisplayType.DateTime, language); + // + amountFormat = DisplayType.getNumberFormat(DisplayType.Amount, language); + integerFormat = DisplayType.getNumberFormat(DisplayType.Integer, language); + numberFormat = DisplayType.getNumberFormat(DisplayType.Number, language); + quantityFormat = DisplayType.getNumberFormat(DisplayType.Quantity, language); + } // setLanguage + + /** + * Finalize + * @throws java.lang.Throwable + */ + protected void finalize () + throws Throwable + { + super.finalize (); + } // finalize + + /** + * String representation + * @return Session + count + */ + public String toString () + { + return "WSessionCtx#" + counter; + } // toString + +} // WSessionCtx \ No newline at end of file diff --git a/base/src/org/compiere/util/WebUser.java b/base/src/org/compiere/util/WebUser.java new file mode 100644 index 0000000000..ef2304c761 --- /dev/null +++ b/base/src/org/compiere/util/WebUser.java @@ -0,0 +1,1103 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.util; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import javax.servlet.http.*; +import org.compiere.model.*; + +/** + * Web User Info. + * Assumes that Email is a direct match. + * UPDATE AD_User SET EMail=TRIM(EMail) WHERE Email<>TRIM(EMail) + * @author Jorg Janke + * @version $Id$ + */ +public class WebUser +{ + /** + * Get from request + * @param request request + * @return web user if exists + */ + public static WebUser get (HttpServletRequest request) + { + HttpSession session = request.getSession(false); + if (session == null) + return null; + return (WebUser)session.getAttribute(WebUser.NAME); + } // get + + + /** + * Get user unconditional from cache + * @param ctx context + * @param email email + * @return web user + */ + public static WebUser get (Properties ctx, String email) + { + return get (ctx, email, null, true); + } // get + + /** + * Get user + * @param ctx context + * @param email email + * @param password optional password + * @param useCache use cache + * @return web user + */ + public static WebUser get (Properties ctx, String email, String password, boolean useCache) + { + if (!useCache) + s_cache = null; + if (s_cache != null && email != null && email.equals(s_cache.getEmail())) + { + // if password is null, don't check it + if (password == null || password.equals(s_cache.getPassword())) + return s_cache; + s_cache.setPasswordOK(false, null); + return s_cache; + } + s_cache = new WebUser (ctx, email, password); + return s_cache; + } // get + + /** + * Get user unconditional (from cache) + * @param ctx context + * @param AD_User_ID BP Contact + * @return web user + */ + public static WebUser get (Properties ctx, int AD_User_ID) + { + if (s_cache != null && s_cache.getAD_User_ID() == AD_User_ID) + return s_cache; + s_cache = new WebUser (ctx, AD_User_ID, null); + return s_cache; + } // get + + /** Short term Cache for immediate re-query/post (hit rate 20%) */ + private static WebUser s_cache = null; + + /*************************************************************************/ + + /** Attribute Name - also in JSPs */ + public static final String NAME = "webUser"; + /** Logging */ + private CLogger log = CLogger.getCLogger(getClass()); + + /** + * Load User with password + * @param ctx context + * @param email email + * @param password password + */ + private WebUser (Properties ctx, String email, String password) + { + m_ctx = ctx; + m_AD_Client_ID = Env.getAD_Client_ID(ctx); + load (email, password); + } // WebUser + + /** + * Load User with password + * @param ctx context + * @param AD_User_ID BP Contact + * @param trxName transaction + */ + private WebUser (Properties ctx, int AD_User_ID, String trxName) + { + m_ctx = ctx; + m_AD_Client_ID = Env.getAD_Client_ID(ctx); + load (AD_User_ID); + } // WebUser + + private Properties m_ctx; + // + private MBPartner m_bp; + private MUser m_bpc; + private MBPartnerLocation m_bpl; + private MLocation m_loc; + // + private boolean m_passwordOK = false; + private String m_passwordMessage; + private String m_saveErrorMessage; + // + private int m_AD_Client_ID = 0; + private boolean m_loggedIn = false; + + + /** + * Load Contact + * @param email email + * @param password optional password + */ + private void load (String email, String password) + { + log.info(email + " - AD_Client_ID=" + m_AD_Client_ID); + String sql = "SELECT * " + + "FROM AD_User " + + "WHERE AD_Client_ID=?" + + " AND TRIM(EMail)=?"; + if (email == null) + email = ""; + + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, m_AD_Client_ID); + pstmt.setString(2, email.trim()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + m_bpc = new MUser (m_ctx, rs, null); + log.fine("Found BPC=" + m_bpc); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + + // Check Password + m_passwordOK = false; + /** User has no password + if (m_bpc != null && m_bpc.getPassword() == null) + { + if (password != null) + m_bpc.setPassword(password); + m_passwordOK = true; + } **/ + // We have a password + if (m_bpc != null && password != null && password.equals(m_bpc.getPassword())) + m_passwordOK = true; + if (m_passwordOK || m_bpc == null) + m_passwordMessage = null; + else + setPasswordOK (false, password); + + // Load BPartner + if (m_bpc != null) + { + m_bp = new MBPartner (m_ctx, m_bpc.getC_BPartner_ID (), null); + log.fine("Found BP=" + m_bp); + } + else + m_bp = null; + // Load Loacation + if (m_bpc != null) + { + if (m_bpc.getC_BPartner_Location_ID() != 0) + { + m_bpl = new MBPartnerLocation (m_ctx, m_bpc.getC_BPartner_Location_ID (), null); + log.fine("Found BPL=" + m_bpl); + } + else + { + MBPartnerLocation[] bpls = m_bp.getLocations(false); + if (bpls != null && bpls.length > 0) + { + m_bpl = bpls[0]; + log.fine("Found BPL=" + m_bpl); + } + } + if (m_bpl != null) + { + m_loc = MLocation.get (m_ctx, m_bpl.getC_Location_ID(), null); + log.fine("Found LOC=" + m_loc); + } + else + m_loc = null; + } + else + { + m_bpl = null; + m_loc = null; + } + + // Make sure that all entities exist + if (m_bpc == null) + { + m_bpc = new MUser (m_ctx, 0, null); + m_bpc.setEMail(email); + m_bpc.setPassword(password); + } + if (m_bp == null) + { + m_bp = new MBPartner (m_ctx); // template + m_bp.setIsCustomer(true); + } + if (m_bpl == null) + m_bpl = new MBPartnerLocation (m_bp); + if (m_loc == null) + m_loc = new MLocation (m_ctx, 0, null); + // + log.config(m_bp + " - " + m_bpc); + } // load + + /** + * Load Contact + * @param AD_User_ID BP Contact + */ + private void load (int AD_User_ID) + { + log.info("ID=" + AD_User_ID + ", AD_Client_ID=" + m_AD_Client_ID); + String sql = "SELECT * " + + "FROM AD_User " + + "WHERE AD_Client_ID=?" + + " AND AD_User_ID=?"; + + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, m_AD_Client_ID); + pstmt.setInt(2, AD_User_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + m_bpc = new MUser (m_ctx, rs, null); + log.fine("= found BPC=" + m_bpc); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + + // Password not entered + m_passwordOK = false; + m_loggedIn = false; + + // Load BPartner + if (m_bpc != null) + { + m_bp = new MBPartner (m_ctx, m_bpc.getC_BPartner_ID (), null); + log.fine("= Found BP=" + m_bp); + } + else + m_bp = null; + // Load Loacation + if (m_bpc != null) + { + if (m_bpc.getC_BPartner_Location_ID() != 0) + { + m_bpl = new MBPartnerLocation (m_ctx, m_bpc.getC_BPartner_Location_ID (), null); + log.fine("= Found BPL=" + m_bpl); + } + else + { + MBPartnerLocation[] bpls = m_bp.getLocations(false); + if (bpls != null && bpls.length > 0) + { + m_bpl = bpls[0]; + log.fine("= Found BPL=" + m_bpl); + } + } + if (m_bpl != null) + { + m_loc = MLocation.get (m_ctx, m_bpl.getC_Location_ID(), null); + log.fine("= Found LOC=" + m_loc); + } + else + m_loc = null; + } + else + { + m_bpl = null; + m_loc = null; + } + + // Make sure that all entities exist + if (m_bpc == null) + { + m_bpc = new MUser (m_ctx, 0, null); + m_bpc.setEMail("?"); + m_bpc.setPassword("?"); + } + if (m_bp == null) + { + m_bp = new MBPartner (m_ctx); // template + m_bp.setIsCustomer(true); + } + if (m_bpl == null) + m_bpl = new MBPartnerLocation (m_bp); + if (m_loc == null) + m_loc = new MLocation (m_ctx, 0, null); + // + log.info("= " + m_bp + " - " + m_bpc); + } // load + + /** + * Return Valid. + * @return return true if found + */ + public boolean isValid() + { + if (m_bpc == null) + return false; + boolean ok = m_bpc.getAD_User_ID() != 0; + return ok; + } // isValid + + /** + * Return Email Validation. + * @return return true if email is valid + */ + public boolean isEMailValid() + { + if (m_bpc == null || !WebUtil.exists(getEmail())) + { + log.fine(getEmail() + ", bpc=" + m_bpc); + return false; + } + // + boolean ok = m_bpc.getAD_User_ID() != 0 + && m_bpc.isEMailValid(); + if (!ok) + log.fine(getEmail() + + ", ID=" + m_bpc.getAD_User_ID() + + ", Online=" + m_bpc.isOnline() + + ", EMailValid=" + m_bpc.isEMailValid()); + return ok; + } // isEMailValid + + /** + * Return Email Verification (reply). + * @return return true if reply received + */ + public boolean isEMailVerified() + { + return m_bpc != null + && m_bpc.isEMailVerified(); + } // isEMailVerified + + + /** + * Info + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer("WebUser["); + sb.append(getEmail()) + .append(",LoggedIn=").append(m_loggedIn) + .append(",").append(m_bpc) + .append(",PasswordOK=").append(m_passwordOK) + .append(",Valid=").append(isValid()) + .append(" - ").append(m_bp).append("Customer=").append(isCustomer()) + .append("]"); + return sb.toString(); + } // toString + + + /************************************************************************** + * Save BPartner Objects + * @return true if saved + */ + public boolean save() + { + m_saveErrorMessage = null; + log.info("BP.Value=" + m_bp.getValue() + ", Name=" + m_bp.getName()); + try + { + // check if BPartner exists *********************************** + if (m_bp.getC_BPartner_ID() == 0) + { + String sql = "SELECT * FROM C_BPartner WHERE AD_Client_ID=? AND Value=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt (1, m_AD_Client_ID); + pstmt.setString (2, m_bp.getValue()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + m_bp = new MBPartner (m_ctx, m_bpc.getC_BPartner_ID (), null); + log.fine("BP loaded =" + m_bp); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "save-check", e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + } + + // save BPartner *************************************** + if (m_bp.getName () == null || m_bp.getName().length() == 0) + m_bp.setName (m_bpc.getName()); + if (m_bp.getValue() == null || m_bp.getValue().length() == 0) + m_bp.setValue(m_bpc.getEMail()); + log.fine("BP=" + m_bp); + if (!m_bp.save ()) + { + m_saveErrorMessage = "Could not save Business Partner"; + return false; + } + + // save Location *************************************** + log.fine("LOC=" + m_loc); + m_loc.save (); + + // save BP Location *************************************** + if (m_bpl.getC_BPartner_ID () != m_bp.getC_BPartner_ID()) + m_bpl.setC_BPartner_ID (m_bp.getC_BPartner_ID()); + if (m_bpl.getC_Location_ID () != m_loc.getC_Location_ID()) + m_bpl.setC_Location_ID (m_loc.getC_Location_ID()); + log.fine("BPL=" + m_bpl); + if (!m_bpl.save ()) + { + m_saveErrorMessage = "Could not save Location"; + return false; + } + + // save Contact *************************************** + if (m_bpc.getC_BPartner_ID () != m_bp.getC_BPartner_ID()) + m_bpc.setC_BPartner_ID (m_bp.getC_BPartner_ID()); + if (m_bpc.getC_BPartner_Location_ID () != m_bpl.getC_BPartner_Location_ID ()) + m_bpc.setC_BPartner_Location_ID (m_bpl.getC_BPartner_Location_ID ()); + log.fine("BPC=" + m_bpc); + if (!m_bpc.save ()) + { + m_saveErrorMessage = "Could not save Contact"; + return false; + } + } + catch (Exception ex) + { + log.log(Level.SEVERE, "save", ex); + m_saveErrorMessage = ex.toString(); + return false; + } + // + return true; + } // save + + /** + * Set Save Error Message + * @param msg message + */ + public void setSaveErrorMessage(String msg) + { + m_saveErrorMessage = msg; + } + /** + * Get Save Error Message + * @return message + */ + public String getSaveErrorMessage() + { + return m_saveErrorMessage; + } + + /************************************************************************** + * Get EMail address. + * used as jsp parameter + * @return email address of contact + */ + public String getEmail () + { + return m_bpc.getEMail(); + } + + public void setEmail (String email) + { + m_bpc.setEMail(email); + } + + public String getName () + { + return m_bpc.getName(); + } + + public void setName (String name) + { + m_bpc.setName(name); + } + + public void setValue (String value) + { + m_bp.setValue (value); + } + + public String getTitle () + { + return m_bpc.getTitle(); + } + + public void setTitle (String title) + { + m_bpc.setTitle(title); + } + + /** + * Get Password + * @return password + */ + public String getPassword () + { + String pwd = m_bpc.getPassword(); + if (pwd == null || pwd.length() == 0) // if no password use time + pwd = String.valueOf(System.currentTimeMillis()); + return pwd; + } // getPassword + + /** + * Check & Save Password + */ + public void setPassword () + { + String pwd = m_bpc.getPassword(); + if ((pwd == null || pwd.length() == 0) // no password set + && m_bpc.getC_BPartner_ID() != 0 && m_bpc.getAD_User_ID() != 0 ) // existing BPartner + { + pwd = String.valueOf (System.currentTimeMillis ()); + m_bpc.setPassword (pwd); + m_bpc.save(); + } + } // setPassword + + /** + * Set Password + * @param password new password + */ + public void setPassword (String password) + { + if (password == null || password.length() == 0) + m_passwordMessage = "Enter Password"; + m_bpc.setPassword (password); + } // setPassword + + /** + * Set Password OK + * @param ok password valid + * @param password password + */ + private void setPasswordOK (boolean ok, String password) + { + m_passwordOK = ok; + if (ok) + m_passwordMessage = null; + else if (password == null || password.length() == 0) + m_passwordMessage = "Enter Password"; + else + m_passwordMessage = "Invalid Password"; + } // setPasswordOK + + /** + * Is Password OK + * @return true if OK + */ + public boolean isPasswordOK() + { + if (m_bpc == null || !WebUtil.exists(m_bpc.getPassword())) + return false; + return m_passwordOK; + } // isPasswordOK + + /** + * Set Password Message + * @return error message or null + */ + public String getPasswordMessage () + { + return m_passwordMessage; + } // getPasswordMessage + + /** + * Set Password Message + * @param passwordMessage message + */ + public void setPasswordMessage (String passwordMessage) + { + m_passwordMessage = passwordMessage; + } // setPasswordMessage + + /** + * Log in with password + * @param password password + * @return true if the user is logged in + */ + public boolean login (String password) + { + m_loggedIn = isValid () // we have a contact + && WebUtil.exists (password) // we have a password + && password.equals (getPassword ()); + setPasswordOK (m_loggedIn, password); + log.fine("success=" + m_loggedIn); + if (m_loggedIn) + Env.setContext(m_ctx, "#AD_User_ID", getAD_User_ID()); + return m_loggedIn; + } // isLoggedIn + + /** + * Log in with oassword + */ + public void logout () + { + m_loggedIn = false; + } // isLoggedIn + + /** + * Is User Logged in + * @return is the user logged in + */ + public boolean isLoggedIn () + { + return m_loggedIn; + } // isLoggedIn + + public String getPhone () + { + return m_bpc.getPhone(); + } + + public void setPhone (String phone) + { + m_bpc.setPhone(phone); + } + + public String getPhone2 () + { + return m_bpc.getPhone2(); + } + + public void setPhone2 (String phone2) + { + m_bpc.setPhone2(phone2); + } + + public String getFax () + { + return m_bpc.getFax(); + } + + public void setFax (String fax) + { + m_bpc.setFax(fax); + } + + public Timestamp getBirthday () + { + return m_bpc.getBirthday(); + } + + public void setBirthday (Timestamp birthday) + { + m_bpc.setBirthday(birthday); + } + + public String getTaxID () + { + return m_bp.getTaxID(); + } + + public void setTaxID (String taxID) + { + m_bp.setTaxID(taxID); + } + + public int getAD_Client_ID () + { + return m_bpc.getAD_Client_ID(); + } + + public int getAD_User_ID () + { + return m_bpc.getAD_User_ID(); + } + + public int getContactID () + { + return getAD_User_ID(); + } + + /*************************************************************************/ + + /** + * Get Company Name + * @return company name + */ + public String getCompany() + { + return m_bp.getName(); + } + + public void setCompany(String company) + { + if (company==null) { + m_bp.setName (m_bpc.getName ()); + } else { + m_bp.setName(company); + } + } + + public int getC_BPartner_ID () + { + return m_bp.getC_BPartner_ID(); + } + + public int getBpartnerID () + { + return m_bp.getC_BPartner_ID(); + } + + public int getM_PriceList_ID () + { + return m_bp.getM_PriceList_ID(); + } + + + /*************************************************************************/ + + /** + * Get BP Location ID + * @return BP Loaction + */ + public int getC_BPartner_Location_ID () + { + return m_bpl.getC_BPartner_Location_ID(); + } + + /************************************************************************** + * Get Location + * @return location address + */ + public String getAddress () + { + return m_loc.getAddress1(); + } + + public void setAddress (String address) + { + m_loc.setAddress1(address); + } + + public String getAddress2 () + { + return m_loc.getAddress2(); + } + + public void setAddress2 (String address2) + { + m_loc.setAddress2(address2); + } + + public String getCity () + { + return m_loc.getCity(); + } + + public void setCity (String city) + { + m_loc.setCity(city); + } + + public String getPostal () + { + return m_loc.getPostal(); + } + + public void setPostal (String postal) + { + m_loc.setPostal(postal); + } + + /************************************************************************** + * Get (additional) Region name + * @return location region name + */ + public String getRegionName () + { + return m_loc.getRegionName(false); + } + + public void setRegionName (String region) + { + m_loc.setRegionName(region); + } + + public int getC_Region_ID () + { + return m_loc.getC_Region_ID(); + } + + public String getRegionID () + { + return String.valueOf(getC_Region_ID()); + } + + public void setC_Region_ID (int C_Region_ID) + { + m_loc.setC_Region_ID(C_Region_ID); + } + + public void setC_Region_ID (String C_Region_ID) + { + try + { + if (C_Region_ID == null || C_Region_ID.length() == 0) + setC_Region_ID(0); + else + setC_Region_ID(Integer.parseInt(C_Region_ID)); + } + catch (Exception e) + { + setC_Region_ID(0); + log.log(Level.WARNING, C_Region_ID, e); + } + } + + public String getCountryName () + { + return m_loc.getCountryName(); + } + + public void setCountryName (String country) + { + log.warning(country + " Ignored - C_Country_ID=" + m_loc.getC_Country_ID()); + // m_loc.setCountryName(country); + } + + public int getC_Country_ID () + { + return m_loc.getC_Country_ID(); + } + + public String getCountryID () + { + return String.valueOf(getC_Country_ID()); + } + + public void setC_Country_ID (int C_Country_ID) + { + m_loc.setC_Country_ID(C_Country_ID); + } + + public void setC_Country_ID (String C_Country_ID) + { + try + { + if (C_Country_ID == null || C_Country_ID.length() == 0) + setC_Country_ID(0); + else + setC_Country_ID(Integer.parseInt(C_Country_ID)); + } + catch (Exception e) + { + setC_Country_ID(0); + log.log(Level.WARNING, C_Country_ID, e); + } + } + + public void setC_BP_Group_ID (int C_BP_Group_ID) + { + m_bp.setC_BP_Group_ID (C_BP_Group_ID); + } + + public void setC_BP_Group_ID (String C_BP_Group_ID) + { + try + { + if (C_BP_Group_ID == null || C_BP_Group_ID.length() == 0) + setC_BP_Group_ID(0); + else + setC_BP_Group_ID(Integer.parseInt(C_BP_Group_ID)); + } + catch (Exception e) + { + setC_BP_Group_ID(0); + log.log(Level.WARNING, C_BP_Group_ID, e); + } + } + + public boolean isEmployee() + { + return m_bp.isEmployee(); + } + + public boolean isSalesRep() + { + return m_bp.isSalesRep(); + } + + public boolean isCustomer() + { + return m_bp.isCustomer(); + } + + public void setIsCustomer(boolean isCustomer) + { + m_bp.setIsCustomer(isCustomer); + } + + public boolean isVendor() + { + return m_bp.isVendor(); + } + + public int getSalesRep_ID() + { + return m_bp.getSalesRep_ID(); + } + + public boolean hasBPAccess (String BPAccessType, Object[] params) + { + return m_bpc.hasBPAccess (BPAccessType, params); + } + + /** + * Credit Status is Stop or Hold. + * Used in Asset download + * @return true if Stop/Hold + */ + public boolean isCreditStopHold() + { + return m_bp.isCreditStopHold(); + } // isCreditStopHold + + /** + * Credit Status is Critical. + * Used in Web UI + * @return true if Stop/Hold/Watch + */ + public boolean isCreditCritical() + { + String status = m_bp.getSOCreditStatus(); + return MBPartner.SOCREDITSTATUS_CreditStop.equals(status) + || MBPartner.SOCREDITSTATUS_CreditHold.equals(status) + || MBPartner.SOCREDITSTATUS_CreditWatch.equals(status); + } + + /** + * Credit Status Clear Text. + * Used in Web UI + * @return Clear Text Credit Status + */ + public String getSOCreditStatus() + { + return MRefList.getListName(m_ctx, MBPartner.SOCREDITSTATUS_AD_Reference_ID, m_bp.getSOCreditStatus()); + } // getSOCreditStatus + + /************************************************************************** + * Get BP Bank Account (or create it) + * @return Bank Account + */ + public MBPBankAccount getBankAccount() + { + return getBankAccount(false); + } + + /************************************************************************** + * Get BP Bank Account (or create it) + * @param requery Requery data + * @return Bank Account + */ + public MBPBankAccount getBankAccount(boolean requery) + { + MBPBankAccount retValue = null; + // Find Bank Account for exact User + MBPBankAccount[] bas = m_bp.getBankAccounts(requery); + for (int i = 0; i < bas.length; i++) + { + if (bas[i].getAD_User_ID() == getAD_User_ID() && bas[i].isActive()) + retValue = bas[i]; + } + + // create new + if (retValue == null) + { + retValue = new MBPBankAccount (m_ctx, m_bp, m_bpc, m_loc); + retValue.setAD_User_ID(getAD_User_ID()); + retValue.save(); + } + + return retValue; + } // getBankAccount + + /** + * Get EMail Verification Code + * @return verification code + */ + public String getEMailVerifyCode() + { + return m_bpc.getEMailVerifyCode(); + } + + /** + * Check & Set EMail Validation Code. + * @param code code + * @param info info + */ + public void setEMailVerifyCode(String code, String info) + { + if (m_bpc.setEMailVerifyCode(code, info)) + setPasswordMessage(null); + else + setPasswordMessage("Invalid Code"); + m_bpc.save(); + } // setEMailVerifyCode + +} // WebUser diff --git a/base/src/org/compiere/util/WebUtil.java b/base/src/org/compiere/util/WebUtil.java new file mode 100644 index 0000000000..278f7b836b --- /dev/null +++ b/base/src/org/compiere/util/WebUtil.java @@ -0,0 +1,1207 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.util; + +import java.io.*; +import java.math.*; +import java.net.*; +import java.sql.*; +import java.text.*; +import java.util.*; +import java.util.logging.*; +import javax.mail.internet.*; +import javax.servlet.*; +import javax.servlet.http.*; +import org.apache.ecs.*; +import org.apache.ecs.xhtml.*; +import org.compiere.model.*; + +/** + * Servlet Utilities + * + * @author Jorg Janke + * @version $Id: WebUtil.java,v 1.7 2006/09/24 12:11:54 comdivision Exp $ + */ +public final class WebUtil +{ + /** Static Logger */ + private static CLogger log = CLogger.getCLogger (WebUtil.class); + + /** + * Create Timeout Message + * + * @param request request + * @param response response + * @param servlet servlet + * @param message - optional message + * @throws ServletException + * @throws IOException + */ + public static void createTimeoutPage (HttpServletRequest request, HttpServletResponse response, + HttpServlet servlet, String message) throws ServletException, IOException + { + log.info(message); + WebSessionCtx wsc = WebSessionCtx.get(request); + String windowTitle = "Timeout"; + if (wsc != null) + windowTitle = Msg.getMsg(wsc.ctx, "Timeout"); + + WebDoc doc = WebDoc.create (windowTitle); + + // Body + body body = doc.getBody(); + // optional message + if (message != null && message.length() > 0) + body.addElement(new p(message, AlignType.CENTER)); + + // login button + body.addElement(getLoginButton(wsc == null ? null : wsc.ctx)); + + // + body.addElement(new hr()); + body.addElement(new small(servlet.getClass().getName())); + // fini + createResponse (request, response, servlet, null, doc, false); + } // createTimeoutPage + + /** + * Create Error Message + * + * @param request request + * @param response response + * @param servlet servlet + * @param message message + * @throws ServletException + * @throws IOException + */ + public static void createErrorPage (HttpServletRequest request, HttpServletResponse response, + HttpServlet servlet, String message) + throws ServletException, IOException + { + log.info( message); + WebSessionCtx wsc = WebSessionCtx.get(request); + String windowTitle = "Error"; + if (wsc != null) + windowTitle = Msg.getMsg(wsc.ctx, "Error"); + if (message != null) + windowTitle += ": " + message; + + WebDoc doc = WebDoc.create (windowTitle); + + // Body + body b = doc.getBody(); + + b.addElement(new p(servlet.getServletName(), AlignType.CENTER)); + b.addElement(new br()); + + // fini + createResponse (request, response, servlet, null, doc, true); + } // createErrorPage + + /** + * Create Exit Page "Log-off". + *

+ * - End Session + * - Go to start page (e.g. /adempiere/index.html) + * + * @param request request + * @param response response + * @param servlet servlet + * @param ctx context + * @param AD_Message messahe + * @throws ServletException + * @throws IOException + */ + public static void createLoginPage (HttpServletRequest request, HttpServletResponse response, + HttpServlet servlet, Properties ctx, String AD_Message) throws ServletException, IOException + { + request.getSession().invalidate(); + String url = WebEnv.getBaseDirectory("index.html"); + // + WebDoc doc = null; + if (ctx != null && AD_Message != null && !AD_Message.equals("")) + doc = WebDoc.create (Msg.getMsg(ctx, AD_Message)); + else if (AD_Message != null) + doc = WebDoc.create (AD_Message); + else + doc = WebDoc.create (false); + script script = new script("window.top.location.replace('" + url + "');"); + doc.getBody().addElement(script); + // + createResponse (request, response, servlet, null, doc, false); + } // createLoginPage + + /** + * Create Login Button - replace Window + * + * @param ctx context + * @return Button + */ + public static button getLoginButton (Properties ctx) + { + String text = "Login"; + if (ctx != null) + text = Msg.getMsg (ctx, "Login"); + button button = new button(); + button.setType("button").setName("Login").addElement(text); + StringBuffer cmd = new StringBuffer ("window.top.location.replace('"); + cmd.append(WebEnv.getBaseDirectory("index.html")); + cmd.append("');"); + button.setOnClick(cmd.toString()); + return button; + } // getLoginButton + + + /************************************************************************** + * Get Cookie Properties + * + * @param request request + * @return Properties + */ + public static Properties getCookieProprties(HttpServletRequest request) + { + // Get Properties + Cookie[] cookies = request.getCookies(); + if (cookies != null) + { + for (int i = 0; i < cookies.length; i++) + { + if (cookies[i].getName().equals(WebEnv.COOKIE_INFO)) + return propertiesDecode(cookies[i].getValue()); + } + } + return new Properties(); + } // getProperties + + + /** + * Get String Parameter. + * + * @param request request + * @param parameter parameter + * @return string or null + */ + public static String getParameter (HttpServletRequest request, String parameter) + { + if (request == null || parameter == null) + return null; + String enc = request.getCharacterEncoding(); + try + { + if (enc == null) + { + request.setCharacterEncoding(WebEnv.ENCODING); + enc = request.getCharacterEncoding(); + } + } + catch (Exception e) + { + log.log(Level.SEVERE, "Set CharacterEncoding=" + WebEnv.ENCODING, e); + enc = request.getCharacterEncoding(); + } + String data = request.getParameter(parameter); + if (data == null || data.length() == 0) + return data; + + // Convert + if (enc != null && !WebEnv.ENCODING.equals(enc)) + { + try + { + String dataEnc = new String(data.getBytes(enc), WebEnv.ENCODING); + log.log(Level.FINER, "Convert " + data + " (" + enc + ")-> " + + dataEnc + " (" + WebEnv.ENCODING + ")"); + data = dataEnc; + } + catch (Exception e) + { + log.log(Level.SEVERE, "Convert " + data + " (" + enc + ")->" + WebEnv.ENCODING); + } + } + + // Convert � to character (JSTL input) + String inStr = data; + StringBuffer outStr = new StringBuffer(); + int i = inStr.indexOf("&#"); + while (i != -1) + { + outStr.append(inStr.substring(0, i)); // up to &# + inStr = inStr.substring(i+2, inStr.length()); // from &# + + int j = inStr.indexOf(";"); // next ; + if (j < 0) // no second tag + { + inStr = "&#" + inStr; + break; + } + + String token = inStr.substring(0, j); + try + { + int intToken = Integer.parseInt(token); + outStr.append((char)intToken); // replace context + } + catch (Exception e) + { + log.log(Level.SEVERE, "Token=" + token, e); + outStr.append("&#").append(token).append(";"); + } + inStr = inStr.substring(j+1, inStr.length()); // from ; + i = inStr.indexOf("&#"); + } + + outStr.append(inStr); // add remainder + String retValue = outStr.toString(); + /** + StringBuffer debug = new StringBuffer(); + char[] cc = data.toCharArray(); + for (int j = 0; j < cc.length; j++) + { + debug.append(cc[j]); + int iii = (int)cc[j]; + debug.append("[").append(iii).append("]"); + } + log.finest(parameter + "=" + data + " -> " + retValue + " == " + debug); + **/ + log.finest(parameter + "=" + data + " -> " + retValue); + return retValue; + } // getParameter + + /** + * Get integer Parameter - 0 if not defined. + * + * @param request request + * @param parameter parameter + * @return int result or 0 + */ + public static int getParameterAsInt (HttpServletRequest request, String parameter) + { + if (request == null || parameter == null) + return 0; + String data = getParameter(request, parameter); + if (data == null || data.length() == 0) + return 0; + try + { + return Integer.parseInt(data); + } + catch (Exception e) + { + log.warning (parameter + "=" + data + " - " + e); + } + return 0; + } // getParameterAsInt + + /** + * Get numeric Parameter - 0 if not defined + * + * @param request request + * @param parameter parameter + * @return big decimal result or 0 + */ + public static BigDecimal getParameterAsBD (HttpServletRequest request, String parameter) + { + if (request == null || parameter == null) + return Env.ZERO; + String data = getParameter(request, parameter); + if (data == null || data.length() == 0) + return Env.ZERO; + try + { + return new BigDecimal (data); + } + catch (Exception e) + { + } + try + { + DecimalFormat format = DisplayType.getNumberFormat(DisplayType.Number); + Object oo = format.parseObject(data); + if (oo instanceof BigDecimal) + return (BigDecimal)oo; + else if (oo instanceof Number) + return new BigDecimal (((Number)oo).doubleValue()); + return new BigDecimal (oo.toString()); + } + catch (Exception e) + { + log.fine(parameter + "=" + data + " - " + e); + } + return Env.ZERO; + } // getParameterAsBD + + /** + * Get date Parameter - null if not defined. + * Date portion only + * @param request request + * @param parameter parameter + * @return timestamp result or null + */ + public static Timestamp getParameterAsDate (HttpServletRequest request, + String parameter) + { + return getParameterAsDate (request, parameter, null); + } // getParameterAsDate + + /** + * Get date Parameter - null if not defined. + * Date portion only + * @param request request + * @param parameter parameter + * @param language optional language + * @return timestamp result or null + */ + public static Timestamp getParameterAsDate (HttpServletRequest request, + String parameter, Language language) + { + if (request == null || parameter == null) + return null; + String data = getParameter(request, parameter); + if (data == null || data.length() == 0) + return null; + + // Language Date Format + if (language != null) + { + try + { + DateFormat format = DisplayType.getDateFormat(DisplayType.Date, language); + java.util.Date date = format.parse(data); + if (date != null) + return new Timestamp (date.getTime()); + } + catch (Exception e) + { + } + } + + // Default Simple Date Format + try + { + SimpleDateFormat format = DisplayType.getDateFormat(DisplayType.Date); + java.util.Date date = format.parse(data); + if (date != null) + return new Timestamp (date.getTime()); + } + catch (Exception e) + { + } + + // JDBC Format + try + { + return Timestamp.valueOf(data); + } + catch (Exception e) + { + } + + log.warning(parameter + " - cannot parse: " + data); + return null; + } // getParameterAsDate + + /** + * Get boolean Parameter. + * @param request request + * @param parameter parameter + * @return true if found + */ + public static boolean getParameterAsBoolean (HttpServletRequest request, + String parameter) + { + return getParameterAsBoolean(request, parameter, null); + } // getParameterAsBoolean + + /** + * Get boolean Parameter. + * @param request request + * @param parameter parameter + * @param expected optional expected value + * @return true if found and if optional value matches + */ + public static boolean getParameterAsBoolean (HttpServletRequest request, + String parameter, String expected) + { + if (request == null || parameter == null) + return false; + String data = getParameter(request, parameter); + if (data == null || data.length() == 0) + return false; + // Ignore actual value + if (expected == null) + return true; + // + return expected.equalsIgnoreCase(data); + } // getParameterAsBoolean + + /** + * get Parameter or Null fi empty + * @param request request + * @param parameter parameter + * @return Request Value or null + */ + public static String getParamOrNull (HttpServletRequest request, String parameter) + { + String value = WebUtil.getParameter(request, parameter); + if(value == null) + return value; + if (value.length() == 0) + return null; + return value; + } // getParamOrNull + + + /** + * reload + * @param logMessage + * @param jsp + * @param session + * @param request + * @param response + * @param thisContext + * @throws ServletException + * @throws IOException + */ + public static void reload(String logMessage, String jsp, HttpSession session, HttpServletRequest request, HttpServletResponse response, ServletContext thisContext) + throws ServletException, IOException + { + session.setAttribute(WebSessionCtx.HDR_MESSAGE, logMessage); + log.warning(" - " + logMessage + " - update not confirmed"); + thisContext.getRequestDispatcher(jsp).forward(request, response); + } + + + /************************************************************************** + * Create Standard Response Header with optional Cookie and print document. + * D:\j2sdk1.4.0\docs\guide\intl\encoding.doc.html + * + * @param request request + * @param response response + * @param servlet servlet + * @param cookieProperties cookie properties + * @param doc doc + * @param debug debug + * @throws IOException + */ + public static void createResponse (HttpServletRequest request, HttpServletResponse response, + HttpServlet servlet, Properties cookieProperties, WebDoc doc, boolean debug) throws IOException + { + response.setHeader("Cache-Control", "no-cache"); + response.setContentType("text/html; charset=UTF-8"); + + // + // Update Cookie - overwrite + if (cookieProperties != null) + { + Cookie cookie = new Cookie (WebEnv.COOKIE_INFO, propertiesEncode(cookieProperties)); + cookie.setComment("(c) adempiere, Inc - Jorg Janke"); + cookie.setSecure(false); + cookie.setPath("/"); + if (cookieProperties.size() == 0) + cookie.setMaxAge(0); // delete cookie + else + cookie.setMaxAge(2592000); // 30 days in seconds 60*60*24*30 + response.addCookie(cookie); + } + // add diagnostics + if (debug && WebEnv.DEBUG) + { + // doc.output(System.out); + WebEnv.addFooter(request, response, servlet, doc.getBody()); + // doc.output(System.out); + } + // String content = doc.toString(); + // response.setContentLength(content.length()); // causes problems at the end of the output + + // print document + PrintWriter out = response.getWriter(); // with character encoding support + doc.output(out); + out.flush(); + if (out.checkError()) + log.log(Level.SEVERE, "error writing"); + // binary output (is faster but does not do character set conversion) + // OutputStream out = response.getOutputStream(); + // byte[] data = doc.toString().getBytes(); + // response.setContentLength(data.length); + // out.write(doc.toString().getBytes()); + // + out.close(); + } // createResponse + + + /************************************************************************** + * Create Java Script to clear Target frame + * + * @param targetFrame target frame + * @return Clear Frame Script + */ + public static script getClearFrame (String targetFrame) + { + StringBuffer cmd = new StringBuffer(); + cmd.append(""); + // + return new script(cmd.toString()); + } // getClearFrame + + + /** + * Return a link and script with new location. + * @param url forward url + * @param delaySec delay in seconds (default 3) + * @return html + */ + public static HtmlCode getForward (String url, int delaySec) + { + if (delaySec <= 0) + delaySec = 3; + HtmlCode retValue = new HtmlCode(); + // Link + a a = new a(url); + a.addElement(url); + retValue.addElement(a); + // Java Script - document.location - + script script = new script("setTimeout(\"window.top.location.replace('" + url + + "')\"," + (delaySec+1000) + ");"); + retValue.addElement(script); + // + return retValue; + } // getForward + + /** + * Create Forward Page + * @param response response + * @param title page title + * @param forwardURL url + * @param delaySec delay in seconds (default 3) + * @throws ServletException + * @throws IOException + */ + public static void createForwardPage (HttpServletResponse response, + String title, String forwardURL, int delaySec) throws ServletException, IOException + { + response.setContentType("text/html; charset=UTF-8"); + WebDoc doc = WebDoc.create(title); + body b = doc.getBody(); + b.addElement(getForward(forwardURL, delaySec)); + PrintWriter out = response.getWriter(); + doc.output(out); + out.flush(); + if (out.checkError()) + log.log(Level.SEVERE, "Error writing"); + out.close(); + log.fine(forwardURL + " - " + title); + } // createForwardPage + + + /** + * Does Test exist + * @param test string + * @return true if String with data + */ + public static boolean exists (String test) + { + if (test == null) + return false; + return test.length() > 0; + } // exists + + /** + * Does Parameter exist + * @param request request + * @param parameter string + * @return true if String with data + */ + public static boolean exists (HttpServletRequest request, String parameter) + { + if (request == null || parameter == null) + return false; + try + { + String enc = request.getCharacterEncoding(); + if (enc == null) + request.setCharacterEncoding(WebEnv.ENCODING); + } + catch (Exception e) + { + log.log(Level.SEVERE, "Set CharacterEncoding=" + WebEnv.ENCODING, e); + } + return exists (request.getParameter(parameter)); + } // exists + + + /** + * Is EMail address valid + * @param email mail address + * @return true if valid + */ + public static boolean isEmailValid (String email) + { + if (email == null || email.length () == 0) + return false; + try + { + InternetAddress ia = new InternetAddress (email, true); + if (ia != null) + return true; + } + catch (AddressException ex) + { + log.warning (email + " - " + + ex.getLocalizedMessage ()); + } + return false; + } // isEmailValid + + + /************************************************************************** + * Decode Properties into String (URL encoded) + * + * @param pp properties + * @return Encoded String + */ + public static String propertiesEncode (Properties pp) + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try + { + pp.store(bos, "adempiere"); // Header + } + catch (IOException e) + { + log.log(Level.SEVERE, "store", e); + } + String result = new String (bos.toByteArray()); + // System.out.println("String=" + result); + try + { + result = URLEncoder.encode(result, WebEnv.ENCODING); + } + catch (UnsupportedEncodingException e) + { + log.log(Level.SEVERE, "encode" + WebEnv.ENCODING, e); + String enc = System.getProperty("file.encoding"); // Windows default is Cp1252 + try + { + result = URLEncoder.encode(result, enc); + log.info("encode: " + enc); + } + catch (Exception ex) + { + log.log(Level.SEVERE, "encode", ex); + } + } + // System.out.println("String-Encoded=" + result); + return result; + } // propertiesEncode + + /** + * Decode data String (URL encoded) into Properties + * + * @param data data + * @return Properties + */ + public static Properties propertiesDecode (String data) + { + String result = null; + // System.out.println("String=" + data); + try + { + result = URLDecoder.decode(data, WebEnv.ENCODING); + } + catch (UnsupportedEncodingException e) + { + log.log(Level.SEVERE, "decode" + WebEnv.ENCODING, e); + String enc = System.getProperty("file.encoding"); // Windows default is Cp1252 + try + { + result = URLEncoder.encode(data, enc); + log.log(Level.SEVERE, "decode: " + enc); + } + catch (Exception ex) + { + log.log(Level.SEVERE, "decode", ex); + } + } + // System.out.println("String-Decoded=" + result); + + ByteArrayInputStream bis = new ByteArrayInputStream(result.getBytes()); + Properties pp = new Properties(); + try + { + pp.load(bis); + } + catch (IOException e) + { + log.log(Level.SEVERE, "load", e); + } + return pp; + } // propertiesDecode + + + /************************************************************************** + * Convert Array of NamePair to HTTP Option Array. + *

+ * If the ArrayList does not contain NamePairs, the String value is used + * @see org.compiere.util.NamePair + * @param list ArrayList containing NamePair values + * @param default_ID Sets the default if the key/ID value is found. + * If the value is null or empty, the first value is selected + * @return Option Array + */ + public static option[] convertToOption (NamePair[] list, String default_ID) + { + int size = list.length; + option[] retValue = new option[size]; + for (int i = 0; i < size; i++) + { + boolean selected = false; + // select first entry + if (i == 0 && (default_ID == null || default_ID.length() == 0)) + selected = true; + + // Create option + String name = Util.maskHTML(list[i].getName()); + retValue[i] = new option(list[i].getID()).addElement(name); + + // Select if ID/Key is same as default ID + if (default_ID != null && default_ID.equals(list[i].getID())) + selected = true; + retValue[i].setSelected(selected); + } + return retValue; + } // convertToOption + + + /** + * Create label/field table row + * + * @param line - null for new line (table row) + * @param FORMNAME form name + * @param PARAMETER parameter name + * @param labelText label + * @param inputType HTML input type + * @param value data value + * @param sizeDisplay display size + * @param size data size + * @param longField field spanning two columns + * @param mandatory mark as mandatory + * @param onChange onChange call + * @param script script + * @return tr table row + */ + static public tr createField (tr line, String FORMNAME, String PARAMETER, + String labelText, String inputType, Object value, + int sizeDisplay, int size, boolean longField, + boolean mandatory, String onChange, StringBuffer script) + { + if (line == null) + line = new tr(); + String labelInfo = labelText; + if (mandatory) + { + labelInfo += " *"; + String fName = "document." + FORMNAME + "." + PARAMETER; + script.append(fName).append(".required=true; "); + } + + label llabel = new label().setFor(PARAMETER).addElement(labelInfo); + llabel.setID("ID_" + PARAMETER + "_Label"); + // label.setTitle(description); + line.addElement(new td().addElement(llabel).setAlign(AlignType.RIGHT)); + input iinput = new input(inputType, PARAMETER, value == null ? "" : value.toString()); + iinput.setSize(sizeDisplay).setMaxlength(size); + iinput.setID("ID_" + PARAMETER); + if (onChange != null && onChange.length() > 0) + iinput.setOnChange(onChange); + iinput.setTitle(labelText); + td field = new td().addElement(iinput).setAlign(AlignType.LEFT); + if (longField) + field.setColSpan(3); + line.addElement(field); + return line; + } // addField + + /** + * Get Close PopUp Buton + * @return button + */ + public static input createClosePopupButton() + { + input close = new input (input.TYPE_BUTTON, "closePopup", "Close"); + close.setTitle ("Close PopUp"); // Help + close.setOnClick ("closePopup();return false;"); + return close; + } // getClosePopupButton + + + /** + * Stream Attachment Entry + * @param response response + * @param attachment attachment + * @param attachmentIndex logical index + * @return error message or null + */ + public static String streamAttachment (HttpServletResponse response, + MAttachment attachment, int attachmentIndex) + { + if (attachment == null) + return "No Attachment"; + + int realIndex = -1; + MAttachmentEntry[] entries = attachment.getEntries(); + for (int i = 0; i < entries.length; i++) + { + MAttachmentEntry entry = entries[i]; + if (entry.getIndex() == attachmentIndex) + { + realIndex = i; + break; + } + } + if (realIndex < 0) + { + log.fine("No Attachment Entry for Index=" + + attachmentIndex + " - " + attachment); + return "Attachment Entry not found"; + } + + MAttachmentEntry entry = entries[realIndex]; + if (entry.getData() == null) + { + log.fine("Empty Attachment Entry for Index=" + + attachmentIndex + " - " + attachment); + return "Attachment Entry empty"; + } + + // Stream Attachment Entry + try + { + int bufferSize = 2048; // 2k Buffer + int fileLength = entry.getData().length; + // + response.setContentType(entry.getContentType()); + response.setBufferSize(bufferSize); + response.setContentLength(fileLength); + // + log.fine(entry.toString()); + long time = System.currentTimeMillis(); // timer start + // + ServletOutputStream out = response.getOutputStream (); + out.write (entry.getData()); + out.flush(); + out.close(); + // + time = System.currentTimeMillis() - time; + double speed = (fileLength/1024) / ((double)time/1000); + log.info("Length=" + + fileLength + " - " + + time + " ms - " + + speed + " kB/sec - " + entry.getContentType()); + } + catch (IOException ex) + { + log.log(Level.SEVERE, ex.toString()); + return "Streaming error - " + ex; + } + return null; + } // streamAttachment + + + /** + * Stream File + * @param response response + * @param file file to stream + * @return error message or null + */ + public static String streamFile (HttpServletResponse response, File file) + { + if (file == null) + return "No File"; + if (!file.exists()) + return "File not found: " + file.getAbsolutePath(); + + MimeType mimeType = MimeType.get(file.getAbsolutePath()); + // Stream File + try + { + int bufferSize = 2048; // 2k Buffer + int fileLength = (int)file.length(); + // + response.setContentType(mimeType.getMimeType()); + response.setBufferSize(bufferSize); + response.setContentLength(fileLength); + // + log.fine(file.toString()); + long time = System.currentTimeMillis(); // timer start + // Get Data + FileInputStream in = new FileInputStream(file); + ServletOutputStream out = response.getOutputStream (); + int c = 0; + while ((c = in.read()) != -1) + out.write(c); + // + out.flush(); + out.close(); + in.close(); + // + time = System.currentTimeMillis() - time; + double speed = (fileLength/1024) / ((double)time/1000); + log.info("Length=" + + fileLength + " - " + + time + " ms - " + + speed + " kB/sec - " + mimeType); + } + catch (IOException ex) + { + log.log(Level.SEVERE, ex.toString()); + return "Streaming error - " + ex; + } + return null; + } // streamFile + + + /** + * Remove Cookie with web user by setting user to _ + * @param request request (for context path) + * @param response response to add cookie + */ + public static void deleteCookieWebUser (HttpServletRequest request, HttpServletResponse response, String COOKIE_NAME) + { + Cookie cookie = new Cookie(COOKIE_NAME, " "); + cookie.setComment("adempiere Web User"); + cookie.setPath(request.getContextPath()); + cookie.setMaxAge(1); // second + response.addCookie(cookie); + } // deleteCookieWebUser + + /************************************************************************** + * Send EMail + * @param request request + * @param to web user + * @param msgType see MMailMsg.MAILMSGTYPE_* + * @param parameter object array with parameters + * @return mail EMail.SENT_OK or error message + */ + public static String sendEMail (HttpServletRequest request, WebUser to, + String msgType, Object[] parameter) + { + WebSessionCtx wsc = WebSessionCtx.get(request); + MStore wStore = wsc.wstore; + MMailMsg mailMsg = wStore.getMailMsg(msgType); + // + StringBuffer subject = new StringBuffer(mailMsg.getSubject()); + if (parameter.length > 0 && parameter[0] != null) + subject.append(parameter[0]); + // + StringBuffer message = new StringBuffer(); + String hdr = wStore.getEMailFooter(); + if (hdr != null && hdr.length() > 0) + message.append(hdr).append("\n"); + message.append(mailMsg.getMessage()); + if (parameter.length > 1 && parameter[1] != null) + message.append(parameter[1]); + if (mailMsg.getMessage2() != null) + { + message.append("\n") + .append(mailMsg.getMessage2()); + if (parameter.length > 2 && parameter[2] != null) + message.append(parameter[2]); + } + if (mailMsg.getMessage3() != null) + { + message.append("\n") + .append(mailMsg.getMessage3()); + if (parameter.length > 3 && parameter[3] != null) + message.append(parameter[3]); + } + message.append(MRequest.SEPARATOR) + .append("http://").append(request.getServerName()).append(request.getContextPath()) + .append("/ - ").append(wStore.getName()) + .append("\n").append("Request from: ").append(getFrom(request)) + .append("\n"); + String ftr = wStore.getEMailFooter(); + if (ftr != null && ftr.length() > 0) + message.append(ftr); + + // Create Mail + EMail email = wStore.createEMail(to.getEmail(), + subject.toString(), message.toString()); + // CC Order + if (msgType == MMailMsg.MAILMSGTYPE_OrderAcknowledgement) + { + String orderEMail = wStore.getWebOrderEMail(); + String storeEMail = wStore.getWStoreEMail(); + if (orderEMail != null && orderEMail.length() > 0 + && !orderEMail.equals(storeEMail)) // already Bcc + email.addBcc(orderEMail); + } + + // Send + String retValue = email.send(); + // Log + MUserMail um = new MUserMail(mailMsg, to.getAD_User_ID(), email); + um.save(); + // + return retValue; + } // sendEMail + + /** + * Get Remote From info + * @param request request + * @return remore info + */ + public static String getFrom (HttpServletRequest request) + { + String host = request.getRemoteHost(); + if (!host.equals(request.getRemoteAddr())) + host += " (" + request.getRemoteAddr() + ")"; + return host; + } // getFrom + + /** + * Add Cookie with web user + * @param request request (for context path) + * @param response response to add cookie + * @param webUser email address + */ + public static void addCookieWebUser (HttpServletRequest request, HttpServletResponse response, String webUser, String COOKIE_NAME) + { + Cookie cookie = new Cookie(COOKIE_NAME, webUser); + cookie.setComment("adempiere Web User"); + cookie.setPath(request.getContextPath()); + cookie.setMaxAge(2592000); // 30 days in seconds 60*60*24*30 + response.addCookie(cookie); + } // setCookieWebUser + + /** + * Resend Validation Code + * @param request request + * @param wu user + */ + public static void resendCode(HttpServletRequest request, WebUser wu) + { + String msg = sendEMail(request, wu, + MMailMsg.MAILMSGTYPE_UserVerification, + new Object[]{ + request.getServerName(), + wu.getName(), + wu.getEMailVerifyCode()}); + if (EMail.SENT_OK.equals(msg)) + wu.setPasswordMessage ("EMail sent"); + else + wu.setPasswordMessage ("Problem sending EMail: " + msg); + } // resendCode + + + /** + * Update Web User + * @param request request + * @param wu user + * @param updateEMailPwd if true, change email/password + * @return true if saved + */ + public static boolean updateFields (HttpServletRequest request, WebUser wu, boolean updateEMailPwd) + { + if (updateEMailPwd) + { + String s = WebUtil.getParameter (request, "PasswordNew"); + wu.setPasswordMessage (null); + wu.setPassword (s); + if (wu.getPasswordMessage () != null) + { + return false; + } + // + s = WebUtil.getParameter (request, "EMail"); + if (!WebUtil.isEmailValid (s)) + { + wu.setPasswordMessage ("EMail Invalid"); + return false; + } + wu.setEmail (s.trim()); + } + // + StringBuffer mandatory = new StringBuffer(); + String s = WebUtil.getParameter (request, "Name"); + if (s != null && s.length() != 0) + wu.setName(s.trim()); + else + mandatory.append(" - Name"); + s = WebUtil.getParameter (request, "Company"); + if (s != null && s.length() != 0) + wu.setCompany(s); + s = WebUtil.getParameter (request, "Title"); + if (s != null && s.length() != 0) + wu.setTitle(s); + // + s = WebUtil.getParameter (request, "Address"); + if (s != null && s.length() != 0) + wu.setAddress(s); + else + mandatory.append(" - Address"); + s = WebUtil.getParameter (request, "Address2"); + if (s != null && s.length() != 0) + wu.setAddress2(s); + // + s = WebUtil.getParameter (request, "City"); + if (s != null && s.length() != 0) + wu.setCity(s); + else + mandatory.append(" - City"); + s = WebUtil.getParameter (request, "Postal"); + if (s != null && s.length() != 0) + wu.setPostal(s); + else + mandatory.append(" - Postal"); + // Set Country before Region for validation + s = WebUtil.getParameter (request, "C_Country_ID"); + if (s != null && s.length() != 0) + wu.setC_Country_ID(s); + s = WebUtil.getParameter (request, "C_Region_ID"); + if (s != null && s.length() != 0) + wu.setC_Region_ID(s); + s = WebUtil.getParameter (request, "RegionName"); + if (s != null && s.length() != 0) + wu.setRegionName(s); + // + s = WebUtil.getParameter (request, "Phone"); + if (s != null && s.length() != 0) + wu.setPhone(s); + s = WebUtil.getParameter (request, "Phone2"); + if (s != null && s.length() != 0) + wu.setPhone2(s); + s = WebUtil.getParameter (request, "C_BP_Group_ID"); + if (s != null && s.length() != 0) + wu.setC_BP_Group_ID (s); + s = WebUtil.getParameter (request, "Fax"); + if (s != null && s.length() != 0) + wu.setFax(s); + // + if (mandatory.length() > 0) + { + mandatory.insert(0, "Enter Mandatory"); + wu.setSaveErrorMessage(mandatory.toString()); + return false; + } + return wu.save(); + } // updateFields +} // WUtil diff --git a/base/src/org/compiere/util/package.html b/base/src/org/compiere/util/package.html new file mode 100644 index 0000000000..9498c814f9 --- /dev/null +++ b/base/src/org/compiere/util/package.html @@ -0,0 +1,25 @@ + + + + + +

Provides utility functions.

+

Package Specification

+

Utility.

+ +

Related Documentation

+

For overviews, tutorials, examples, guides, and tool documentation, please + see: http://www.adempiere.org

+

+ +

+ + diff --git a/base/src/org/compiere/wf/DocWorkflowManager.java b/base/src/org/compiere/wf/DocWorkflowManager.java new file mode 100644 index 0000000000..2dd6a6e193 --- /dev/null +++ b/base/src/org/compiere/wf/DocWorkflowManager.java @@ -0,0 +1,211 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.sql.*; +import java.util.logging.*; + +import org.compiere.model.*; +import org.compiere.process.*; +import org.compiere.util.*; + + +/** + * Document Workflow Manager + * + * @author Jorg Janke + * @version $Id: DocWorkflowManager.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class DocWorkflowManager implements DocWorkflowMgr +{ + /** + * Get Document Workflow Manager + * @return mgr + */ + public static DocWorkflowManager get() + { + if (s_mgr == null) + s_mgr = new DocWorkflowManager(); + return s_mgr; + } // get + + // Set PO Workflow Manager + static { + PO.setDocWorkflowMgr(get()); + } + + /** Document Workflow Manager */ + private static DocWorkflowManager s_mgr = null; + /** Logger */ + private static CLogger log = CLogger.getCLogger(DocWorkflowManager.class); + + + /** + * Doc Workflow Manager + */ + private DocWorkflowManager () + { + super (); + if (s_mgr == null) + s_mgr = this; + } // DocWorkflowManager + + private int m_noCalled = 0; + private int m_noStarted = 0; + + /** + * Process Document Value Workflow + * @param document document + * @param AD_Table_ID table + * @return true if WF started + */ + public boolean process (PO document, int AD_Table_ID) + { + m_noCalled++; + MWorkflow[] wfs = MWorkflow.getDocValue (document.getCtx(), + document.getAD_Client_ID(), AD_Table_ID + , document.get_TrxName() // Bug 1568766 Trx should be kept all along the road + ); + if (wfs == null || wfs.length == 0) + return false; + + boolean started = false; + for (int i = 0; i < wfs.length; i++) + { + MWorkflow wf = wfs[i]; + // We have a Document Workflow + String logic = wf.getDocValueLogic(); + if (logic == null || logic.length() == 0) + { + log.severe ("Workflow has no Logic - " + wf.getName()); + continue; + } + + // Re-check: Document must be same Client as workflow + if (wf.getAD_Client_ID() != document.getAD_Client_ID()) + continue; + + // Check Logic + boolean sql = logic.startsWith("SQL="); + if (sql && !testStart(wf, document)) + { + log.fine("SQL Logic evaluated to false (" + logic + ")"); + continue; + } + if (!sql && !Evaluator.evaluateLogic(document, logic)) + { + log.fine("Logic evaluated to false (" + logic + ")"); + continue; + } + + // Start Workflow + log.fine(logic); + int AD_Process_ID = 305; // HARDCODED + ProcessInfo pi = new ProcessInfo (wf.getName(), AD_Process_ID, + AD_Table_ID, document.get_ID()); + pi.setAD_User_ID (Env.getAD_User_ID(document.getCtx())); + pi.setAD_Client_ID(document.getAD_Client_ID()); + // + if (wf.start(pi) != null) + { + log.config(wf.getName()); + m_noStarted++; + started = true; + } + } + return started; + } // process + + /** + * Test Start condition + * @param wf workflow + * @param document document + * @return true if WF should be started + */ + private boolean testStart (MWorkflow wf, PO document) + { + boolean retValue = false; + String logic = wf.getDocValueLogic(); + logic = logic.substring(4); // "SQL=" + // + String tableName = document.get_TableName(); + String[] keyColumns = document.get_KeyColumns(); + if (keyColumns.length != 1) + { + log.severe("Tables with more then one key column not supported - " + + tableName + " = " + keyColumns.length); + return false; + } + String keyColumn = keyColumns[0]; + StringBuffer sql = new StringBuffer("SELECT ") + .append(keyColumn).append(" FROM ").append(tableName) + .append(" WHERE AD_Client_ID=? AND ") // #1 + .append(keyColumn).append("=? AND ") // #2 + .append(logic) + // Duplicate Open Workflow test + .append(" AND NOT EXISTS (SELECT * FROM AD_WF_Process wfp ") + .append("WHERE wfp.AD_Table_ID=? AND wfp.Record_ID=") // #3 + .append(tableName).append(".").append(keyColumn) + .append(" AND wfp.AD_Workflow_ID=?") // #4 + .append(" AND SUBSTR(wfp.WFState,1,1)='O')"); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql.toString(), document.get_TrxName()); + pstmt.setInt (1, wf.getAD_Client_ID()); + pstmt.setInt (2, document.get_ID()); + pstmt.setInt (3, document.get_Table_ID()); + pstmt.setInt (4, wf.getAD_Workflow_ID()); + ResultSet rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = true; + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, "Logic=" + logic + + " - SQL=" + sql.toString(), e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + return retValue; + } // testStart + + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("DocWorkflowManager["); + sb.append("Called=").append(m_noCalled) + .append(",Stated=").append(m_noStarted) + .append("]"); + return sb.toString(); + } // toString +} // DocWorkflowManager diff --git a/base/src/org/compiere/wf/MWFActivity.java b/base/src/org/compiere/wf/MWFActivity.java new file mode 100644 index 0000000000..b748ff55b4 --- /dev/null +++ b/base/src/org/compiere/wf/MWFActivity.java @@ -0,0 +1,1608 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.io.*; +import java.math.*; +import java.rmi.*; +import java.sql.*; +import java.text.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.db.*; +import org.compiere.interfaces.*; +import org.compiere.model.*; +import org.compiere.print.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Workflow Activity Model. + * Controlled by WF Process: + * set Node - startWork + * + * @author Jorg Janke + * @version $Id: MWFActivity.java,v 1.4 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MWFActivity extends X_AD_WF_Activity implements Runnable +{ + /** + * Get Activities for table/tecord + * @param ctx context + * @param AD_Table_ID table + * @param Record_ID record + * @param activeOnly if true only not processed records are returned + * @return activity + */ + public static MWFActivity[] get (Properties ctx, int AD_Table_ID, int Record_ID, boolean activeOnly) + { + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + String sql = "SELECT * FROM AD_WF_Activity WHERE AD_Table_ID=? AND Record_ID=?"; + if (activeOnly) + sql += " AND Processed<>'Y'"; + sql += " ORDER BY AD_WF_Activity_ID"; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, AD_Table_ID); + pstmt.setInt (2, Record_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MWFActivity (ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MWFActivity[] retValue = new MWFActivity[list.size ()]; + list.toArray (retValue); + return retValue; + } // get + + /** + * Get Active Info + * @param ctx context + * @param AD_Table_ID table + * @param Record_ID record + * @return activity summary + */ + public static String getActiveInfo (Properties ctx, int AD_Table_ID, int Record_ID) + { + MWFActivity[] acts = get (ctx, AD_Table_ID, Record_ID, true); + if (acts == null || acts.length == 0) + return null; + // + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < acts.length; i++) + { + if (i > 0) + sb.append("\n"); + MWFActivity activity = acts[i]; + sb.append(activity.toStringX()); + } + return sb.toString(); + } // getActivityInfo + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MWFActivity.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param AD_WF_Activity_ID id + * @param trxName transaction + */ + public MWFActivity (Properties ctx, int AD_WF_Activity_ID, String trxName) + { + super (ctx, AD_WF_Activity_ID, trxName); + if (AD_WF_Activity_ID == 0) + throw new IllegalArgumentException ("Cannot create new WF Activity directly"); + m_state = new StateEngine (getWFState()); + } // MWFActivity + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MWFActivity (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + m_state = new StateEngine (getWFState()); + } // MWFActivity + + /** + * Parent Contructor + * @param process process + * @param AD_WF_Node_ID start node + */ + public MWFActivity (MWFProcess process, int AD_WF_Node_ID) + { + super (process.getCtx(), 0, process.get_TrxName()); + setAD_WF_Process_ID (process.getAD_WF_Process_ID()); + setPriority(process.getPriority()); + // Document Link + setAD_Table_ID(process.getAD_Table_ID()); + setRecord_ID(process.getRecord_ID()); + // Status + super.setWFState(WFSTATE_NotStarted); + m_state = new StateEngine (getWFState()); + setProcessed (false); + // Set Workflow Node + setAD_Workflow_ID (process.getAD_Workflow_ID()); + setAD_WF_Node_ID (AD_WF_Node_ID); + // Node Priority & End Duration + MWFNode node = MWFNode.get(getCtx(), AD_WF_Node_ID); + int priority = node.getPriority(); + if (priority != 0 && priority != getPriority()) + setPriority (priority); + long limitMS = node.getLimitMS(); + if (limitMS != 0) + setEndWaitTime(new Timestamp(limitMS + System.currentTimeMillis())); + // Responsible + setResponsible(process); + save(); + // + m_audit = new MWFEventAudit(this); + m_audit.save(); + // + m_process = process; + } // MWFActivity + + /** State Machine */ + private StateEngine m_state = null; + /** Workflow Node */ + private MWFNode m_node = null; + /** Transaction */ + private Trx m_trx = null; + /** Audit */ + private MWFEventAudit m_audit = null; + /** Persistent Object */ + private PO m_po = null; + /** Document Status */ + private String m_docStatus = null; + /** New Value to save in audit */ + private String m_newValue = null; + /** Process */ + private MWFProcess m_process = null; + /** Post Immediate Candidate */ + private DocAction m_postImmediate = null; + /** List of email recipients */ + private ArrayList m_emails = new ArrayList(); + + /************************************************************************** + * Get State + * @return state + */ + public StateEngine getState() + { + return m_state; + } // getState + + /** + * Set Activity State + * @param WFState + */ + public void setWFState (String WFState) + { + if (m_state == null) + m_state = new StateEngine (getWFState()); + if (m_state.isClosed()) + return; + if (getWFState().equals(WFState)) + return; + // + if (m_state.isValidNewState(WFState)) + { + String oldState = getWFState(); + log.fine(oldState + "->"+ WFState + ", Msg=" + getTextMsg()); + super.setWFState (WFState); + m_state = new StateEngine (getWFState()); + save(); // closed in MWFProcess.checkActivities() + updateEventAudit(); + + // Inform Process + if (m_process == null) + m_process = new MWFProcess (getCtx(), getAD_WF_Process_ID(), null); + m_process.checkActivities(m_trx == null ? null : m_trx.getTrxName()); + } + else + { + String msg = "Set WFState - Ignored Invalid Transformation - New=" + + WFState + ", Current=" + getWFState(); + log.log(Level.SEVERE, msg); + Trace.printStack(); + setTextMsg(msg); + save(); + } + } // setWFState + + /** + * Is Activity closed + * @return true if closed + */ + public boolean isClosed() + { + return m_state.isClosed(); + } // isClosed + + + /************************************************************************** + * Update Event Audit + */ + private void updateEventAudit() + { + // log.fine(""); + getEventAudit(); + m_audit.setTextMsg(getTextMsg()); + m_audit.setWFState(getWFState()); + if (m_newValue != null) + m_audit.setNewValue(m_newValue); + if (m_state.isClosed()) + { + m_audit.setEventType(MWFEventAudit.EVENTTYPE_ProcessCompleted); + long ms = System.currentTimeMillis() - m_audit.getCreated().getTime(); + m_audit.setElapsedTimeMS(new BigDecimal(ms)); + } + else + m_audit.setEventType(MWFEventAudit.EVENTTYPE_StateChanged); + m_audit.save(); + } // updateEventAudit + + /** + * Get/Create Event Audit + * @return event + */ + public MWFEventAudit getEventAudit() + { + if (m_audit != null) + return m_audit; + MWFEventAudit[] events = MWFEventAudit.get(getCtx(), getAD_WF_Process_ID(), getAD_WF_Node_ID()); + if (events == null || events.length == 0) + m_audit = new MWFEventAudit(this); + else + m_audit = events[events.length-1]; // last event + return m_audit; + } // getEventAudit + + + /************************************************************************** + * Get Persistent Object in Transaction + * @param trx transaction + * @return po + */ + public PO getPO (Trx trx) + { + if (m_po != null) + return m_po; + + MTable table = MTable.get (getCtx(), getAD_Table_ID()); + if (trx != null) + m_po = table.getPO(getRecord_ID(), trx.getTrxName()); + else + m_po = table.getPO(getRecord_ID(), null); + return m_po; + } // getPO + + /** + * Get Persistent Object + * @return po + */ + public PO getPO() + { + return getPO(null); + } // getPO + + /** + * Get PO AD_Client_ID + * @return client of PO + */ + public int getPO_AD_Client_ID() + { + if (m_po == null) + getPO(null); + if (m_po != null) + return m_po.getAD_Client_ID(); + return 0; + } // getPO_AD_Client_ID + + /** + * Get Attribute Value (based on Node) of PO + * @return Attribute Value or null + */ + public Object getAttributeValue() + { + MWFNode node = getNode(); + if (node == null) + return null; + int AD_Column_ID = node.getAD_Column_ID(); + if (AD_Column_ID == 0) + return null; + PO po = getPO(); + if (po.get_ID() == 0) + return null; + return po.get_ValueOfColumn(AD_Column_ID); + } // getAttributeValue + + /** + * Is SO Trx + * @return SO Trx or of not found true + */ + public boolean isSOTrx() + { + PO po = getPO(); + if (po.get_ID() == 0) + return true; + // Is there a Column? + int index = po.get_ColumnIndex("IsSOTrx"); + if (index < 0) + { + if (po.get_TableName().startsWith("M_")) + return false; + return true; + } + // we have a column + try + { + Boolean IsSOTrx = (Boolean)po.get_Value(index); + return IsSOTrx.booleanValue(); + } + catch (Exception e) + { + log.log(Level.SEVERE, "", e); + } + return true; + } // isSOTrx + + + /************************************************************************** + * Set AD_WF_Node_ID. + * (Re)Set to Not Started + * @param AD_WF_Node_ID now node + */ + public void setAD_WF_Node_ID (int AD_WF_Node_ID) + { + if (AD_WF_Node_ID == 0) + throw new IllegalArgumentException("Workflow Node is not defined"); + super.setAD_WF_Node_ID (AD_WF_Node_ID); + // + if (!WFSTATE_NotStarted.equals(getWFState())) + { + super.setWFState(WFSTATE_NotStarted); + m_state = new StateEngine (getWFState()); + } + if (isProcessed()) + setProcessed (false); + } // setAD_WF_Node_ID + + /** + * Get WF Node + * @return node + */ + public MWFNode getNode() + { + if (m_node == null) + m_node = MWFNode.get (getCtx(), getAD_WF_Node_ID()); + return m_node; + } // getNode + + /** + * Get WF Node Name + * @return translated node name + */ + public String getNodeName() + { + return getNode().getName(true); + } // getNodeName + + /** + * Get Node Description + * @return translated node description + */ + public String getNodeDescription() + { + return getNode().getDescription(true); + } // getNodeDescription + + /** + * Get Node Help + * @return translated node help + */ + public String getNodeHelp() + { + return getNode().getHelp(true); + } // getNodeHelp + + + /** + * Is this an user Approval step? + * @return true if User Approval + */ + public boolean isUserApproval() + { + return getNode().isUserApproval(); + } // isNodeApproval + + /** + * Is this a Manual user step? + * @return true if Window/Form/.. + */ + public boolean isUserManual() + { + return getNode().isUserManual(); + } // isUserManual + + /** + * Is this a user choice step? + * @return true if User Choice + */ + public boolean isUserChoice() + { + return getNode().isUserChoice(); + } // isUserChoice + + + /** + * Set Text Msg (add to existing) + * @param TextMsg + */ + public void setTextMsg (String TextMsg) + { + if (TextMsg == null || TextMsg.length() == 0) + return; + String oldText = getTextMsg(); + if (oldText == null || oldText.length() == 0) + super.setTextMsg (Util.trimSize(TextMsg,1000)); + else if (TextMsg != null && TextMsg.length() > 0) + super.setTextMsg (Util.trimSize(oldText + "\n - " + TextMsg,1000)); + } // setTextMsg + + /** + * Add to Text Msg + * @param obj some object + */ + public void addTextMsg (Object obj) + { + if (obj == null) + return; + // + StringBuffer TextMsg = new StringBuffer (obj.toString()); + if (obj instanceof Exception) + { + Exception ex = (Exception)obj; + while (ex != null) + { + StackTraceElement[] st = ex.getStackTrace(); + for (int i = 0; i < st.length; i++) + { + StackTraceElement ste = st[i]; + if (i == 0 || ste.getClassName().startsWith("org.compiere")) + TextMsg.append(" (").append(i).append("): ") + .append(ste.toString()) + .append("\n"); + } + if (ex.getCause() instanceof Exception) + ex = (Exception)ex.getCause(); + else + ex = null; + } + } + // + String oldText = getTextMsg(); + if (oldText == null || oldText.length() == 0) + super.setTextMsg(Util.trimSize(TextMsg.toString(),1000)); + else if (TextMsg != null && TextMsg.length() > 0) + super.setTextMsg(Util.trimSize(oldText + "\n - " + TextMsg.toString(),1000)); + } // setTextMsg + + /** + * Get WF State text + * @return state text + */ + public String getWFStateText () + { + return MRefList.getListName(getCtx(), WFSTATE_AD_Reference_ID, getWFState()); + } // getWFStateText + + /** + * Set Responsible and User from Process / Node + * @param process process + */ + private void setResponsible (MWFProcess process) + { + // Responsible + int AD_WF_Responsible_ID = getNode().getAD_WF_Responsible_ID(); + if (AD_WF_Responsible_ID == 0) // not defined on Node Level + AD_WF_Responsible_ID = process.getAD_WF_Responsible_ID(); + setAD_WF_Responsible_ID (AD_WF_Responsible_ID); + MWFResponsible resp = getResponsible(); + + // User - Directly responsible + int AD_User_ID = resp.getAD_User_ID(); + // Invoker - get Sales Rep or last updater of document + if (AD_User_ID == 0 && resp.isInvoker()) + AD_User_ID = process.getAD_User_ID(); + // + setAD_User_ID(AD_User_ID); + } // setResponsible + + /** + * Get Responsible + * @return responsible + */ + public MWFResponsible getResponsible() + { + MWFResponsible resp = MWFResponsible.get(getCtx(), getAD_WF_Responsible_ID()); + return resp; + } // isInvoker + + /** + * Is Invoker (no user & no role) + * @return true if invoker + */ + public boolean isInvoker() + { + return getResponsible().isInvoker(); + } // isInvoker + + /** + * Get Approval User. + * If the returned user is the same, the document is approved. + * @param AD_User_ID starting User + * @param C_Currency_ID currency + * @param amount amount + * @param AD_Org_ID document organization + * @param ownDocument the document is owned by AD_User_ID + * @return AD_User_ID - if -1 no Approver + */ + public int getApprovalUser (int AD_User_ID, + int C_Currency_ID, BigDecimal amount, + int AD_Org_ID, boolean ownDocument) + { + // Nothing to approve + if (amount == null + || amount.signum() == 0) + return AD_User_ID; + + // Starting user + MUser user = MUser.get(getCtx(), AD_User_ID); + log.info("For User=" + user + + ", Amt=" + amount + + ", Own=" + ownDocument); + + MUser oldUser = null; + while (user != null) + { + if (user.equals(oldUser)) + { + log.info("Loop - " + user.getName()); + return -1; + } + oldUser = user; + log.fine("User=" + user.getName()); + // Get Roles of User + MRole[] roles = user.getRoles(AD_Org_ID); + for (int i = 0; i < roles.length; i++) + { + MRole role = roles[i]; + if (ownDocument && !role.isCanApproveOwnDoc()) + continue; // find a role with allows them to approve own + BigDecimal roleAmt = role.getAmtApproval(); + if (roleAmt == null || roleAmt.signum() == 0) + continue; + if (C_Currency_ID != role.getC_Currency_ID() + && role.getC_Currency_ID() != 0) // No currency = amt only + { + roleAmt = MConversionRate.convert(getCtx(),// today & default rate + roleAmt, role.getC_Currency_ID(), + C_Currency_ID, getAD_Client_ID(), AD_Org_ID); + if (roleAmt == null || roleAmt.signum() == 0) + continue; + } + boolean approved = amount.compareTo(roleAmt) <= 0; + log.fine("Approved=" + approved + + " - User=" + user.getName() + ", Role=" + role.getName() + + ", ApprovalAmt=" + roleAmt); + if (approved) + return user.getAD_User_ID(); + } + + // **** Find next User + // Get Supervisor + if (user.getSupervisor_ID() != 0) + { + user = MUser.get(getCtx(), user.getSupervisor_ID()); + log.fine("Supervisor: " + user.getName()); + } + else + { + log.fine("No Supervisor"); + MOrg org = MOrg.get (getCtx(), AD_Org_ID); + MOrgInfo orgInfo = org.getInfo(); + // Get Org Supervisor + if (orgInfo.getSupervisor_ID() != 0) + { + user = MUser.get(getCtx(), orgInfo.getSupervisor_ID()); + log.fine("Org=" + org.getName() + ",Supervisor: " + user.getName()); + } + else + { + log.fine("No Org Supervisor"); + // Get Parent Org Supervisor + if (orgInfo.getParent_Org_ID() != 0) + { + org = MOrg.get (getCtx(), orgInfo.getParent_Org_ID()); + orgInfo = org.getInfo(); + if (orgInfo.getSupervisor_ID() != 0) + { + user = MUser.get(getCtx(), orgInfo.getSupervisor_ID()); + log.fine("Parent Org Supervisor: " + user.getName()); + } + } + } + } // No Supervisor + + } // while there is a user to approve + + log.fine("No user found"); + return -1; + } // getApproval + + + /************************************************************************** + * Execute Work. + * Called from MWFProcess.startNext + * Feedback to Process via setWFState -> checkActivities + */ + public void run() + { + log.info ("Node=" + getNode()); + m_newValue = null; + if (!m_state.isValidAction(StateEngine.ACTION_Start)) + { + setTextMsg("State=" + getWFState() + " - cannot start"); + setWFState(StateEngine.STATE_Terminated); + return; + } + // + setWFState(StateEngine.STATE_Running); + m_trx = Trx.get(Trx.createTrxName("WF"), true); + // + try + { + if (getNode().get_ID() == 0) + { + setTextMsg("Node not found - AD_WF_Node_ID=" + getAD_WF_Node_ID()); + setWFState(StateEngine.STATE_Aborted); + return; + } + // Do Work + /**** Trx Start ****/ + boolean done = performWork(m_trx); + //begin vpj-cd e-evolution 03/08/2005 PostgreSQL + // Reason: When is execute setWFState create a transaction for same table is generate a clicle Trx + // is cause that PostgreSQL wait into transaction idle + //setWFState (done ? StateEngine.STATE_Completed : StateEngine.STATE_Suspended); + //end vpj-cd e-evolution 03/08/2005 PostgreSQL + /**** Trx End ****/ + m_trx.commit(); + m_trx.close(); + m_trx = null; + //begin vpj-cd e-evolution 03/08/2005 PostgreSQL + //Reason: setWFState moved for the first trx be finished + setWFState (done ? StateEngine.STATE_Completed : StateEngine.STATE_Suspended); + //end vpj-cd e-evolution 03/08/2005 PostgreSQL + if (m_postImmediate != null) + postImmediate(); + } + catch (Exception e) + { + log.log(Level.WARNING, "" + getNode(), e); + /**** Trx Rollback ****/ + m_trx.rollback(); + m_trx.close(); + m_trx = null; + // + if (e.getCause() != null) + log.log(Level.WARNING, "Cause", e.getCause()); + String processMsg = e.getLocalizedMessage(); + if (processMsg == null || processMsg.length() == 0) + processMsg = e.getMessage(); + setTextMsg(processMsg); + addTextMsg(e); + setWFState (StateEngine.STATE_Terminated); // unlocks + // Set Document Status + if (m_po != null && m_docStatus != null) + { + m_po.load(null); + DocAction doc = (DocAction)m_po; + doc.setDocStatus(m_docStatus); + m_po.save(); + } + } + m_trx = null; + } // run + + + /** + * Perform Work. + * Set Text Msg. + * @param trx transaction + * @return true if completed, false otherwise + * @throws Exception if error + */ + private boolean performWork (Trx trx) throws Exception + { + log.info (m_node + " [" + trx.getTrxName() + "]"); + m_postImmediate = null; + m_docStatus = null; + if (m_node.getPriority() != 0) // overwrite priority if defined + setPriority(m_node.getPriority()); + String action = m_node.getAction(); + + /****** Sleep (Start/End) ******/ + if (MWFNode.ACTION_WaitSleep.equals(action)) + { + log.fine("Sleep:WaitTime=" + m_node.getWaitTime()); + if (m_node.getWaitingTime() == 0) + return true; // done + Calendar cal = Calendar.getInstance(); + cal.add(m_node.getDurationCalendarField(), m_node.getWaitTime()); + setEndWaitTime(new Timestamp(cal.getTimeInMillis())); + return false; // not done + } + + /****** Document Action ******/ + else if (MWFNode.ACTION_DocumentAction.equals(action)) + { + log.fine("DocumentAction=" + m_node.getDocAction()); + getPO(trx); + if (m_po == null) + throw new Exception("Persistent Object not found - AD_Table_ID=" + + getAD_Table_ID() + ", Record_ID=" + getRecord_ID()); + m_po.set_TrxName(trx.getTrxName()); + boolean success = false; + String processMsg = null; + DocAction doc = null; + if (m_po instanceof DocAction) + { + doc = (DocAction)m_po; + // + success = doc.processIt (m_node.getDocAction()); // ** Do the work + setTextMsg(doc.getSummary()); + processMsg = doc.getProcessMsg(); + m_docStatus = doc.getDocStatus(); + // Post Immediate + if (success && DocAction.ACTION_Complete.equals(m_node.getDocAction())) + { + MClient client = MClient.get(doc.getCtx(), doc.getAD_Client_ID()); + if (client.isPostImmediate()) + m_postImmediate = doc; + } + // + if (m_process != null) + m_process.setProcessMsg(processMsg); + } + else + throw new IllegalStateException("Persistent Object not DocAction - " + + m_po.getClass().getName() + + " - AD_Table_ID=" + getAD_Table_ID() + ", Record_ID=" + getRecord_ID()); + // + if (!m_po.save()) + { + success = false; + processMsg = "SaveError"; + } + if (!success) + { + if (processMsg == null || processMsg.length() == 0) + { + processMsg = "PerformWork Error - " + m_node.toStringX(); + if (doc != null) // problem: status will be rolled back + processMsg += " - DocStatus=" + doc.getDocStatus(); + } + throw new Exception(processMsg); + } + return success; + } // DocumentAction + + /****** Report ******/ + else if (MWFNode.ACTION_AppsReport.equals(action)) + { + log.fine("Report:AD_Process_ID=" + m_node.getAD_Process_ID()); + // Process + MProcess process = MProcess.get(getCtx(), m_node.getAD_Process_ID()); + if (!process.isReport() || process.getAD_ReportView_ID() == 0) + throw new IllegalStateException("Not a Report AD_Process_ID=" + m_node.getAD_Process_ID()); + // + ProcessInfo pi = new ProcessInfo (m_node.getName(true), m_node.getAD_Process_ID(), + getAD_Table_ID(), getRecord_ID()); + pi.setAD_User_ID(getAD_User_ID()); + pi.setAD_Client_ID(getAD_Client_ID()); + MPInstance pInstance = new MPInstance(process, getRecord_ID()); + fillParameter(pInstance, trx); + pi.setAD_PInstance_ID(pInstance.getAD_PInstance_ID()); + // Report + ReportEngine re = ReportEngine.get(getCtx(), pi); + if (re == null) + throw new IllegalStateException("Cannot create Report AD_Process_ID=" + m_node.getAD_Process_ID()); + File report = re.getPDF(); + // Notice + int AD_Message_ID = 753; // HARDCODED WorkflowResult + MNote note = new MNote(getCtx(), AD_Message_ID, getAD_User_ID(), trx.getTrxName()); + note.setTextMsg(m_node.getName(true)); + note.setDescription(m_node.getDescription(true)); + note.setRecord(getAD_Table_ID(), getRecord_ID()); + note.save(); + // Attachment + MAttachment attachment = new MAttachment (getCtx(), MNote.Table_ID, note.getAD_Note_ID(), get_TrxName()); + attachment.addEntry(report); + attachment.setTextMsg(m_node.getName(true)); + attachment.save(); + return true; + } + + /****** Process ******/ + else if (MWFNode.ACTION_AppsProcess.equals(action)) + { + log.fine("Process:AD_Process_ID=" + m_node.getAD_Process_ID()); + // Process + MProcess process = MProcess.get(getCtx(), m_node.getAD_Process_ID()); + MPInstance pInstance = new MPInstance(process, getRecord_ID()); + fillParameter(pInstance, trx); + // + ProcessInfo pi = new ProcessInfo (m_node.getName(true), m_node.getAD_Process_ID(), + getAD_Table_ID(), getRecord_ID()); + pi.setAD_User_ID(getAD_User_ID()); + pi.setAD_Client_ID(getAD_Client_ID()); + pi.setAD_PInstance_ID(pInstance.getAD_PInstance_ID()); + return process.processIt(pi, trx); + } + + /****** TODO Start Task ******/ + else if (MWFNode.ACTION_AppsTask.equals(action)) + { + log.warning ("Task:AD_Task_ID=" + m_node.getAD_Task_ID()); + } + + /****** EMail ******/ + else if (MWFNode.ACTION_EMail.equals(action)) + { + log.fine ("EMail:EMailRecipient=" + m_node.getEMailRecipient()); + getPO(trx); + if (m_po == null) + throw new Exception("Persistent Object not found - AD_Table_ID=" + + getAD_Table_ID() + ", Record_ID=" + getRecord_ID()); + if (m_po instanceof DocAction) + { + m_emails = new ArrayList(); + sendEMail(); + setTextMsg(m_emails.toString()); + } + return true; // done + } // EMail + + /****** Set Variable ******/ + else if (MWFNode.ACTION_SetVariable.equals(action)) + { + String value = m_node.getAttributeValue(); + log.fine("SetVariable:AD_Column_ID=" + m_node.getAD_Column_ID() + + " to " + value); + MColumn column = m_node.getColumn(); + int dt = column.getAD_Reference_ID(); + return setVariable (value, dt, null); + } // SetVariable + + /****** TODO Start WF Instance ******/ + else if (MWFNode.ACTION_SubWorkflow.equals(action)) + { + log.warning ("Workflow:AD_Workflow_ID=" + m_node.getAD_Workflow_ID()); + } + + /****** User Choice ******/ + else if (MWFNode.ACTION_UserChoice.equals(action)) + { + log.fine("UserChoice:AD_Column_ID=" + m_node.getAD_Column_ID()); + // Approval + if (m_node.isUserApproval() + && getPO() instanceof DocAction) + { + DocAction doc = (DocAction)m_po; + boolean autoApproval = false; + // Approval Hierarchy + if (isInvoker()) + { + // Set Approver + int startAD_User_ID = getAD_User_ID(); + if (startAD_User_ID == 0) + startAD_User_ID = doc.getDoc_User_ID(); + int nextAD_User_ID = getApprovalUser(startAD_User_ID, + doc.getC_Currency_ID(), doc.getApprovalAmt(), + doc.getAD_Org_ID(), + startAD_User_ID == doc.getDoc_User_ID()); // own doc + // same user = approved + autoApproval = startAD_User_ID == nextAD_User_ID; + if (!autoApproval) + setAD_User_ID(nextAD_User_ID); + } + else // fixed Approver + { + MWFResponsible resp = getResponsible(); + autoApproval = resp.getAD_User_ID() == getAD_User_ID(); + if (!autoApproval && resp.getAD_User_ID() != 0) + setAD_User_ID(resp.getAD_User_ID()); + } + if (autoApproval + && doc.processIt(DocAction.ACTION_Approve) + && doc.save()) + return true; // done + } // approval + return false; // wait for user + } + /****** User Workbench ******/ + else if (MWFNode.ACTION_UserWorkbench.equals(action)) + { + log.fine("Workbench:?"); + return false; + } + /****** User Form ******/ + else if (MWFNode.ACTION_UserForm.equals(action)) + { + log.fine("Form:AD_Form_ID=" + m_node.getAD_Form_ID()); + return false; + } + /****** User Window ******/ + else if (MWFNode.ACTION_UserWindow.equals(action)) + { + log.fine("Window:AD_Window_ID=" + m_node.getAD_Window_ID()); + return false; + } + // + throw new IllegalArgumentException("Invalid Action (Not Implemented) =" + action); + } // performWork + + /** + * Set Variable + * @param value new Value + * @param displayType display type + * @param textMsg optional Message + * @return true if set + * @throws Exception if error + */ + private boolean setVariable(String value, int displayType, String textMsg) throws Exception + { + m_newValue = null; + getPO(); + if (m_po == null) + throw new Exception("Persistent Object not found - AD_Table_ID=" + + getAD_Table_ID() + ", Record_ID=" + getRecord_ID()); + // Set Value + Object dbValue = null; + if (value == null) + ; + else if (displayType == DisplayType.YesNo) + dbValue = new Boolean("Y".equals(value)); + else if (DisplayType.isNumeric(displayType)) + dbValue = new BigDecimal (value); + else + dbValue = value; + m_po.set_ValueOfColumn(getNode().getAD_Column_ID(), dbValue); + m_po.save(); + if (!dbValue.equals(m_po.get_ValueOfColumn(getNode().getAD_Column_ID()))) + throw new Exception("Persistent Object not updated - AD_Table_ID=" + + getAD_Table_ID() + ", Record_ID=" + getRecord_ID() + + " - Should=" + value + ", Is=" + m_po.get_ValueOfColumn(m_node.getAD_Column_ID())); + // Info + String msg = getNode().getAttributeName() + "=" + value; + if (textMsg != null && textMsg.length() > 0) + msg += " - " + textMsg; + setTextMsg (msg); + m_newValue = value; + return true; + } // setVariable + + /** + * Set User Choice + * @param AD_User_ID user + * @param value new Value + * @param displayType display type + * @param textMsg optional Message + * @return true if set + * @throws Exception if error + */ + public boolean setUserChoice (int AD_User_ID, String value, int displayType, + String textMsg) throws Exception + { + // Check if user approves own document when a role is reponsible + if (getNode().isUserApproval() && getPO() instanceof DocAction) + { + DocAction doc = (DocAction)m_po; + MUser user = new MUser (getCtx(), AD_User_ID, null); + MRole[] roles = user.getRoles(m_po.getAD_Org_ID()); + boolean canApproveOwnDoc = false; + for (int r = 0; r < roles.length; r++) + { + if (roles[r].isCanApproveOwnDoc()) + { + canApproveOwnDoc = true; + break; + } // found a role which allows to approve own document + } + if (!canApproveOwnDoc) + { + String info = user.getName() + " cannot approve own document " + doc; + addTextMsg(info); + log.fine(info); + return false; // ignore + } + } + + setWFState (StateEngine.STATE_Running); + setAD_User_ID(AD_User_ID); + boolean ok = setVariable (value, displayType, textMsg); + if (!ok) + return false; + + String newState = StateEngine.STATE_Completed; + // Approval + if (getNode().isUserApproval() && getPO() instanceof DocAction) + { + DocAction doc = (DocAction)m_po; + try + { + // Not pproved + if (!"Y".equals(value)) + { + newState = StateEngine.STATE_Aborted; + if (!(doc.processIt (DocAction.ACTION_Reject))) + setTextMsg ("Cannot Reject - Document Status: " + doc.getDocStatus()); + } + else + { + if (isInvoker()) + { + int startAD_User_ID = getAD_User_ID(); + if (startAD_User_ID == 0) + startAD_User_ID = doc.getDoc_User_ID(); + int nextAD_User_ID = getApprovalUser(startAD_User_ID, + doc.getC_Currency_ID(), doc.getApprovalAmt(), + doc.getAD_Org_ID(), + startAD_User_ID == doc.getDoc_User_ID()); // own doc + // No Approver + if (nextAD_User_ID <= 0) + { + newState = StateEngine.STATE_Aborted; + setTextMsg ("Cannot Approve - No Approver"); + doc.processIt (DocAction.ACTION_Reject); + } + else if (startAD_User_ID != nextAD_User_ID) + { + forwardTo(nextAD_User_ID, "Next Approver"); + newState = StateEngine.STATE_Suspended; + } + else // Approve + { + if (!(doc.processIt (DocAction.ACTION_Approve))) + { + newState = StateEngine.STATE_Aborted; + setTextMsg ("Cannot Approve - Document Status: " + doc.getDocStatus()); + } + } + } + // No Invoker - Approve + else if (!(doc.processIt (DocAction.ACTION_Approve))) + { + newState = StateEngine.STATE_Aborted; + setTextMsg ("Cannot Approve - Document Status: " + doc.getDocStatus()); + } + } + doc.save(); + } + catch (Exception e) + { + newState = StateEngine.STATE_Terminated; + setTextMsg ("User Choice: " + e.toString()); + log.log(Level.WARNING, "", e); + } + // Send Approval Notification + if (newState.equals(StateEngine.STATE_Aborted)) + { + MClient client = MClient.get(getCtx(), doc.getAD_Client_ID()); + client.sendEMail(doc.getDoc_User_ID(), + doc.getDocumentInfo() + ": " + Msg.getMsg(getCtx(), "NotApproved"), + doc.getSummary() + + "\n" + doc.getProcessMsg() + + "\n" + getTextMsg(), + doc.createPDF()); + } + } + setWFState (newState); + return ok; + } // setUserChoice + + /** + * Forward To + * @param AD_User_ID user + * @param textMsg text message + * @return true if forwarded + */ + public boolean forwardTo (int AD_User_ID, String textMsg) + { + if (AD_User_ID == getAD_User_ID()) + { + log.log(Level.WARNING, "Same User - AD_User_ID=" + AD_User_ID); + return false; + } + // + MUser oldUser = MUser.get(getCtx(), getAD_User_ID()); + MUser user = MUser.get(getCtx(), AD_User_ID); + if (user == null || user.get_ID() == 0) + { + log.log(Level.WARNING, "Does not exist - AD_User_ID=" + AD_User_ID); + return false; + } + // Update + setAD_User_ID (user.getAD_User_ID()); + setTextMsg(textMsg); + save(); + // Close up Old Event + getEventAudit(); + m_audit.setAD_User_ID(oldUser.getAD_User_ID()); + m_audit.setTextMsg(getTextMsg()); + m_audit.setAttributeName("AD_User_ID"); + m_audit.setOldValue(oldUser.getName()+ "("+oldUser.getAD_User_ID()+")"); + m_audit.setNewValue(user.getName()+ "("+user.getAD_User_ID()+")"); + // + m_audit.setWFState(getWFState()); + m_audit.setEventType(MWFEventAudit.EVENTTYPE_StateChanged); + long ms = System.currentTimeMillis() - m_audit.getCreated().getTime(); + m_audit.setElapsedTimeMS(new BigDecimal(ms)); + m_audit.save(); + // Create new one + m_audit = new MWFEventAudit(this); + m_audit.save(); + return true; + } // forwardTo + + /** + * Set User Confirmation + * @param AD_User_ID user + * @param textMsg optional message + */ + public void setUserConfirmation (int AD_User_ID, String textMsg) + { + log.fine(textMsg); + setWFState (StateEngine.STATE_Running); + setAD_User_ID(AD_User_ID); + if (textMsg != null) + setTextMsg (textMsg); + setWFState (StateEngine.STATE_Completed); + } // setUserConfirmation + + + /** + * Fill Parameter + * @param pInstance process instance + * @param trx transaction + */ + private void fillParameter(MPInstance pInstance, Trx trx) + { + getPO(trx); + // + MWFNodePara[] nParams = m_node.getParameters(); + MPInstancePara[] iParams = pInstance.getParameters(); + for (int pi = 0; pi < iParams.length; pi++) + { + MPInstancePara iPara = iParams[pi]; + for (int np = 0; np < nParams.length; np++) + { + MWFNodePara nPara = nParams[np]; + if (iPara.getParameterName().equals(nPara.getAttributeName())) + { + String variableName = nPara.getAttributeValue(); + log.fine(nPara.getAttributeName() + + " = " + variableName); + // Value - Constant/Variable + Object value = variableName; + if (variableName == null + || (variableName != null && variableName.length() == 0)) + value = null; + else if (variableName.indexOf("@") != -1 && m_po != null) // we have a variable + { + // Strip + int index = variableName.indexOf("@"); + String columnName = variableName.substring(index+1); + index = columnName.indexOf("@"); + if (index == -1) + { + log.warning(nPara.getAttributeName() + + " - cannot evaluate=" + variableName); + break; + } + columnName = columnName.substring(0, index); + index = m_po.get_ColumnIndex(columnName); + if (index != -1) + { + value = m_po.get_Value(index); + } + else // not a column + { + // try Env + String env = Env.getContext(getCtx(), columnName); + if (env.length() == 0) + { + log.warning(nPara.getAttributeName() + + " - not column nor environment =" + columnName + + "(" + variableName + ")"); + break; + } + else + value = env; + } + } // @variable@ + + // No Value + if (value == null) + { + if (nPara.isMandatory()) + log.warning(nPara.getAttributeName() + + " - empty - mandatory!"); + else + log.fine(nPara.getAttributeName() + + " - empty"); + break; + } + + // Convert to Type + try + { + if (DisplayType.isNumeric(nPara.getDisplayType()) + || DisplayType.isID(nPara.getDisplayType())) + { + BigDecimal bd = null; + if (value instanceof BigDecimal) + bd = (BigDecimal)value; + else if (value instanceof Integer) + bd = new BigDecimal (((Integer)value).intValue()); + else + bd = new BigDecimal (value.toString()); + iPara.setP_Number(bd); + log.fine(nPara.getAttributeName() + + " = " + variableName + " (=" + bd + "=)"); + } + else if (DisplayType.isDate(nPara.getDisplayType())) + { + Timestamp ts = null; + if (value instanceof Timestamp) + ts = (Timestamp)value; + else + ts = Timestamp.valueOf(value.toString()); + iPara.setP_Date(ts); + log.fine(nPara.getAttributeName() + + " = " + variableName + " (=" + ts + "=)"); + } + else + { + iPara.setP_String(value.toString()); + log.fine(nPara.getAttributeName() + + " = " + variableName + + " (=" + value + "=) " + value.getClass().getName()); + } + if (!iPara.save()) + log.warning("Not Saved - " + nPara.getAttributeName()); + } + catch (Exception e) + { + log.warning(nPara.getAttributeName() + + " = " + variableName + " (" + value + + ") " + value.getClass().getName() + + " - " + e.getLocalizedMessage()); + } + break; + } + } // node parameter loop + } // instance parameter loop + } // fillParameter + + /** + * Post Immediate + */ + private void postImmediate() + { + if (CConnection.get().isAppsServerOK(false)) + { + try + { + Server server = CConnection.get().getServer(); + if (server != null) + { + String error = server.postImmediate(Env.getCtx(), + m_postImmediate.getAD_Client_ID(), + m_postImmediate.get_Table_ID(), m_postImmediate.get_ID(), + true, null); + m_postImmediate.get_Logger().config("Server: " + error == null ? "OK" : error); + return; + } + else + m_postImmediate.get_Logger().config("NoAppsServer"); + } + catch (RemoteException e) + { + m_postImmediate.get_Logger().config("(RE) " + e.getMessage()); + } + catch (Exception e) + { + m_postImmediate.get_Logger().config("(ex) " + e.getMessage()); + } + } + } // PostImmediate + + + /********************************* + * Send EMail + */ + private void sendEMail() + { + DocAction doc = (DocAction)m_po; + MMailText text = new MMailText (getCtx(), m_node.getR_MailText_ID(), null); + text.setPO(m_po, true); + // + String subject = doc.getDocumentInfo() + + ": " + text.getMailHeader(); + String message = text.getMailText(true) + + "\n-----\n" + doc.getDocumentInfo() + + "\n" + doc.getSummary(); + File pdf = doc.createPDF(); + // + MClient client = MClient.get(doc.getCtx(), doc.getAD_Client_ID()); + + // Explicit EMail + sendEMail(client, 0, m_node.getEMail(), subject, message, pdf); + // Recipient Type + String recipient = m_node.getEMailRecipient(); + // email to document user + if (recipient == null || recipient.length() == 0) + sendEMail(client, doc.getDoc_User_ID(), null, subject, message, pdf); + else if (recipient.equals(MWFNode.EMAILRECIPIENT_DocumentBusinessPartner)) + { + int index = m_po.get_ColumnIndex("AD_User_ID"); + if (index > 0) + { + Object oo = m_po.get_Value(index); + if (oo instanceof Integer) + { + int AD_User_ID = ((Integer)oo).intValue(); + if (AD_User_ID != 0) + sendEMail(client, AD_User_ID, null, subject, message, pdf); + else + log.fine("No User in Document"); + } + else + log.fine("Empty User in Document"); + } + else + log.fine("No User Field in Document"); + } + else if (recipient.equals(MWFNode.EMAILRECIPIENT_DocumentOwner)) + sendEMail(client, doc.getDoc_User_ID(), null, subject, message, pdf); + else if (recipient.equals(MWFNode.EMAILRECIPIENT_WFResponsible)) + { + MWFResponsible resp = getResponsible(); + if (resp.isInvoker()) + sendEMail(client, doc.getDoc_User_ID(), null, subject, message, pdf); + else if (resp.isHuman()) + sendEMail(client, resp.getAD_User_ID(), null, subject, message, pdf); + else if (resp.isRole()) + { + MRole role = resp.getRole(); + if (role != null) + { + MUser[] users = MUser.getWithRole(role); + for (int i = 0; i < users.length; i++) + sendEMail(client, users[i].getAD_User_ID(), null, subject, message, pdf); + } + } + else if (resp.isOrganization()) + { + MOrgInfo org = MOrgInfo.get(getCtx(), m_po.getAD_Org_ID()); + if (org.getSupervisor_ID() == 0) + log.fine("No Supervisor for AD_Org_ID=" + m_po.getAD_Org_ID()); + else + sendEMail(client, org.getSupervisor_ID(), null, subject, message, pdf); + } + } + } // sendEMail + + /** + * Send actual EMail + * @param client client + * @param AD_User_ID user + * @param email email string + * @param subject subject + * @param message message + * @param pdf attachment + */ + private void sendEMail (MClient client, int AD_User_ID, String email, + String subject, String message, File pdf) + { + if (AD_User_ID != 0) + { + MUser user = MUser.get(getCtx(), AD_User_ID); + email = user.getEMail(); + if (email != null && email.length() > 0) + { + email = email.trim(); + if (!m_emails.contains(email)) + { + client.sendEMail(null, user, subject, message, pdf); + m_emails.add(email); + } + } + else + log.info("No EMail for User " + user.getName()); + } + else if (email != null && email.length() > 0) + { + // Just one + if (email.indexOf(";") == -1) + { + email = email.trim(); + if (!m_emails.contains(email)) + { + client.sendEMail(email, subject, message, pdf); + m_emails.add(email); + } + return; + } + // Multiple EMail + StringTokenizer st = new StringTokenizer(email, ";"); + while (st.hasMoreTokens()) + { + String email1 = st.nextToken().trim(); + if (email1.length() == 0) + continue; + if (!m_emails.contains(email1)) + { + client.sendEMail(email1, subject, message, pdf); + m_emails.add(email1); + } + } + } + } // sendEMail + + /************************************************************************** + * Get Process Activity (Event) History + * @return history + */ + public String getHistoryHTML() + { + SimpleDateFormat format = DisplayType.getDateFormat(DisplayType.DateTime); + StringBuffer sb = new StringBuffer(); + MWFEventAudit[] events = MWFEventAudit.get(getCtx(), getAD_WF_Process_ID()); + for (int i = 0; i < events.length; i++) + { + MWFEventAudit audit = events[i]; + // sb.append("

"); + sb.append("

"); + sb.append(format.format(audit.getCreated())) + .append(" ") + .append(getHTMLpart("b", audit.getNodeName())) + .append(": ") + .append(getHTMLpart(null, audit.getDescription())) + .append(getHTMLpart("i", audit.getTextMsg())); + sb.append("

"); + } + return sb.toString(); + } // getHistory + + /** + * Get HTML part + * @param tag HTML tag + * @param content content + * @return content + */ + private StringBuffer getHTMLpart (String tag, String content) + { + StringBuffer sb = new StringBuffer(); + if (content == null || content.length() == 0) + return sb; + if (tag != null && tag.length() > 0) + sb.append("<").append(tag).append(">"); + sb.append(content); + if (tag != null && tag.length() > 0) + sb.append(""); + return sb; + } // getHTMLpart + + + /************************************************************************** + * Does the underlying PO (!) object have a PDF Attachment + * @return true if there is a pdf attachment + */ + public boolean isPdfAttachment() + { + if (getPO() == null) + return false; + return m_po.isPdfAttachment(); + } // isPDFAttachment + + /** + * Get PDF Attachment of underlying PO (!) object + * @return pdf data or null + */ + public byte[] getPdfAttachment() + { + if (getPO() == null) + return null; + return m_po.getPdfAttachment(); + } // getPdfAttachment + + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MWFActivity["); + sb.append(get_ID()).append(",Node="); + if (m_node == null) + sb.append(getAD_WF_Node_ID()); + else + sb.append(m_node.getName()); + sb.append(",State=").append(getWFState()) + .append(",AD_User_ID=").append(getAD_User_ID()) + .append(",").append(getCreated()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * User String Representation. + * Suspended: Approve it (Joe) + * @return info + */ + public String toStringX () + { + StringBuffer sb = new StringBuffer(); + sb.append(getWFStateText()) + .append(": ").append(getNode().getName()); + if (getAD_User_ID() > 0) + { + MUser user = MUser.get(getCtx(), getAD_User_ID()); + sb.append(" (").append(user.getName()).append(")"); + } + return sb.toString(); + } // toStringX + +} // MWFActivity diff --git a/base/src/org/compiere/wf/MWFBlock.java b/base/src/org/compiere/wf/MWFBlock.java new file mode 100644 index 0000000000..0f0b08ab7a --- /dev/null +++ b/base/src/org/compiere/wf/MWFBlock.java @@ -0,0 +1,77 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.sql.*; +import java.util.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Work Flow Commitment Block + * + * @author Jorg Janke + * @version $Id: MWFBlock.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MWFBlock extends X_AD_WF_Block +{ + /** + * Get MWFBlock from Cache + * @param ctx context + * @param AD_WF_Block_ID id + * @return MWFBlock + */ + public static MWFBlock get (Properties ctx, int AD_WF_Block_ID) + { + Integer key = new Integer (AD_WF_Block_ID); + MWFBlock retValue = (MWFBlock) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MWFBlock (ctx, AD_WF_Block_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("AD_WF_Block", 20); + + + /** + * Standard Constructor + * @param ctx context + * @param AD_WF_Block_ID id + * @param trxName transaction + */ + public MWFBlock (Properties ctx, int AD_WF_Block_ID, String trxName) + { + super (ctx, AD_WF_Block_ID, trxName); + } // MWFBlock + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MWFBlock (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MWFBlock + +} // MWFBlock diff --git a/base/src/org/compiere/wf/MWFEventAudit.java b/base/src/org/compiere/wf/MWFEventAudit.java new file mode 100644 index 0000000000..97395946d1 --- /dev/null +++ b/base/src/org/compiere/wf/MWFEventAudit.java @@ -0,0 +1,167 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Workflow Event Audit + * + * @author Jorg Janke + * @version $Id: MWFEventAudit.java,v 1.3 2006/07/30 00:51:06 jjanke Exp $ + */ +public class MWFEventAudit extends X_AD_WF_EventAudit +{ + /** + * Get Event Audit for node + * @param ctx context + * @param AD_WF_Process_ID process + * @param AD_WF_Node_ID optional node + * @return event audit or null + */ + public static MWFEventAudit[] get (Properties ctx, int AD_WF_Process_ID, int AD_WF_Node_ID) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM AD_WF_EventAudit " + + "WHERE AD_WF_Process_ID=?"; + if (AD_WF_Node_ID > 0) + sql += " AND AD_WF_Node_ID=?"; + sql += " ORDER BY AD_WF_EventAudit_ID"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, AD_WF_Process_ID); + if (AD_WF_Node_ID > 0) + pstmt.setInt (2, AD_WF_Node_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MWFEventAudit (ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "get", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // + MWFEventAudit[] retValue = new MWFEventAudit[list.size()]; + list.toArray (retValue); + return retValue; + } // get + + /** + * Get Event Audit for node + * @param ctx context + * @param AD_WF_Process_ID process + * @return event audit or null + */ + public static MWFEventAudit[] get (Properties ctx, int AD_WF_Process_ID) + { + return get(ctx, AD_WF_Process_ID, 0); + } // get + + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MWFEventAudit.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param AD_WF_EventAudit_ID id + * @param trxName transaction + */ + public MWFEventAudit (Properties ctx, int AD_WF_EventAudit_ID, String trxName) + { + super (ctx, AD_WF_EventAudit_ID, trxName); + } // MWFEventAudit + + /** + * Load Cosntructors + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MWFEventAudit (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MWFEventAudit + + /** + * Activity Constructor + * @param activity activity + */ + public MWFEventAudit (MWFActivity activity) + { + super (activity.getCtx(), 0, activity.get_TrxName()); + setAD_WF_Process_ID (activity.getAD_WF_Process_ID()); + setAD_WF_Node_ID (activity.getAD_WF_Node_ID()); + setAD_Table_ID (activity.getAD_Table_ID()); + setRecord_ID (activity.getRecord_ID()); + // + setAD_WF_Responsible_ID (activity.getAD_WF_Responsible_ID()); + setAD_User_ID(activity.getAD_User_ID()); + // + setWFState (activity.getWFState()); + setEventType (EVENTTYPE_ProcessCreated); + setElapsedTimeMS (Env.ZERO); + // + MWFNode node = activity.getNode(); + if (node != null && node.get_ID() != 0) + { + String action = node.getAction(); + if (MWFNode.ACTION_SetVariable.equals(action) + || MWFNode.ACTION_UserChoice.equals(action)) + { + setAttributeName(node.getAttributeName()); + setOldValue(String.valueOf(activity.getAttributeValue())); + if (MWFNode.ACTION_SetVariable.equals(action)) + setNewValue(node.getAttributeValue()); + } + } + } // MWFEventAudit + + /** + * Get Node Name + * @return node name + */ + public String getNodeName() + { + MWFNode node = MWFNode.get(getCtx(), getAD_WF_Node_ID()); + if (node.get_ID() == 0) + return "?"; + return node.getName(true); + } // getNodeName + + +} // MWFEventAudit diff --git a/base/src/org/compiere/wf/MWFNextCondition.java b/base/src/org/compiere/wf/MWFNextCondition.java new file mode 100644 index 0000000000..784bdd56e9 --- /dev/null +++ b/base/src/org/compiere/wf/MWFNextCondition.java @@ -0,0 +1,237 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.sql.*; +import java.util.*; +import java.math.*; + +import org.compiere.model.*; + +/** + * Workflow Transition Condition + * + * @author Jorg Janke + * @version $Id: MWFNextCondition.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MWFNextCondition extends X_AD_WF_NextCondition +{ + /** + * Default Constructor + * @param ctx context + * @param id id + * @param trxName transaction + */ + public MWFNextCondition (Properties ctx, int id, String trxName) + { + super (ctx, id, trxName); + } // MWFNextCondition + + /** + * Load Cosntructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MWFNextCondition (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MWFNextCondition + + /** Numeric evaluation */ + private boolean m_numeric = true; + + /** + * Is Or Condition + * @return true if OR + */ + public boolean isOr() + { + return ANDOR_Or.equals(getAndOr()); + } // isOr + + /** + * Evaluate Condition + * @param activity activity + * @return true if true + */ + public boolean evaluate (MWFActivity activity) + { + if (getAD_Column_ID() == 0) + throw new IllegalStateException("No Column defined - " + this); + + PO po = activity.getPO(); + if (po == null || po.get_ID() == 0) + throw new IllegalStateException("Could not evaluate " + po + " - " + this); + // + Object valueObj = po.get_ValueOfColumn(getAD_Column_ID()); + if (valueObj == null) + valueObj = ""; + String value1 = getValue(); + if (value1 == null) + value1 = ""; + String value2 = getValue2(); + if (value2 == null) + value2 = ""; + + String resultStr = "PO:{" + valueObj + "} " + getOperation() + " Condition:{" + value1 + "}"; + if (getOperation().equals(OPERATION_Sql)) + throw new IllegalArgumentException("SQL Operator not implemented yet: " + resultStr); + if (getOperation().equals(OPERATION_X)) + resultStr += "{" + value2 + "}"; + + boolean result = false; + if (valueObj instanceof Number) + result = compareNumber ((Number)valueObj, value1, value2); + else + result = compareString(valueObj, value1, value2); + // + log.fine(resultStr + " -> " + result + + (m_numeric ? " (#)" : " ($)")); + return result; + } // evaluate + + /** + * Compare Number + * @param valueObj comparator + * @param value1 first value + * @param value2 second value + * @return true if operation + */ + private boolean compareNumber (Number valueObj, String value1, String value2) + { + BigDecimal valueObjB = null; + BigDecimal value1B = null; + BigDecimal value2B = null; + try + { + if (valueObj instanceof BigDecimal) + valueObjB = (BigDecimal)valueObj; + else if (valueObj instanceof Integer) + valueObjB = new BigDecimal (((Integer)valueObj).intValue()); + else + valueObjB = new BigDecimal (String.valueOf(valueObj)); + } + catch (Exception e) + { + log.fine("compareNumber - valueObj=" + valueObj + " - " + e.toString()); + return compareString(valueObj, value1, value2); + } + try + { + value1B = new BigDecimal (value1); + } + catch (Exception e) + { + log.fine("compareNumber - value1=" + value1 + " - " + e.toString()); + return compareString(valueObj, value1, value2); + } + + String op = getOperation(); + if (OPERATION_Eq.equals(op)) + return valueObjB.compareTo(value1B) == 0; + else if (OPERATION_Gt.equals(op)) + return valueObjB.compareTo(value1B) > 0; + else if (OPERATION_GtEq.equals(op)) + return valueObjB.compareTo(value1B) >= 0; + else if (OPERATION_Le.equals(op)) + return valueObjB.compareTo(value1B) < 0; + else if (OPERATION_LeEq.equals(op)) + return valueObjB.compareTo(value1B) <= 0; + else if (OPERATION_Like.equals(op)) + return valueObjB.compareTo(value1B) == 0; + else if (OPERATION_NotEq.equals(op)) + return valueObjB.compareTo(value1B) != 0; + // + else if (OPERATION_Sql.equals(op)) + throw new IllegalArgumentException("SQL not Implemented"); + // + else if (OPERATION_X.equals(op)) + { + if (valueObjB.compareTo(value1B) < 0) + return false; + // To + try + { + value2B = new BigDecimal (String.valueOf(value2)); + return valueObjB.compareTo(value2B) <= 0; + } + catch (Exception e) + { + log.fine("compareNumber - value2=" + value2 + " - " + e.toString()); + return false; + } + } + // + throw new IllegalArgumentException("Unknown Operation=" + op); + } // compareNumber + + /** + * Compare String + * @param valueObj comparator + * @param value1S first value + * @param value2S second value + * @return true if operation + */ + private boolean compareString (Object valueObj, String value1S, String value2S) + { + m_numeric = false; + String valueObjS = String.valueOf(valueObj); + // + String op = getOperation(); + if (OPERATION_Eq.equals(op)) + return valueObjS.compareTo(value1S) == 0; + else if (OPERATION_Gt.equals(op)) + return valueObjS.compareTo(value1S) > 0; + else if (OPERATION_GtEq.equals(op)) + return valueObjS.compareTo(value1S) >= 0; + else if (OPERATION_Le.equals(op)) + return valueObjS.compareTo(value1S) < 0; + else if (OPERATION_LeEq.equals(op)) + return valueObjS.compareTo(value1S) <= 0; + else if (OPERATION_Like.equals(op)) + return valueObjS.compareTo(value1S) == 0; + else if (OPERATION_NotEq.equals(op)) + return valueObjS.compareTo(value1S) != 0; + // + else if (OPERATION_Sql.equals(op)) + throw new IllegalArgumentException("SQL not Implemented"); + // + else if (OPERATION_X.equals(op)) + { + if (valueObjS.compareTo(value1S) < 0) + return false; + // To + return valueObjS.compareTo(value2S) <= 0; + } + // + throw new IllegalArgumentException("Unknown Operation=" + op); + } // compareString + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MWFNextCondition["); + sb.append(get_ID()).append(",SeqNo=").append(getSeqNo()) + .append ("]"); + return sb.toString (); + } // toString + +} // MWFNextCondition diff --git a/base/src/org/compiere/wf/MWFNode.java b/base/src/org/compiere/wf/MWFNode.java new file mode 100644 index 0000000000..ef70129c84 --- /dev/null +++ b/base/src/org/compiere/wf/MWFNode.java @@ -0,0 +1,631 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.awt.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Workflow Node Model + * + * @author Jorg Janke + * @version $Id: MWFNode.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MWFNode extends X_AD_WF_Node +{ + /** + * Get WF Node from Cache + * @param ctx context + * @param AD_WF_Node_ID id + * @return MWFNode + */ + public static MWFNode get (Properties ctx, int AD_WF_Node_ID) + { + Integer key = new Integer (AD_WF_Node_ID); + MWFNode retValue = (MWFNode) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MWFNode (ctx, AD_WF_Node_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache ("AD_WF_Node", 50); + + + /************************************************************************** + * Standard Constructor - save to cache + * @param ctx context + * @param AD_WF_Node_ID id + * @param trxName transaction + */ + public MWFNode (Properties ctx, int AD_WF_Node_ID, String trxName) + { + super (ctx, AD_WF_Node_ID, trxName); + if (AD_WF_Node_ID == 0) + { + // setAD_WF_Node_ID (0); + // setAD_Workflow_ID (0); + // setValue (null); + // setName (null); + setAction (ACTION_WaitSleep); + setCost (Env.ZERO); + setDuration (0); + setEntityType (ENTITYTYPE_UserMaintained); // U + setIsCentrallyMaintained (true); // Y + setJoinElement (JOINELEMENT_XOR); // X + setLimit (0); + setSplitElement (SPLITELEMENT_XOR); // X + setWaitingTime (0); + setXPosition (0); + setYPosition (0); + } + // Save to Cache + if (get_ID() != 0) + s_cache.put (new Integer(getAD_WF_Node_ID()), this); + } // MWFNode + + /** + * Parent Constructor + * @param wf workflow (parent) + * @param Value value + * @param Name name + */ + public MWFNode (MWorkflow wf, String Value, String Name) + { + this (wf.getCtx(), 0, wf.get_TrxName()); + setClientOrg(wf); + setAD_Workflow_ID (wf.getAD_Workflow_ID()); + setValue (Value); + setName (Name); + m_durationBaseMS = wf.getDurationBaseSec() * 1000; + } // MWFNode + + /** + * Load Constructor - save to cache + * @param ctx context + * @param rs result set to load info from + * @param trxName transaction + */ + public MWFNode (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + loadNext(); + loadTrl(); + // Save to Cache + s_cache.put (new Integer(getAD_WF_Node_ID()), this); + } // MWFNode + + + + /** Next Modes */ + private ArrayList m_next = new ArrayList(); + /** Translated Name */ + private String m_name_trl = null; + /** Translated Description */ + private String m_description_trl = null; + /** Translated Help */ + private String m_help_trl = null; + /** Translation Flag */ + private boolean m_translated = false; + /** Column */ + private MColumn m_column = null; + /** Process Parameters */ + private MWFNodePara[] m_paras = null; + /** Duration Base MS */ + private long m_durationBaseMS = -1; + + /** + * Set Client Org + * @param AD_Client_ID client + * @param AD_Org_ID org + */ + public void setClientOrg (int AD_Client_ID, int AD_Org_ID) + { + super.setClientOrg (AD_Client_ID, AD_Org_ID); + } // setClientOrg + + /** + * Load Next + */ + private void loadNext() + { + String sql = "SELECT * FROM AD_WF_NodeNext WHERE AD_WF_Node_ID=? AND IsActive='Y' ORDER BY SeqNo"; + boolean splitAnd = SPLITELEMENT_AND.equals(getSplitElement()); + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, get_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + MWFNodeNext next = new MWFNodeNext (getCtx(), rs, get_TrxName()); + next.setFromSplitAnd(splitAnd); + m_next.add(next); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + log.fine("#" + m_next.size()); + } // loadNext + + /** + * Load Translation + */ + private void loadTrl() + { + if (Env.isBaseLanguage(getCtx(), "AD_Workflow") || get_ID() == 0) + return; + String sql = "SELECT Name, Description, Help FROM AD_WF_Node_Trl WHERE AD_WF_Node_ID=? AND AD_Language=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, get_ID()); + pstmt.setString(2, Env.getAD_Language(getCtx())); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + m_name_trl = rs.getString(1); + m_description_trl = rs.getString(2); + m_help_trl = rs.getString(3); + m_translated = true; + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + log.fine("Trl=" + m_translated); + } // loadTrl + + /** + * Get Number of Next Nodes + * @return number of next nodes + */ + public int getNextNodeCount() + { + return m_next.size(); + } // getNextNodeCount + + /** + * Get the transitions + * @param AD_Client_ID for client + * @return array of next nodes + */ + public MWFNodeNext[] getTransitions(int AD_Client_ID) + { + ArrayList list = new ArrayList(); + for (int i = 0; i < m_next.size(); i++) + { + MWFNodeNext next = m_next.get(i); + if (next.getAD_Client_ID() == 0 || next.getAD_Client_ID() == AD_Client_ID) + list.add(next); + } + MWFNodeNext[] retValue = new MWFNodeNext [list.size()]; + list.toArray(retValue); + return retValue; + } // getNextNodes + + + /************************************************************************** + * Get Name + * @param translated translated + * @return Name + */ + public String getName(boolean translated) + { + if (translated && m_translated) + return m_name_trl; + return getName(); + } // getName + + /** + * Get Description + * @param translated translated + * @return Description + */ + public String getDescription(boolean translated) + { + if (translated && m_translated) + return m_description_trl; + return getDescription(); + } // getDescription + + /** + * Get Help + * @param translated translated + * @return Name + */ + public String getHelp(boolean translated) + { + if (translated && m_translated) + return m_help_trl; + return getHelp(); + } // getHelp + + /** + * Set Position + * @param position point + */ + public void setPosition (Point position) + { + setPosition(position.x, position.y); + } // setPosition + + /** + * Set Position + * @param x x + * @param y y + */ + public void setPosition (int x, int y) + { + setXPosition(x); + setYPosition(y); + } // setPosition + + /** + * Get Position + * @return position point + */ + public Point getPosition () + { + return new Point (getXPosition(), getYPosition()); + } // getPosition + + /** + * Get Action Info + * @return info + */ + public String getActionInfo() + { + String action = getAction(); + if (ACTION_AppsProcess.equals(action)) + return "Process:AD_Process_ID=" + getAD_Process_ID(); + else if (ACTION_DocumentAction.equals(action)) + return "DocumentAction=" + getDocAction(); + else if (ACTION_AppsReport.equals(action)) + return "Report:AD_Process_ID=" + getAD_Process_ID(); + else if (ACTION_AppsTask.equals(action)) + return "Task:AD_Task_ID=" + getAD_Task_ID(); + else if (ACTION_SetVariable.equals(action)) + return "SetVariable:AD_Column_ID=" + getAD_Column_ID(); + else if (ACTION_SubWorkflow.equals(action)) + return "Workflow:AD_Workflow_ID=" + getAD_Workflow_ID(); + else if (ACTION_UserChoice.equals(action)) + return "UserChoice:AD_Column_ID=" + getAD_Column_ID(); + else if (ACTION_UserWorkbench.equals(action)) + return "Workbench:?"; + else if (ACTION_UserForm.equals(action)) + return "Form:AD_Form_ID=" + getAD_Form_ID(); + else if (ACTION_UserWindow.equals(action)) + return "Window:AD_Window_ID=" + getAD_Window_ID(); + else if (ACTION_WaitSleep.equals(action)) + return "Sleep:WaitTime=" + getWaitTime(); + return "??"; + } // getActionInfo + + + /** + * Get Attribute Name + * @see org.compiere.model.X_AD_WF_Node#getAttributeName() + * @return Attribute Name + */ + public String getAttributeName () + { + if (getAD_Column_ID() == 0) + return super.getAttributeName(); + // We have a column + String attribute = super.getAttributeName(); + if (attribute != null && attribute.length() > 0) + return attribute; + setAttributeName(getColumn().getColumnName()); + return super.getAttributeName (); + } // getAttributeName + + + /** + * Get Column + * @return column if valid + */ + public MColumn getColumn() + { + if (getAD_Column_ID() == 0) + return null; + if (m_column == null) + m_column = MColumn.get(getCtx(), getAD_Column_ID()); + return m_column; + } // getColumn + + /** + * Is this an Approval setp? + * @return true if User Approval + */ + public boolean isUserApproval() + { + if (!ACTION_UserChoice.equals(getAction())) + return false; + return getColumn() != null + && "IsApproved".equals(getColumn().getColumnName()); + } // isApproval + + /** + * Is this a User Choice step? + * @return true if User Choice + */ + public boolean isUserChoice() + { + return ACTION_UserChoice.equals(getAction()); + } // isUserChoice + + /** + * Is this a Manual user step? + * @return true if Window/Form/Workbench + */ + public boolean isUserManual() + { + if (ACTION_UserForm.equals(getAction()) + || ACTION_UserWindow.equals(getAction()) + || ACTION_UserWorkbench.equals(getAction())) + return true; + return false; + } // isUserManual + + + /** + * Get Duration in ms + * @return duration in ms + */ + public long getDurationMS () + { + long duration = super.getDuration (); + if (duration == 0) + return 0; + if (m_durationBaseMS == -1) + m_durationBaseMS = getWorkflow().getDurationBaseSec() * 1000; + return duration * m_durationBaseMS; + } // getDurationMS + + /** + * Get Duration Limit in ms + * @return duration limit in ms + */ + public long getLimitMS () + { + long limit = super.getLimit (); + if (limit == 0) + return 0; + if (m_durationBaseMS == -1) + m_durationBaseMS = getWorkflow().getDurationBaseSec() * 1000; + return limit * m_durationBaseMS; + } // getLimitMS + + /** + * Get Duration CalendarField + * @return Calendar.MINUTE, etc. + */ + public int getDurationCalendarField() + { + return getWorkflow().getDurationCalendarField(); + } // getDirationCalendarField + + /** + * Calculate Dynamic Priority + * @param seconds second after created + * @return dyn prio + */ + public int calculateDynamicPriority (int seconds) + { + if (seconds == 0 || getDynPriorityUnit() == null + || getDynPriorityChange() == null + || Env.ZERO.compareTo(getDynPriorityChange()) == 0) + return 0; + // + BigDecimal divide = Env.ZERO; + if (DYNPRIORITYUNIT_Minute.equals(getDynPriorityUnit())) + divide = new BigDecimal (60); + else if (DYNPRIORITYUNIT_Hour.equals(getDynPriorityUnit())) + divide = new BigDecimal (3600); + else if (DYNPRIORITYUNIT_Day.equals(getDynPriorityUnit())) + divide = new BigDecimal (86400); + else + return 0; + // + BigDecimal change = new BigDecimal (seconds) + .divide(divide, BigDecimal.ROUND_DOWN) + .multiply(getDynPriorityChange()); + return change.intValue(); + } // calculateDynamicPriority + + /************************************************************************** + * Get Parameters + * @return array of parameters + */ + public MWFNodePara[] getParameters() + { + if (m_paras == null) + m_paras = MWFNodePara.getParameters(getCtx(), getAD_WF_Node_ID()); + return m_paras; + } // getParameters + + /** + * Get Workflow + * @return workflow + */ + public MWorkflow getWorkflow() + { + return MWorkflow.get(getCtx(), getAD_Workflow_ID()); + } // getWorkflow + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MWFNode["); + sb.append(get_ID()) + .append("-").append(getName()) + .append(",Action=").append(getActionInfo()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * User String Representation + * @return info + */ + public String toStringX () + { + StringBuffer sb = new StringBuffer ("MWFNode["); + sb.append(getName()) + .append("-").append(getActionInfo()) + .append("]"); + return sb.toString (); + } // toStringX + + /** + * Before Save + * @param newRecord new + * @return true if can be saved + */ + protected boolean beforeSave (boolean newRecord) + { + String action = getAction(); + if (action.equals(ACTION_WaitSleep)) + ; + else if (action.equals(ACTION_AppsProcess) || action.equals(ACTION_AppsReport)) + { + if (getAD_Process_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "AD_Process_ID")); + return false; + } + } + else if (action.equals(ACTION_AppsTask)) + { + if (getAD_Task_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "AD_Task_ID")); + return false; + } + } + else if (action.equals(ACTION_DocumentAction)) + { + if (getDocAction() == null || getDocAction().length() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "DocAction")); + return false; + } + } + else if (action.equals(ACTION_EMail)) + { + if (getR_MailText_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "R_MailText_ID")); + return false; + } + } + else if (action.equals(ACTION_SetVariable)) + { + if (getAttributeValue() == null) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "AttributeValue")); + return false; + } + } + else if (action.equals(ACTION_SubWorkflow)) + { + if (getAD_Workflow_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "AD_Workflow_ID")); + return false; + } + } + else if (action.equals(ACTION_UserChoice)) + { + if (getAD_Column_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "AD_Column_ID")); + return false; + } + } + else if (action.equals(ACTION_UserForm)) + { + if (getAD_Form_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "AD_Form_ID")); + return false; + } + } + else if (action.equals(ACTION_UserWindow)) + { + if (getAD_Window_ID() == 0) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "AD_Window_ID")); + return false; + } + } +// else if (action.equals(ACTION_UserWorkbench)) +// { +// && getAD_Workbench_ID() == 0) +// log.saveError("FillMandatory", Msg.getElement(getCtx(), "AD_Workbench_ID")); +// return false; +// } + + return true; + } // beforeSave + + /** + * After Save + * @param newRecord new + * @param success success + * @return saved + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success) + return success; + TranslationTable.save(this, newRecord); + return true; + } // afterSave + + /** + * After Delete + * @param success success + * @return deleted + */ + protected boolean afterDelete (boolean success) + { + if (TranslationTable.isActiveLanguages(false)) + TranslationTable.delete(this); + return success; + } // afterDelete + +} // M_WFNext diff --git a/base/src/org/compiere/wf/MWFNodeNext.java b/base/src/org/compiere/wf/MWFNodeNext.java new file mode 100644 index 0000000000..9f45849536 --- /dev/null +++ b/base/src/org/compiere/wf/MWFNodeNext.java @@ -0,0 +1,266 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.sql.*; +import java.util.*; + +import org.compiere.model.*; +import org.compiere.process.*; +import java.util.logging.*; +import org.compiere.util.*; + +/** + * Workflow Node Next - Transition + * + * @author Jorg Janke + * @version $Id: MWFNodeNext.java,v 1.3 2006/10/06 00:42:24 jjanke Exp $ + */ +public class MWFNodeNext extends X_AD_WF_NodeNext +{ + /** + * Standard Costructor + * @param ctx context + * @param AD_WF_NodeNext_ID id + * @param trxName transaction + */ + public MWFNodeNext (Properties ctx, int AD_WF_NodeNext_ID, String trxName) + { + super (ctx, AD_WF_NodeNext_ID, trxName); + if (AD_WF_NodeNext_ID == 0) + { + // setAD_WF_Next_ID (0); + // setAD_WF_Node_ID (0); + setEntityType (ENTITYTYPE_UserMaintained); // U + setIsStdUserWorkflow (false); + setSeqNo (10); // 10 + } + } // MWFNodeNext + + /** + * Default Constructor + * @param ctx context + * @param rs result set to load info from + * @param trxName transaction + */ + public MWFNodeNext (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MWFNodeNext + + /** + * Parent constructor + * @param parent patent + * @param AD_WF_Next_ID Next + */ + public MWFNodeNext (MWFNode parent, int AD_WF_Next_ID) + { + this(parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setAD_WF_Node_ID(parent.getAD_WF_Node_ID()); + setAD_WF_Next_ID(AD_WF_Next_ID); + } // MWFNodeNext + + /** Transition Conditions */ + private MWFNextCondition[] m_conditions = null; + /** From (Split Eleemnt) is AND */ + public Boolean m_fromSplitAnd = null; + /** To (Join Element) is AND */ + public Boolean m_toJoinAnd = null; + + /** + * Set Client Org + * @param AD_Client_ID client + * @param AD_Org_ID org + */ + public void setClientOrg (int AD_Client_ID, int AD_Org_ID) + { + super.setClientOrg (AD_Client_ID, AD_Org_ID); + } // setClientOrg + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MWFNodeNext["); + sb.append(getSeqNo()) + .append(":Node=").append(getAD_WF_Node_ID()).append("->Next=").append(getAD_WF_Next_ID()); + if (m_conditions != null) + sb.append(",#").append(m_conditions.length); + if (getDescription() != null && getDescription().length() > 0) + sb.append(",").append(getDescription()); + sb.append ("]"); + return sb.toString (); + } // toString + + + /************************************************************************* + * Get Conditions + * @param requery true if requery + * @return Array of Conditions + */ + public MWFNextCondition[] getConditions(boolean requery) + { + if (!requery && m_conditions != null) + return m_conditions; + // + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM AD_WF_NextCondition WHERE AD_WF_NodeNext_ID=? AND IsActive='Y' ORDER BY SeqNo"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getAD_WF_NodeNext_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MWFNextCondition(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_conditions = new MWFNextCondition[list.size()]; + list.toArray (m_conditions); + return m_conditions; + } // getConditions + + /** + * Unconditional + * @return true if no conditions + */ + public boolean isUnconditional() + { + return !isStdUserWorkflow() && getConditions(false).length == 0; + } // isUnconditional + + /** + * Is this a Valid Transition For .. + * @param activity activity + * @return true if valid + */ + public boolean isValidFor (MWFActivity activity) + { + if (isStdUserWorkflow()) + { + PO po = activity.getPO(); + if (po instanceof DocAction) + { + DocAction da = (DocAction)po; + String docStatus = da.getDocStatus(); + String docAction = da.getDocAction(); + if (!DocAction.ACTION_Complete.equals(docAction) + || DocAction.STATUS_Completed.equals(docStatus) + || DocAction.STATUS_WaitingConfirmation.equals(docStatus) + || DocAction.STATUS_WaitingPayment.equals(docStatus) + || DocAction.STATUS_Voided.equals(docStatus) + || DocAction.STATUS_Closed.equals(docStatus) + || DocAction.STATUS_Reversed.equals(docStatus) ) + /* + || DocAction.ACTION_Complete.equals(docAction) + || DocAction.ACTION_ReActivate.equals(docAction) + || DocAction.ACTION_None.equals(docAction) + || DocAction.ACTION_Post.equals(docAction) + || DocAction.ACTION_Unlock.equals(docAction) + || DocAction.ACTION_Invalidate.equals(docAction) ) */ + { + log.fine("isValidFor =NO= StdUserWF - Status=" + docStatus + " - Action=" + docAction); + return false; + } + } + } + // No Conditions + if (getConditions(false).length == 0) + { + log.fine("isValidFor #0 " + toString()); + return true; + } + // First condition always AND + boolean ok = m_conditions[0].evaluate(activity); + for (int i = 1; i < m_conditions.length; i++) + { + if (m_conditions[i].isOr()) + ok = ok || m_conditions[i].evaluate(activity); + else + ok = ok || m_conditions[i].evaluate(activity); + } // for all conditions + log.fine("isValidFor (" + ok + ") " + toString()); + return ok; + } // isValidFor + + + /** + * Split Element is AND + * @return Returns the from Split And. + */ + public boolean isFromSplitAnd() + { + if (m_fromSplitAnd != null) + return m_fromSplitAnd.booleanValue(); + return false; + } // getFromSplitAnd + + /** + * Split Element is AND. + * Set by MWFNode.loadNodes + * @param fromSplitAnd The from Split And + */ + public void setFromSplitAnd (boolean fromSplitAnd) + { + m_fromSplitAnd = new Boolean(fromSplitAnd); + } // setFromSplitAnd + + /** + * Join Element is AND + * @return Returns the to Join And. + */ + public boolean isToJoinAnd () + { + if (m_toJoinAnd == null && getAD_WF_Next_ID() != 0) + { + MWFNode next = MWFNode.get(getCtx(), getAD_WF_Next_ID()); + setToJoinAnd(MWFNode.JOINELEMENT_AND.equals(next.getJoinElement())); + } + if (m_toJoinAnd != null) + return m_toJoinAnd.booleanValue(); + return false; + } // getToJoinAnd + + /** + * Join Element is AND. + * @param toJoinAnd The to Join And to set. + */ + private void setToJoinAnd (boolean toJoinAnd) + { + m_toJoinAnd = new Boolean(toJoinAnd); + } // setToJoinAnd + +} // MWFNodeNext diff --git a/base/src/org/compiere/wf/MWFNodePara.java b/base/src/org/compiere/wf/MWFNodePara.java new file mode 100644 index 0000000000..26747b4ffa --- /dev/null +++ b/base/src/org/compiere/wf/MWFNodePara.java @@ -0,0 +1,163 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.sql.*; +import java.util.*; + +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Workflow Node Process Parameter Model + * + * @author Jorg Janke + * @version $Id: MWFNodePara.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MWFNodePara extends X_AD_WF_Node_Para +{ + /** + * Get Parameters for a node + * @param ctx context + * @param AD_WF_Node_ID node + * @return array of parameters + */ + public static MWFNodePara[] getParameters (Properties ctx, int AD_WF_Node_ID) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM AD_WF_Node_Para " + + "WHERE AD_WF_Node_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, AD_WF_Node_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MWFNodePara (ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, "getParameters", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MWFNodePara[] retValue = new MWFNodePara[list.size ()]; + list.toArray (retValue); + return retValue; + } // getParameters + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MWFNodePara.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param id id + * @param trxName transaction + */ + public MWFNodePara (Properties ctx, int id, String trxName) + { + super (ctx, id, trxName); + } // MWFNodePara + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MWFNodePara (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MWFNodePara + + + /** Linked Process Parameter */ + private MProcessPara m_processPara = null; + + /** + * Get Process Parameter + * @return process parameter + */ + public MProcessPara getProcessPara() + { + if (m_processPara == null) + m_processPara = new MProcessPara (getCtx(), getAD_Process_Para_ID(), get_TrxName()); + return m_processPara; + } // getProcessPara + + /** + * Get Attribute Name. + * If not set - retrieve it + * @return attribute name + */ + public String getAttributeName () + { + String an = super.getAttributeName (); + if (an == null || an.length() == 0 && getAD_Process_Para_ID() != 0) + { + an = getProcessPara().getColumnName(); + setAttributeName(an); + save(); + } + return an; + } // getAttributeName + + /** + * Get Display Type + * @return display type + */ + public int getDisplayType() + { + return getProcessPara().getAD_Reference_ID(); + } // getDisplayType + + /** + * Is Mandatory + * @return true if mandatory + */ + public boolean isMandatory() + { + return getProcessPara().isMandatory(); + } // isMandatory + + /** + * Set AD_Process_Para_ID + * @param AD_Process_Para_ID id + */ + public void setAD_Process_Para_ID (int AD_Process_Para_ID) + { + super.setAD_Process_Para_ID (AD_Process_Para_ID); + setAttributeName(null); + } + +} // MWFNodePara diff --git a/base/src/org/compiere/wf/MWFProcess.java b/base/src/org/compiere/wf/MWFProcess.java new file mode 100644 index 0000000000..bff6855f7d --- /dev/null +++ b/base/src/org/compiere/wf/MWFProcess.java @@ -0,0 +1,535 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.process.*; +import org.compiere.util.*; + + +/** + * Workflow Process + * + * @author Jorg Janke + * @version $Id: MWFProcess.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MWFProcess extends X_AD_WF_Process +{ + /** + * Standard Constructor + * @param ctx context + * @param AD_WF_Process_ID process + * @param trxName transaction + */ + public MWFProcess (Properties ctx, int AD_WF_Process_ID, String trxName) + { + super (ctx, AD_WF_Process_ID, trxName); + if (AD_WF_Process_ID == 0) + throw new IllegalArgumentException ("Cannot create new WF Process directly"); + m_state = new StateEngine (getWFState()); + } // MWFProcess + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MWFProcess (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + m_state = new StateEngine (getWFState()); + } // MWFProcess + + /** + * New Constructor + * @param wf workflow + * @param pi Process Info (Record_ID) + * @throws Exception + */ + public MWFProcess (MWorkflow wf, ProcessInfo pi) throws Exception + { + super (wf.getCtx(), 0, wf.get_TrxName()); + if (!TimeUtil.isValid(wf.getValidFrom(), wf.getValidTo())) + throw new IllegalStateException("Workflow not valid"); + m_wf = wf; + m_pi = pi; + setAD_Workflow_ID (wf.getAD_Workflow_ID()); + setPriority(wf.getPriority()); + super.setWFState (WFSTATE_NotStarted); + + // Document + setAD_Table_ID(wf.getAD_Table_ID()); + setRecord_ID(pi.getRecord_ID()); + if (getPO() == null) + { + setTextMsg("No PO with ID=" + pi.getRecord_ID()); + super.setWFState (WFSTATE_Terminated); + } + else + setTextMsg(getPO()); + // Responsible/User + if (wf.getAD_WF_Responsible_ID() == 0) + setAD_WF_Responsible_ID(); + else + setAD_WF_Responsible_ID(wf.getAD_WF_Responsible_ID()); + setUser_ID(pi.getAD_User_ID()); // user starting + // + m_state = new StateEngine (getWFState()); + setProcessed (false); + // Lock Entity + getPO(); + if (m_po != null) + m_po.lock(); + } // MWFProcess + + /** State Machine */ + private StateEngine m_state = null; + /** Activities */ + private MWFActivity[] m_activities = null; + /** Workflow */ + private MWorkflow m_wf = null; + /** Process Info */ + private ProcessInfo m_pi = null; + /** Persistent Object */ + private PO m_po = null; + /** Message from Activity */ + private String m_processMsg = null; + + /** + * Get active Activities of Process + * @param requery if true requery + * @param onlyActive only active activities + * @return array of activities + */ + public MWFActivity[] getActivities (boolean requery, boolean onlyActive) + { + if (!requery && m_activities != null) + return m_activities; + // + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + String sql = "SELECT * FROM AD_WF_Activity WHERE AD_WF_Process_ID=?"; + if (onlyActive) + sql += " AND Processed='N'"; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getAD_WF_Process_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MWFActivity(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + m_activities = new MWFActivity[list.size ()]; + list.toArray (m_activities); + return m_activities; + } // getActivities + + /** + * Get State + * @return state + */ + public StateEngine getState() + { + return m_state; + } // getState + + /** + * Get Action Options + * @return array of valid actions + */ + public String[] getActionOptions() + { + return m_state.getActionOptions(); + } // getActionOptions + + /** + * Set Process State and update Actions + * @param WFState + */ + public void setWFState (String WFState) + { + if (m_state == null) + m_state = new StateEngine (getWFState()); + if (m_state.isClosed()) + return; + if (getWFState().equals(WFState)) + return; + // + if (m_state.isValidNewState(WFState)) + { + log.fine(WFState); + super.setWFState (WFState); + m_state = new StateEngine (getWFState()); + if (m_state.isClosed()) + setProcessed(true); + save(); + // Force close to all Activities + if (m_state.isClosed()) + { + MWFActivity[] activities = getActivities(true, true); // requery only active + for (int i = 0; i < activities.length; i++) + { + if (!activities[i].isClosed()) + { + activities[i].setTextMsg("Process:" + WFState); + activities[i].setWFState(WFState); + } + if (!activities[i].isProcessed()) + activities[i].setProcessed(true); + activities[i].save(); + } + } // closed + } + else + log.log(Level.SEVERE, "Ignored Invalid Transformation - New=" + WFState + + ", Current=" + getWFState()); + } // setWFState + + + /************************************************************************** + * Check Status of Activities. + * - update Process if required + * - start new activity + * @param trxName transaction + */ + public void checkActivities(String trxName) + { + log.info("(" + getAD_Workflow_ID() + ") - " + getWFState() + + (trxName == null ? "" : "[" + trxName + "]")); + if (m_state.isClosed()) + return; + // + MWFActivity[] activities = getActivities (true, true); // requery active + String closedState = null; + boolean suspended = false; + boolean running = false; + for (int i = 0; i < activities.length; i++) + { + MWFActivity activity = activities[i]; + StateEngine activityState = activity.getState(); + + // Completed - Start Next + if (activityState.isCompleted()) + { + if (startNext (activity, activities)) + continue; + } + // + String activityWFState = activity.getWFState(); + if (activityState.isClosed()) + { + // eliminate from active processed + activity.setProcessed(true); + activity.save(); + // + if (closedState == null) + closedState = activityWFState; + else if (!closedState.equals(activityState)) + { + // Overwrite if terminated + if (WFSTATE_Terminated.equals(activityState)) + closedState = activityWFState; + // Overwrite if activity aborted and no other terminated + else if (WFSTATE_Aborted.equals(activityState) && !WFSTATE_Terminated.equals(closedState)) + closedState = activityWFState; + } + } + else // not closed + { + closedState = null; // all need to be closed + if (activityState.isSuspended()) + suspended = true; + if (activityState.isRunning()) + running = true; + } + } // for all activities + if (activities.length == 0) + { + setTextMsg("No Active Processed found"); + closedState = WFSTATE_Terminated; + } + if (closedState != null) + { + setWFState(closedState); + getPO(); + if (m_po != null) + m_po.unlock(trxName); + } + else if (suspended) + setWFState(WFSTATE_Suspended); + else if (running) + setWFState(WFSTATE_Running); + } // checkActivities + + + /** + * Start Next Activity + * @param last last activity + * @param activities all activities + * @return true if there is a next activity + */ + private boolean startNext (MWFActivity last, MWFActivity[] activities) + { + log.fine("Last=" + last); + // transitions from the last processed node + MWFNodeNext[] transitions = getWorkflow().getNodeNexts( + last.getAD_WF_Node_ID(), last.getPO_AD_Client_ID()); + if (transitions == null || transitions.length == 0) + return false; // done + + // We need to wait for last activity + if (MWFNode.JOINELEMENT_AND.equals(last.getNode().getJoinElement())) + { + // get previous nodes + // check if all have closed activities + // return false for all but the last + } + // eliminate from active processed + last.setProcessed(true); + last.save(); + + // Start next activity + String split = last.getNode().getSplitElement(); + for (int i = 0; i < transitions.length; i++) + { + // Is this a valid transition? + if (!transitions[i].isValidFor(last)) + continue; + + // Start new Activity + MWFActivity activity = new MWFActivity (this, transitions[i].getAD_WF_Next_ID()); + new Thread(activity).start(); + + // only the first valid if XOR + if (MWFNode.SPLITELEMENT_XOR.equals(split)) + return true; + } // for all transitions + return true; + } // startNext + + + /************************************************************************** + * Set Workflow Responsible. + * Searches for a Invoker. + */ + public void setAD_WF_Responsible_ID () + { + int AD_WF_Responsible_ID = DB.getSQLValue(null, + MRole.getDefault(getCtx(), false).addAccessSQL( + "SELECT AD_WF_Responsible_ID FROM AD_WF_Responsible " + + "WHERE ResponsibleType='H' AND COALESCE(AD_User_ID,0)=0 " + + "ORDER BY AD_Client_ID DESC", + "AD_WF_Responsible", MRole.SQL_NOTQUALIFIED, MRole.SQL_RO)); + setAD_WF_Responsible_ID (AD_WF_Responsible_ID); + } // setAD_WF_Responsible_ID + + /** + * Set User from + * - (1) Responsible + * - (2) Document Sales Rep + * - (3) Document UpdatedBy + * - (4) Process invoker + * @param User_ID process invoker + */ + private void setUser_ID (Integer User_ID) + { + // Responsible + MWFResponsible resp = MWFResponsible.get(getCtx(), getAD_WF_Responsible_ID()); + // (1) User - Directly responsible + int AD_User_ID = resp.getAD_User_ID(); + + // Invoker - get Sales Rep or last updater of Document + if (AD_User_ID == 0 && resp.isInvoker()) + { + getPO(); + // (2) Doc Owner + if (m_po != null && m_po instanceof DocAction) + { + DocAction da = (DocAction)m_po; + AD_User_ID = da.getDoc_User_ID(); + } + // (2) Sales Rep + if (AD_User_ID == 0 && m_po != null && m_po.get_ColumnIndex("SalesRep_ID") != -1) + { + Object sr = m_po.get_Value("SalesRep_ID"); + if (sr != null && sr instanceof Integer) + AD_User_ID = ((Integer)sr).intValue(); + } + // (3) UpdatedBy + if (AD_User_ID == 0 && m_po != null) + AD_User_ID = m_po.getUpdatedBy(); + } + + // (4) Process Owner + if (AD_User_ID == 0 && User_ID != null) + AD_User_ID = User_ID.intValue(); + // Fallback + if (AD_User_ID == 0) + AD_User_ID = Env.getAD_User_ID(getCtx()); + // + setAD_User_ID(AD_User_ID); + } // setUser_ID + + /** + * Get Workflow + * @return workflow + */ + private MWorkflow getWorkflow() + { + if (m_wf == null) + m_wf = MWorkflow.get (getCtx(), getAD_Workflow_ID()); + if (m_wf.get_ID() == 0) + throw new IllegalStateException("Not found - AD_Workflow_ID=" + getAD_Workflow_ID()); + return m_wf; + } // getWorkflow + + + /************************************************************************** + * Perform Action + * @param action StateEngine.ACTION_* + * @return true if valid + */ + public boolean perform (String action) + { + if (!m_state.isValidAction(action)) + { + log.log(Level.SEVERE, "Ignored Invalid Transformation - Action=" + action + + ", CurrentState=" + getWFState()); + return false; + } + log.fine(action); + // Action is Valid + if (StateEngine.ACTION_Start.equals(action)) + return startWork(); + // Set new State + setWFState (m_state.getNewStateIfAction(action)); + return true; + } // perform + + /** + * Start WF Execution async + * @return true if success + */ + public boolean startWork() + { + if (!m_state.isValidAction(StateEngine.ACTION_Start)) + { + log.warning("State=" + getWFState() + " - cannot start"); + return false; + } + int AD_WF_Node_ID = getWorkflow().getAD_WF_Node_ID(); + log.fine("AD_WF_Node_ID=" + AD_WF_Node_ID); + setWFState(WFSTATE_Running); + try + { + // Start first Activity with first Node + MWFActivity activity = new MWFActivity (this, AD_WF_Node_ID); + new Thread(activity).start(); + } + catch (Exception e) + { + log.log(Level.SEVERE, "AD_WF_Node_ID=" + AD_WF_Node_ID, e); + setTextMsg(e.toString()); + setWFState(StateEngine.STATE_Terminated); + return false; + } + return true; + } // performStart + + + /************************************************************************** + * Get Persistent Object + * @return po + */ + public PO getPO() + { + if (m_po != null) + return m_po; + if (getRecord_ID() == 0) + return null; + + MTable table = MTable.get (getCtx(), getAD_Table_ID()); + m_po = table.getPO(getRecord_ID(), get_TrxName()); + return m_po; + } // getPO + + /** + * Set Text Msg (add to existing) + * @param po base object + */ + public void setTextMsg (PO po) + { + if (po != null && po instanceof DocAction) + setTextMsg(((DocAction)po).getSummary()); + } // setTextMsg + + /** + * Set Text Msg (add to existing) + * @param TextMsg msg + */ + public void setTextMsg (String TextMsg) + { + String oldText = getTextMsg(); + if (oldText == null || oldText.length() == 0) + super.setTextMsg (TextMsg); + else if (TextMsg != null && TextMsg.length() > 0) + super.setTextMsg (oldText + "\n - " + TextMsg); + } // setTextMsg + + + /** + * Set Runtime (Error) Message + * @param msg message + */ + public void setProcessMsg (String msg) + { + m_processMsg = msg; + if (msg != null && msg.length() > 0) + setTextMsg(msg); + } // setProcessMsg + + /** + * Get Runtime (Error) Message + * @return msg + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + +} // MWFProcess diff --git a/base/src/org/compiere/wf/MWFResponsible.java b/base/src/org/compiere/wf/MWFResponsible.java new file mode 100644 index 0000000000..1cb114c684 --- /dev/null +++ b/base/src/org/compiere/wf/MWFResponsible.java @@ -0,0 +1,170 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.sql.*; +import java.util.*; +import org.compiere.model.*; +import org.compiere.util.*; + + +/** + * Workflow Resoinsible + * + * @author Jorg Janke + * @version $Id: MWFResponsible.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MWFResponsible extends X_AD_WF_Responsible +{ + /** + * Get WF Responsible from Cache + * @param ctx context + * @param AD_WF_Responsible_ID id + * @return MWFResponsible + */ + public static MWFResponsible get (Properties ctx, int AD_WF_Responsible_ID) + { + Integer key = new Integer (AD_WF_Responsible_ID); + MWFResponsible retValue = (MWFResponsible) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MWFResponsible (ctx, AD_WF_Responsible_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("AD_WF_Responsible", 10); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param AD_WF_Responsible_ID id + * @param trxName transaction + */ + public MWFResponsible (Properties ctx, int AD_WF_Responsible_ID, String trxName) + { + super (ctx, AD_WF_Responsible_ID, trxName); + } // MWFResponsible + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MWFResponsible (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MWFResponsible + + /** + * Invoker - return true if no user and no role + * @return true if invoker + */ + public boolean isInvoker() + { + return getAD_User_ID() == 0 && getAD_Role_ID() == 0; + } // isInvoker + + /** + * Is Role Responsible + * @return true if role + */ + public boolean isRole() + { + return RESPONSIBLETYPE_Role.equals(getResponsibleType()) + && getAD_Role_ID() != 0; + } // isRole + + /** + * Is Role Responsible + * @return true if role + */ + public MRole getRole() + { + if (!isRole()) + return null; + return MRole.get(getCtx(), getAD_Role_ID()); + } // getRole + + /** + * Is Human Responsible + * @return true if human + */ + public boolean isHuman() + { + return RESPONSIBLETYPE_Human.equals(getResponsibleType()) + && getAD_User_ID() != 0; + } // isHuman + + /** + * Is Org Responsible + * @return true if Org + */ + public boolean isOrganization() + { + return RESPONSIBLETYPE_Organization.equals(getResponsibleType()) + && getAD_Org_ID() != 0; + } // isOrg + + /** + * Before Save + * @param newRecord new + * @return tre if can be saved + */ + protected boolean beforeSave (boolean newRecord) + { + // if (RESPONSIBLETYPE_Human.equals(getResponsibleType()) && getAD_User_ID() == 0) + // return true; + if (RESPONSIBLETYPE_Role.equals(getResponsibleType()) + && getAD_Role_ID() == 0 + && getAD_Client_ID() > 0) + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@RequiredEnter@ @AD_Role_ID@")); + return false; + } + // User not used + if (!RESPONSIBLETYPE_Human.equals(getResponsibleType()) && getAD_User_ID() == 0) + setAD_User_ID(0); + // Role not used + if (!RESPONSIBLETYPE_Role.equals(getResponsibleType()) && getAD_Role_ID() == 0) + setAD_Role_ID(0); + return true; + } // beforeSave + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer("MWFResponsible["); + sb.append (get_ID()) + .append("-").append(getName()) + .append(",Type=").append(getResponsibleType()); + if (getAD_User_ID() != 0) + sb.append(",AD_User_ID=").append(getAD_User_ID()); + if (getAD_Role_ID() != 0) + sb.append(",AD_Role_ID=").append(getAD_Role_ID()); + sb.append ("]"); + return sb.toString (); + } // toString + +} // MWFResponsible diff --git a/base/src/org/compiere/wf/MWorkflow.java b/base/src/org/compiere/wf/MWorkflow.java new file mode 100644 index 0000000000..852d4ca6e6 --- /dev/null +++ b/base/src/org/compiere/wf/MWorkflow.java @@ -0,0 +1,871 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * WorkFlow Model + * + * @author Jorg Janke + * @version $Id: MWorkflow.java,v 1.4 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MWorkflow extends X_AD_Workflow +{ + /** + * Get Workflow from Cache + * @param ctx context + * @param AD_Workflow_ID id + * @return workflow + */ + public static MWorkflow get (Properties ctx, int AD_Workflow_ID) + { + Integer key = new Integer (AD_Workflow_ID); + MWorkflow retValue = (MWorkflow)s_cache.get(key); + if (retValue != null) + return retValue; + retValue = new MWorkflow (ctx, AD_Workflow_ID, null); + if (retValue.get_ID() != 0) + s_cache.put(key, retValue); + return retValue; + } // get + + + /** + * Get Doc Value Workflow + * @param ctx context + * @param AD_Client_ID client + * @param AD_Table_ID table + * @return document value workflow array or null + */ + public static MWorkflow[] getDocValue (Properties ctx, int AD_Client_ID, int AD_Table_ID + , String trxName //Bug 1568766 Trx should be kept all along the road + ) + { + String key = "C" + AD_Client_ID + "T" + AD_Table_ID; + // Reload + if (s_cacheDocValue.isReset()) + { + String sql = "SELECT * FROM AD_Workflow " + + "WHERE WorkflowType='V' AND IsActive='Y' AND IsValid='Y' " + + "ORDER BY AD_Client_ID, AD_Table_ID"; + ArrayList list = new ArrayList(); + String oldKey = ""; + String newKey = null; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); //Bug 1568766 + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MWorkflow wf = new MWorkflow (ctx, rs, trxName); //Bug 1568766 + newKey = "C" + wf.getAD_Client_ID() + "T" + wf.getAD_Table_ID(); + if (!newKey.equals(oldKey) && list.size() > 0) + { + MWorkflow[] wfs = new MWorkflow[list.size()]; + list.toArray(wfs); + s_cacheDocValue.put (oldKey, wfs); + list = new ArrayList(); + } + oldKey = newKey; + list.add(wf); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + // Last one + if (list.size() > 0) + { + MWorkflow[] wfs = new MWorkflow[list.size()]; + list.toArray(wfs); + s_cacheDocValue.put (oldKey, wfs); + } + s_log.config("#" + s_cacheDocValue.size()); + } + // Look for Entry + MWorkflow[] retValue = (MWorkflow[])s_cacheDocValue.get(key); + return retValue; + } // getDocValue + + + /** Single Cache */ + private static CCache s_cache = new CCache("AD_Workflow", 20); + /** Document Value Cache */ + private static CCache s_cacheDocValue = new CCache ("AD_Workflow", 5); + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MWorkflow.class); + + + /************************************************************************** + * Create/Load Workflow + * @param ctx Context + * @param AD_Workflow_ID ID + * @param trxName transaction + */ + public MWorkflow (Properties ctx, int AD_Workflow_ID, String trxName) + { + super (ctx, AD_Workflow_ID, trxName); + if (AD_Workflow_ID == 0) + { + // setAD_Workflow_ID (0); + // setValue (null); + // setName (null); + setAccessLevel (ACCESSLEVEL_Organization); + setAuthor ("ComPiere, Inc."); + setDurationUnit(DURATIONUNIT_Day); + setDuration (1); + setEntityType (ENTITYTYPE_UserMaintained); // U + setIsDefault (false); + setPublishStatus (PUBLISHSTATUS_UnderRevision); // U + setVersion (0); + setCost (0); + setWaitingTime (0); + setWorkingTime (0); + } + loadTrl(); + loadNodes(); + } // MWorkflow + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MWorkflow (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + loadTrl(); + loadNodes(); + } // Workflow + + /** WF Nodes */ + private ArrayList m_nodes = new ArrayList(); + + /** Translated Name */ + private String m_name_trl = null; + /** Translated Description */ + private String m_description_trl = null; + /** Translated Help */ + private String m_help_trl = null; + /** Translation Flag */ + private boolean m_translated = false; + + /** + * Load Translation + */ + private void loadTrl() + { + if (Env.isBaseLanguage(getCtx(), "AD_Workflow") || get_ID() == 0) + return; + String sql = "SELECT Name, Description, Help FROM AD_Workflow_Trl WHERE AD_Workflow_ID=? AND AD_Language=?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, get_ID()); + pstmt.setString(2, Env.getAD_Language(getCtx())); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + m_name_trl = rs.getString(1); + m_description_trl = rs.getString(2); + m_help_trl = rs.getString(3); + m_translated = true; + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + log.fine("Translated=" + m_translated); + } // loadTrl + + /** + * Load All Nodes + */ + private void loadNodes() + { + String sql = "SELECT * FROM AD_WF_Node WHERE AD_WorkFlow_ID=? AND IsActive='Y'"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, get_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + m_nodes.add (new MWFNode (getCtx(), rs, get_TrxName())); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + log.log(Level.SEVERE, sql, e); + } + log.fine("#" + m_nodes.size()); + } // loadNodes + + + /************************************************************************** + * Get Number of Nodes + * @return number of nodes + */ + public int getNodeCount() + { + return m_nodes.size(); + } // getNextNodeCount + + /** + * Get the nodes + * @param ordered ordered array + * @param AD_Client_ID for client + * @return array of nodes + */ + public MWFNode[] getNodes(boolean ordered, int AD_Client_ID) + { + if (ordered) + return getNodesInOrder(AD_Client_ID); + // + ArrayList list = new ArrayList(); + for (int i = 0; i < m_nodes.size(); i++) + { + MWFNode node = m_nodes.get(i); + if (node.getAD_Client_ID() == 0 || node.getAD_Client_ID() == AD_Client_ID) + list.add(node); + } + MWFNode[] retValue = new MWFNode [list.size()]; + list.toArray(retValue); + return retValue; + } // getNodes + + /** + * Get the first node + * @return array of next nodes + */ + public MWFNode getFirstNode() + { + return getNode (getAD_WF_Node_ID()); + } // getFirstNode + + /** + * Get Node with ID in Workflow + * @param AD_WF_Node_ID ID + * @return node or null + */ + protected MWFNode getNode (int AD_WF_Node_ID) + { + for (int i = 0; i < m_nodes.size(); i++) + { + MWFNode node = (MWFNode)m_nodes.get(i); + if (node.getAD_WF_Node_ID() == AD_WF_Node_ID) + return node; + } + return null; + } // getNode + + /** + * Get the next nodes + * @param AD_WF_Node_ID ID + * @param AD_Client_ID for client + * @return array of next nodes or null + */ + public MWFNode[] getNextNodes (int AD_WF_Node_ID, int AD_Client_ID) + { + MWFNode node = getNode(AD_WF_Node_ID); + if (node == null || node.getNextNodeCount() == 0) + return null; + // + MWFNodeNext[] nexts = node.getTransitions(AD_Client_ID); + ArrayList list = new ArrayList(); + for (int i = 0; i < nexts.length; i++) + { + MWFNode next = getNode (nexts[i].getAD_WF_Next_ID()); + if (next != null) + list.add(next); + } + + // Return Nodes + MWFNode[] retValue = new MWFNode [list.size()]; + list.toArray(retValue); + return retValue; + } // getNextNodes + + /** + * Get The Nodes in Sequence Order + * @param AD_Client_ID client + * @return Nodes in sequence + */ + private MWFNode[] getNodesInOrder(int AD_Client_ID) + { + ArrayList list = new ArrayList(); + addNodesSF (list, getAD_WF_Node_ID(), AD_Client_ID); // start with first + // Remaining Nodes + if (m_nodes.size() != list.size()) + { + // Add Stand alone + for (int n = 0; n < m_nodes.size(); n++) + { + MWFNode node = (MWFNode)m_nodes.get(n); + if (node.getAD_Client_ID() == 0 || node.getAD_Client_ID() == AD_Client_ID) + { + boolean found = false; + for (int i = 0; i < list.size(); i++) + { + MWFNode existing = (MWFNode)list.get(i); + if (existing.getAD_WF_Node_ID() == node.getAD_WF_Node_ID()) + { + found = true; + break; + } + } + if (!found) + { + log.log(Level.WARNING, "Added Node w/o transition: " + node); + list.add(node); + } + } + } + } + // + MWFNode[] nodeArray = new MWFNode [list.size()]; + list.toArray(nodeArray); + return nodeArray; + } // getNodesInOrder + + /** + * Add Nodes recursively (depth first) to Ordered List + * @param list list to add to + * @param AD_WF_Node_ID start node id + * @param AD_Client_ID for client + */ + private void addNodesDF (ArrayList list, int AD_WF_Node_ID, int AD_Client_ID) + { + MWFNode node = getNode (AD_WF_Node_ID); + if (node != null && !list.contains(node)) + { + list.add(node); + // Get Dependent + MWFNodeNext[] nexts = node.getTransitions(AD_Client_ID); + for (int i = 0; i < nexts.length; i++) + addNodesDF (list, nexts[i].getAD_WF_Next_ID(), AD_Client_ID); + } + } // addNodesDF + + /** + * Add Nodes recursively (sibling first) to Ordered List + * @param list list to add to + * @param AD_WF_Node_ID start node id + * @param AD_Client_ID for client + */ + private void addNodesSF (ArrayList list, int AD_WF_Node_ID, int AD_Client_ID) + { + MWFNode node = getNode (AD_WF_Node_ID); + if (node != null + && (node.getAD_Client_ID() == 0 || node.getAD_Client_ID() == AD_Client_ID)) + { + if (!list.contains(node)) + list.add(node); + MWFNodeNext[] nexts = node.getTransitions(AD_Client_ID); + for (int i = 0; i < nexts.length; i++) + { + MWFNode child = getNode (nexts[i].getAD_WF_Next_ID()); + if (child.getAD_Client_ID() == 0 + || child.getAD_Client_ID() == AD_Client_ID) + { + if (!list.contains(child)) + list.add(child); + } + } + // Remainder Nodes not conncetd + for (int i = 0; i < nexts.length; i++) + addNodesSF (list, nexts[i].getAD_WF_Next_ID(), AD_Client_ID); + } + } // addNodesSF + + /************************************************************************** + * Get first transition (Next Node) of ID + * @param AD_WF_Node_ID id + * @param AD_Client_ID for client + * @return next AD_WF_Node_ID or 0 + */ + public int getNext (int AD_WF_Node_ID, int AD_Client_ID) + { + MWFNode[] nodes = getNodesInOrder(AD_Client_ID); + for (int i = 0; i < nodes.length; i++) + { + if (nodes[i].getAD_WF_Node_ID() == AD_WF_Node_ID) + { + MWFNodeNext[] nexts = nodes[i].getTransitions(AD_Client_ID); + if (nexts.length > 0) + return nexts[0].getAD_WF_Next_ID(); + return 0; + } + } + return 0; + } // getNext + + /** + * Get Transitions (NodeNext) of ID + * @param AD_WF_Node_ID id + * @param AD_Client_ID for client + * @return array of next nodes + */ + public MWFNodeNext[] getNodeNexts (int AD_WF_Node_ID, int AD_Client_ID) + { + MWFNode[] nodes = getNodesInOrder(AD_Client_ID); + for (int i = 0; i < nodes.length; i++) + { + if (nodes[i].getAD_WF_Node_ID() == AD_WF_Node_ID) + { + return nodes[i].getTransitions(AD_Client_ID); + } + } + return null; + } // getNext + + /** + * Get (first) Previous Node of ID + * @param AD_WF_Node_ID id + * @param AD_Client_ID for client + * @return next AD_WF_Node_ID or 0 + */ + public int getPrevious (int AD_WF_Node_ID, int AD_Client_ID) + { + MWFNode[] nodes = getNodesInOrder(AD_Client_ID); + for (int i = 0; i < nodes.length; i++) + { + if (nodes[i].getAD_WF_Node_ID() == AD_WF_Node_ID) + { + if (i > 0) + return nodes[i-1].getAD_WF_Node_ID(); + return 0; + } + } + return 0; + } // getPrevious + + /** + * Get very Last Node + * @param AD_WF_Node_ID ignored + * @param AD_Client_ID for client + * @return next AD_WF_Node_ID or 0 + */ + public int getLast (int AD_WF_Node_ID, int AD_Client_ID) + { + MWFNode[] nodes = getNodesInOrder(AD_Client_ID); + if (nodes.length > 0) + return nodes[nodes.length-1].getAD_WF_Node_ID(); + return 0; + } // getLast + + /** + * Is this the first Node + * @param AD_WF_Node_ID id + * @param AD_Client_ID for client + * @return true if first node + */ + public boolean isFirst (int AD_WF_Node_ID, int AD_Client_ID) + { + return AD_WF_Node_ID == getAD_WF_Node_ID(); + } // isFirst + + /** + * Is this the last Node + * @param AD_WF_Node_ID id + * @param AD_Client_ID for client + * @return true if last node + */ + public boolean isLast (int AD_WF_Node_ID, int AD_Client_ID) + { + MWFNode[] nodes = getNodesInOrder(AD_Client_ID); + return AD_WF_Node_ID == nodes[nodes.length-1].getAD_WF_Node_ID(); + } // isLast + + + /************************************************************************** + * Get Name + * @param translated translated + * @return Name + */ + public String getName(boolean translated) + { + if (translated && m_translated) + return m_name_trl; + return getName(); + } // getName + + /** + * Get Description + * @param translated translated + * @return Description + */ + public String getDescription (boolean translated) + { + if (translated && m_translated) + return m_description_trl; + return getDescription(); + } // getDescription + + /** + * Get Help + * @param translated translated + * @return Name + */ + public String getHelp (boolean translated) + { + if (translated && m_translated) + return m_help_trl; + return getHelp(); + } // getHelp + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MWorkflow["); + sb.append(get_ID()).append("-").append(getName()) + .append ("]"); + return sb.toString (); + } // toString + + /************************************************************************** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + validate(); + return true; + } // beforeSave + + /** + * After Save. + * @param newRecord new record + * @param success success + * @return true if save complete (if not overwritten true) + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + log.fine("Success=" + success); + if (success && newRecord) + { + // save all nodes -- Creating new Workflow + MWFNode[] nodes = getNodesInOrder(0); + for (int i = 0; i < nodes.length; i++) + nodes[i].save(get_TrxName()); + } + + if (newRecord) + { + int AD_Role_ID = Env.getAD_Role_ID(getCtx()); + MWorkflowAccess wa = new MWorkflowAccess(this, AD_Role_ID); + wa.save(); + } + // Menu/Workflow + else if (is_ValueChanged("IsActive") || is_ValueChanged("Name") + || is_ValueChanged("Description") || is_ValueChanged("Help")) + { + MMenu[] menues = MMenu.get(getCtx(), "AD_Workflow_ID=" + getAD_Workflow_ID()); + for (int i = 0; i < menues.length; i++) + { + menues[i].setIsActive(isActive()); + menues[i].setName(getName()); + menues[i].setDescription(getDescription()); + menues[i].save(); + } + X_AD_WF_Node[] nodes = MWindow.getWFNodes(getCtx(), "AD_Workflow_ID=" + getAD_Workflow_ID()); + for (int i = 0; i < nodes.length; i++) + { + boolean changed = false; + if (nodes[i].isActive() != isActive()) + { + nodes[i].setIsActive(isActive()); + changed = true; + } + if (nodes[i].isCentrallyMaintained()) + { + nodes[i].setName(getName()); + nodes[i].setDescription(getDescription()); + nodes[i].setHelp(getHelp()); + changed = true; + } + if (changed) + nodes[i].save(); + } + } + + return success; + } // afterSave + + + /************************************************************************** + * Start Workflow. + * @param pi Process Info (Record_ID) + * @return process + */ + public MWFProcess start (ProcessInfo pi) + { + MWFProcess retValue = null; + try + { + retValue = new MWFProcess (this, pi); + retValue.save(); + retValue.startWork(); + pi.setSummary(Msg.getMsg(getCtx(), "Processing")); + } + catch (Exception e) + { + log.log(Level.SEVERE, e.getLocalizedMessage(), e); + pi.setSummary(e.getMessage(), true); + retValue = null; + } + return retValue; + } // MWFProcess + + /** + * Start Workflow and Wait for completion. + * @param pi process info with Record_ID record for the workflow + * @return process + */ + public MWFProcess startWait (ProcessInfo pi) + { + final int SLEEP = 500; // 1/2 sec + final int MAXLOOPS = 30; // 15 sec + // + MWFProcess process = start(pi); + if (process == null) + return null; + Thread.yield(); + StateEngine state = process.getState(); + int loops = 0; + while (!state.isClosed() && !state.isSuspended()) + { + if (loops > MAXLOOPS) + { + log.warning("Timeout after sec " + ((SLEEP*MAXLOOPS)/1000)); + pi.setSummary(Msg.getMsg(getCtx(), "ProcessRunning")); + pi.setIsTimeout(true); + return process; + } + // System.out.println("--------------- " + loops + ": " + state); + try + { + Thread.sleep(SLEEP); + loops++; + } + catch (InterruptedException e) + { + log.log(Level.SEVERE, "startWait interrupted", e); + pi.setSummary("Interrupted"); + return process; + } + Thread.yield(); + state = process.getState(); + } + String summary = process.getProcessMsg(); + if (summary == null || summary.trim().length() == 0) + summary = state.toString(); + pi.setSummary(summary, state.isTerminated() || state.isAborted()); + log.fine(summary); + return process; + } // startWait + + /** + * Get Duration Base in Seconds + * @return duration unit in seconds + */ + public long getDurationBaseSec () + { + if (getDurationUnit() == null) + return 0; + else if (DURATIONUNIT_Second.equals(getDurationUnit())) + return 1; + else if (DURATIONUNIT_Minute.equals(getDurationUnit())) + return 60; + else if (DURATIONUNIT_Hour.equals(getDurationUnit())) + return 3600; + else if (DURATIONUNIT_Day.equals(getDurationUnit())) + return 86400; + else if (DURATIONUNIT_Month.equals(getDurationUnit())) + return 2592000; + else if (DURATIONUNIT_Year.equals(getDurationUnit())) + return 31536000; + return 0; + } // getDurationBaseSec + + /** + * Get Duration CalendarField + * @return Calendar.MINUTE, etc. + */ + public int getDurationCalendarField() + { + if (getDurationUnit() == null) + return Calendar.MINUTE; + else if (DURATIONUNIT_Second.equals(getDurationUnit())) + return Calendar.SECOND; + else if (DURATIONUNIT_Minute.equals(getDurationUnit())) + return Calendar.MINUTE; + else if (DURATIONUNIT_Hour.equals(getDurationUnit())) + return Calendar.HOUR; + else if (DURATIONUNIT_Day.equals(getDurationUnit())) + return Calendar.DAY_OF_YEAR; + else if (DURATIONUNIT_Month.equals(getDurationUnit())) + return Calendar.MONTH; + else if (DURATIONUNIT_Year.equals(getDurationUnit())) + return Calendar.YEAR; + return Calendar.MINUTE; + } // getDurationCalendarField + + + /************************************************************************** + * Validate workflow. + * Sets Valid flag + * @return errors or "" + */ + public String validate() + { + StringBuffer errors = new StringBuffer(); + // + if (getAD_WF_Node_ID() == 0) + errors.append(" - No Start Node"); + // + if (WORKFLOWTYPE_DocumentValue.equals(getWorkflowType()) + && (getDocValueLogic() == null || getDocValueLogic().length() == 0)) + errors.append(" - No Document Value Logic"); + // + + + // final + boolean valid = errors.length() == 0; + setIsValid(valid); + if (!valid) + log.info("validate: " + errors); + return errors.toString(); + } // validate + + + + /************************************************************************** + * main + * @param args + */ + public static void main (String[] args) + { + org.compiere.Adempiere.startup(true); + + // Create Standard Document Process + MWorkflow wf = new MWorkflow(Env.getCtx(), 0, null); + wf.setValue ("Process_xx"); + wf.setName (wf.getValue()); + wf.setDescription("(Standard " + wf.getValue()); + wf.setEntityType (ENTITYTYPE_Dictionary); + wf.save(); + // + MWFNode node10 = new MWFNode (wf, "10", "(Start)"); + node10.setDescription("(Standard Node)"); + node10.setEntityType (ENTITYTYPE_Dictionary); + node10.setAction(MWFNode.ACTION_WaitSleep); + node10.setWaitTime(0); + node10.setPosition(5, 5); + node10.save(); + wf.setAD_WF_Node_ID(node10.getAD_WF_Node_ID()); + wf.save(); + + MWFNode node20 = new MWFNode (wf, "20", "(DocAuto)"); + node20.setDescription("(Standard Node)"); + node20.setEntityType (ENTITYTYPE_Dictionary); + node20.setAction(MWFNode.ACTION_DocumentAction); + node20.setDocAction(MWFNode.DOCACTION_None); + node20.setPosition(5, 120); + node20.save(); + MWFNodeNext tr10_20 = new MWFNodeNext(node10, node20.getAD_WF_Node_ID()); + tr10_20.setEntityType (ENTITYTYPE_Dictionary); + tr10_20.setDescription("(Standard Transition)"); + tr10_20.setSeqNo(100); + tr10_20.save(); + + MWFNode node100 = new MWFNode (wf, "100", "(DocPrepare)"); + node100.setDescription("(Standard Node)"); + node100.setEntityType (ENTITYTYPE_Dictionary); + node100.setAction(MWFNode.ACTION_DocumentAction); + node100.setDocAction(MWFNode.DOCACTION_Prepare); + node100.setPosition(170, 5); + node100.save(); + MWFNodeNext tr10_100 = new MWFNodeNext(node10, node100.getAD_WF_Node_ID()); + tr10_100.setEntityType (ENTITYTYPE_Dictionary); + tr10_100.setDescription("(Standard Approval)"); + tr10_100.setIsStdUserWorkflow(true); + tr10_100.setSeqNo(10); + tr10_100.save(); + + MWFNode node200 = new MWFNode (wf, "200", "(DocComplete)"); + node200.setDescription("(Standard Node)"); + node200.setEntityType (ENTITYTYPE_Dictionary); + node200.setAction(MWFNode.ACTION_DocumentAction); + node200.setDocAction(MWFNode.DOCACTION_Complete); + node200.setPosition(170, 120); + node200.save(); + MWFNodeNext tr100_200 = new MWFNodeNext(node100, node200.getAD_WF_Node_ID()); + tr100_200.setEntityType (ENTITYTYPE_Dictionary); + tr100_200.setDescription("(Standard Transition)"); + tr100_200.setSeqNo(100); + tr100_200.save(); + + + /** + Env.setContext(Env.getCtx(), "#AD_Client_ID ", "11"); + Env.setContext(Env.getCtx(), "#AD_Org_ID ", "11"); + Env.setContext(Env.getCtx(), "#AD_User_ID ", "100"); + // + int AD_Workflow_ID = 115; // Requisition WF + int M_Requsition_ID = 100; + MRequisition req = new MRequisition (Env.getCtx(), M_Requsition_ID); + req.setDocStatus(DocAction.DOCSTATUS_Drafted); + req.save(); + Log.setTraceLevel(8); + System.out.println("---------------------------------------------------"); + MWorkflow wf = MWorkflow.get (Env.getCtx(), AD_Workflow_ID); + **/ + // wf.start(M_Requsition_ID); + + } // main + +} // MWorkflow_ID diff --git a/base/src/org/compiere/wf/MWorkflowAccess.java b/base/src/org/compiere/wf/MWorkflowAccess.java new file mode 100644 index 0000000000..7bff8dea6f --- /dev/null +++ b/base/src/org/compiere/wf/MWorkflowAccess.java @@ -0,0 +1,76 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.sql.*; +import java.util.*; +import org.compiere.model.*; + + +/** + * Worflow Access Model + * + * @author Jorg Janke + * @version $Id: MWorkflowAccess.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MWorkflowAccess extends X_AD_Workflow_Access +{ + + /** + * Standard Constructor + * @param ctx context + * @param ignored - + * @param trxName transaction + */ + public MWorkflowAccess (Properties ctx, int ignored, String trxName) + { + super(ctx, 0, trxName); + if (ignored != 0) + throw new IllegalArgumentException("Multi-Key"); + else + { + // setAD_Role_ID (0); + // setAD_Workflow_ID (0); + setIsReadWrite (true); + } + } // MWorkflowAccess + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MWorkflowAccess (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MWorkflowAccess + + /** + * Parent Constructor + * @param parent parent + * @param AD_Role_ID role id + */ + public MWorkflowAccess (MWorkflow parent, int AD_Role_ID) + { + super (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setAD_Workflow_ID(parent.getAD_Workflow_ID()); + setAD_Role_ID (AD_Role_ID); + } // MWorkflowAccess + +} // MWorkflowAccess diff --git a/base/src/org/compiere/wf/MWorkflowProcessor.java b/base/src/org/compiere/wf/MWorkflowProcessor.java new file mode 100644 index 0000000000..c44e23c617 --- /dev/null +++ b/base/src/org/compiere/wf/MWorkflowProcessor.java @@ -0,0 +1,179 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.sql.*; +import java.util.*; +import org.compiere.model.*; +import java.util.logging.*; +import org.compiere.util.*; + + +/** + * Workflow Processor Model + * + * @author Jorg Janke + * @version $Id: MWorkflowProcessor.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MWorkflowProcessor extends X_AD_WorkflowProcessor + implements AdempiereProcessor +{ + /** + * Get Active + * @param ctx context + * @return active processors + */ + public static MWorkflowProcessor[] getActive (Properties ctx) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM AD_WorkflowProcessor WHERE IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MWorkflowProcessor (ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MWorkflowProcessor[] retValue = new MWorkflowProcessor[list.size ()]; + list.toArray (retValue); + return retValue; + } // getActive + + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MWorkflowProcessor.class); + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param AD_WorkflowProcessor_ID id + * @param trxName transaction + */ + public MWorkflowProcessor (Properties ctx, int AD_WorkflowProcessor_ID, String trxName) + { + super (ctx, AD_WorkflowProcessor_ID, trxName); + } // MWorkflowProcessor + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MWorkflowProcessor (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MWorkflowProcessor + + /** + * Get Server ID + * @return id + */ + public String getServerID () + { + return "WorkflowProcessor" + get_ID(); + } // getServerID + + /** + * Get Date Next Run + * @param requery requery + * @return date next run + */ + public Timestamp getDateNextRun (boolean requery) + { + if (requery) + load(get_TrxName()); + return getDateNextRun(); + } // getDateNextRun + + /** + * Get Logs + * @return logs + */ + public AdempiereProcessorLog[] getLogs () + { + ArrayList list = new ArrayList(); + String sql = "SELECT * " + + "FROM AD_WorkflowProcessorLog " + + "WHERE AD_WorkflowProcessor_ID=? " + + "ORDER BY Created DESC"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getAD_WorkflowProcessor_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MWorkflowProcessorLog (getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MWorkflowProcessorLog[] retValue = new MWorkflowProcessorLog[list.size ()]; + list.toArray (retValue); + return retValue; + } // getLogs + + /** + * Delete old Request Log + * @return number of records + */ + public int deleteLog() + { + if (getKeepLogDays() < 1) + return 0; + String sql = "DELETE AD_WorkflowProcessorLog " + + "WHERE AD_WorkflowProcessor_ID=" + getAD_WorkflowProcessor_ID() + + " AND (Created+" + getKeepLogDays() + ") < SysDate"; + int no = DB.executeUpdate(sql, get_TrxName()); + return 0; + } // deleteLog + +} // MWorkflowProcessor diff --git a/base/src/org/compiere/wf/MWorkflowProcessorLog.java b/base/src/org/compiere/wf/MWorkflowProcessorLog.java new file mode 100644 index 0000000000..be039c3c97 --- /dev/null +++ b/base/src/org/compiere/wf/MWorkflowProcessorLog.java @@ -0,0 +1,74 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.sql.*; +import java.util.*; + +import org.compiere.model.*; + + +/** + * Processor Log + * + * @author Jorg Janke + * @version $Id: MWorkflowProcessorLog.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + */ +public class MWorkflowProcessorLog extends X_AD_WorkflowProcessorLog + implements AdempiereProcessorLog +{ + /** + * Standard Constructor + * @param ctx context + * @param AD_WorkflowProcessorLog_ID id + * @param trxName transaction + */ + public MWorkflowProcessorLog (Properties ctx, int AD_WorkflowProcessorLog_ID, String trxName) + { + super (ctx, AD_WorkflowProcessorLog_ID, trxName); + if (AD_WorkflowProcessorLog_ID == 0) + { + setIsError (false); + } + } // MWorkflowProcessorLog + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MWorkflowProcessorLog (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MWorkflowProcessorLog + + /** + * Parent Constructor + * @param parent parent + * @param Summary Summary + */ + public MWorkflowProcessorLog (MWorkflowProcessor parent, String Summary) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setAD_WorkflowProcessor_ID(parent.getAD_WorkflowProcessor_ID()); + setSummary(Summary); + } // MWorkflowProcessorLog + + +} // MWorkflowProcessorLog diff --git a/base/src/org/compiere/wf/WFActivityManage.java b/base/src/org/compiere/wf/WFActivityManage.java new file mode 100644 index 0000000000..62da765a13 --- /dev/null +++ b/base/src/org/compiere/wf/WFActivityManage.java @@ -0,0 +1,112 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.process.*; + +/** + * Manage Workflow Activity + * + * @author Jorg Janke + * @version $Id: WFActivityManage.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class WFActivityManage extends SvrProcess +{ + /** Abort It */ + private boolean p_IsAbort = false; + /** New User */ + private int p_AD_User_ID = 0; + /** New Responsible */ + private int p_AD_WF_Responsible_ID = 0; + /** Record */ + private int p_AD_WF_Activity_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("IsAbort")) + p_IsAbort = "Y".equals(para[i].getParameter()); + else if (name.equals("AD_User_ID")) + p_AD_User_ID = para[i].getParameterAsInt(); + else if (name.equals("AD_WF_Responsible_ID")) + p_AD_WF_Responsible_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_AD_WF_Activity_ID = getRecord_ID(); + } // prepare + + /** + * Perform process. + * @return Message (variables are parsed) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + MWFActivity activity = new MWFActivity (getCtx(), p_AD_WF_Activity_ID, get_TrxName()); + log.info("doIt - " + activity); + + MUser user = MUser.get(getCtx(), getAD_User_ID()); + // Abort + if (p_IsAbort) + { + String msg = user.getName() + ": Abort"; + activity.setTextMsg(msg); + activity.setAD_User_ID(getAD_User_ID()); + activity.setWFState(StateEngine.STATE_Aborted); + return msg; + } + String msg = null; + // Change User + if (p_AD_User_ID != 0 && activity.getAD_User_ID() != p_AD_User_ID) + { + MUser from = MUser.get(getCtx(), activity.getAD_User_ID()); + MUser to = MUser.get(getCtx(), p_AD_User_ID); + msg = user.getName() + ": " + from.getName() + " -> " + to.getName(); + activity.setTextMsg(msg); + activity.setAD_User_ID(p_AD_User_ID); + } + // Change Responsible + if (p_AD_WF_Responsible_ID != 0 && activity.getAD_WF_Responsible_ID() != p_AD_WF_Responsible_ID) + { + MWFResponsible from = MWFResponsible.get(getCtx(), activity.getAD_WF_Responsible_ID()); + MWFResponsible to = MWFResponsible.get(getCtx(), p_AD_WF_Responsible_ID); + String msg1 = user.getName() + ": " + from.getName() + " -> " + to.getName(); + activity.setTextMsg(msg1); + activity.setAD_WF_Responsible_ID(p_AD_WF_Responsible_ID); + if (msg == null) + msg = msg1; + else + msg += " - " + msg1; + } + // + activity.save(); + + return msg; + } // doIt + +} // WFActivityManage diff --git a/base/src/org/compiere/wf/WFProcessManage.java b/base/src/org/compiere/wf/WFProcessManage.java new file mode 100644 index 0000000000..3a370256dd --- /dev/null +++ b/base/src/org/compiere/wf/WFProcessManage.java @@ -0,0 +1,112 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.util.logging.*; +import org.compiere.model.*; +import org.compiere.process.*; + +/** + * Manage Workflow Process + * + * @author Jorg Janke + * @version $Id: WFProcessManage.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class WFProcessManage extends SvrProcess +{ + /** Abort It */ + private boolean p_IsAbort = false; + /** New User */ + private int p_AD_User_ID = 0; + /** New Responsible */ + private int p_AD_WF_Responsible_ID = 0; + /** Record */ + private int p_AD_WF_Process_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare() + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("IsAbort")) + p_IsAbort = "Y".equals(para[i].getParameter()); + else if (name.equals("AD_User_ID")) + p_AD_User_ID = para[i].getParameterAsInt(); + else if (name.equals("AD_WF_Responsible_ID")) + p_AD_WF_Responsible_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "Unknown Parameter: " + name); + } + p_AD_WF_Process_ID = getRecord_ID(); + } // prepare + + /** + * Perform process. + * @return Message (variables are parsed) + * @throws Exception if not successful + */ + protected String doIt() throws Exception + { + MWFProcess process = new MWFProcess (getCtx(), p_AD_WF_Process_ID, get_TrxName()); + log.info("doIt - " + process); + + MUser user = MUser.get(getCtx(), getAD_User_ID()); + // Abort + if (p_IsAbort) + { + String msg = user.getName() + ": Abort"; + process.setTextMsg(msg); + process.setAD_User_ID(getAD_User_ID()); + process.setWFState(StateEngine.STATE_Aborted); + return msg; + } + String msg = null; + // Change User + if (p_AD_User_ID != 0 && process.getAD_User_ID() != p_AD_User_ID) + { + MUser from = MUser.get(getCtx(), process.getAD_User_ID()); + MUser to = MUser.get(getCtx(), p_AD_User_ID); + msg = user.getName() + ": " + from.getName() + " -> " + to.getName(); + process.setTextMsg(msg); + process.setAD_User_ID(p_AD_User_ID); + } + // Change Responsible + if (p_AD_WF_Responsible_ID != 0 && process.getAD_WF_Responsible_ID() != p_AD_WF_Responsible_ID) + { + MWFResponsible from = MWFResponsible.get(getCtx(), process.getAD_WF_Responsible_ID()); + MWFResponsible to = MWFResponsible.get(getCtx(), p_AD_WF_Responsible_ID); + String msg1 = user.getName() + ": " + from.getName() + " -> " + to.getName(); + process.setTextMsg(msg1); + process.setAD_WF_Responsible_ID(p_AD_WF_Responsible_ID); + if (msg == null) + msg = msg1; + else + msg += " - " + msg1; + } + // + process.save(); + + return "OK"; + } // doIt + +} // WFProcessManage diff --git a/base/src/org/compiere/wf/WorkflowMoveToClient.java b/base/src/org/compiere/wf/WorkflowMoveToClient.java new file mode 100644 index 0000000000..1513913bfa --- /dev/null +++ b/base/src/org/compiere/wf/WorkflowMoveToClient.java @@ -0,0 +1,121 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import java.util.logging.*; +import org.compiere.util.*; +import org.compiere.process.*; + +/** + * Move Workflow Customizations to Client + * + * @author Jorg Janke + * @version $Id: WorkflowMoveToClient.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class WorkflowMoveToClient extends SvrProcess +{ + /** The new Client */ + private int p_AD_Client_ID = 0; + /** The Workflow */ + private int p_AD_Workflow_ID = 0; + + /** + * Prepare - e.g., get Parameters. + */ + protected void prepare () + { + ProcessInfoParameter[] para = getParameter(); + for (int i = 0; i < para.length; i++) + { + String name = para[i].getParameterName(); + if (para[i].getParameter() == null) + ; + else if (name.equals("AD_Client_ID")) + p_AD_Client_ID = para[i].getParameterAsInt(); + else if (name.equals("AD_Workflow_ID")) + p_AD_Workflow_ID = para[i].getParameterAsInt(); + else + log.log(Level.SEVERE, "prepare - Unknown Parameter: " + name); + } + } // prepare + + /** + * Process + * @return message + * @throws Exception + */ + protected String doIt () throws Exception + { + log.info("doIt - AD_Client_ID=" + p_AD_Client_ID + ", AD_Workflow_ID=" + p_AD_Workflow_ID); + + int changes = 0; + // WF + String sql = "UPDATE AD_Workflow SET AD_Client_ID=" + p_AD_Client_ID + + " WHERE AD_Client_ID=0 AND EntityType NOT IN ('D','C')" + + " AND AD_Workflow_ID=" + p_AD_Workflow_ID; + int no = DB.executeUpdate(sql, get_TrxName()); + if (no == -1) + throw new AdempiereSystemError ("Error updating Workflow"); + changes += no; + + // Node + sql = "UPDATE AD_WF_Node SET AD_Client_ID=" + p_AD_Client_ID + + " WHERE AD_Client_ID=0 AND EntityType NOT IN ('D','C')" + + " AND AD_Workflow_ID=" + p_AD_Workflow_ID; + no = DB.executeUpdate(sql, get_TrxName()); + if (no == -1) + throw new AdempiereSystemError ("Error updating Workflow Node"); + changes += no; + + // Node Next + sql = "UPDATE AD_WF_NodeNext SET AD_Client_ID=" + p_AD_Client_ID + + " WHERE AD_Client_ID=0 AND EntityType NOT IN ('D','C')" + + " AND (AD_WF_Node_ID IN (SELECT AD_WF_Node_ID FROM AD_WF_Node WHERE AD_Workflow_ID=" + p_AD_Workflow_ID + + ") OR AD_WF_Next_ID IN (SELECT AD_WF_Node_ID FROM AD_WF_Node WHERE AD_Workflow_ID=" + p_AD_Workflow_ID + + "))"; + no = DB.executeUpdate(sql, get_TrxName()); + if (no == -1) + throw new AdempiereSystemError ("Error updating Workflow Transition"); + changes += no; + + // Node Parameters + sql = "UPDATE AD_WF_Node_Para SET AD_Client_ID=" + p_AD_Client_ID + + " WHERE AD_Client_ID=0 AND EntityType NOT IN ('D','C')" + + " AND AD_WF_Node_ID IN (SELECT AD_WF_Node_ID FROM AD_WF_Node WHERE AD_Workflow_ID=" + p_AD_Workflow_ID + + ")"; + no = DB.executeUpdate(sql, get_TrxName()); + if (no == -1) + throw new AdempiereSystemError ("Error updating Workflow Node Parameters"); + changes += no; + + // Node Next Condition + sql = "UPDATE AD_WF_NextCondition SET AD_Client_ID=" + p_AD_Client_ID + + " WHERE AD_Client_ID=0 AND EntityType NOT IN ('D','C')" + + " AND AD_WF_NodeNext_ID IN (" + + "SELECT AD_WF_NodeNext_ID FROM AD_WF_NodeNext " + + "WHERE AD_WF_Node_ID IN (SELECT AD_WF_Node_ID FROM AD_WF_Node WHERE AD_Workflow_ID=" + p_AD_Workflow_ID + + ") OR AD_WF_Next_ID IN (SELECT AD_WF_Node_ID FROM AD_WF_Node WHERE AD_Workflow_ID=" + p_AD_Workflow_ID + + "))"; + no = DB.executeUpdate(sql, get_TrxName()); + if (no == -1) + throw new AdempiereSystemError ("Error updating Workflow Transition Condition"); + changes += no; + + return "@Updated@ - #" + changes; + } // doIt + +} // WorkflowMoveToClient diff --git a/base/src/org/compiere/wf/WorkflowValidate.java b/base/src/org/compiere/wf/WorkflowValidate.java new file mode 100644 index 0000000000..5b5cb8306e --- /dev/null +++ b/base/src/org/compiere/wf/WorkflowValidate.java @@ -0,0 +1,60 @@ +/****************************************************************************** + * 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. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.wf; + +import org.compiere.process.*; +import org.compiere.util.*; + + +/** + * Validate Workflow Process + * + * @author Jorg Janke + * @version $Id: WorkflowValidate.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ + */ +public class WorkflowValidate extends SvrProcess +{ + private int p_AD_Worlflow_ID = 0; + + /** + * Prepare + */ + protected void prepare () + { + p_AD_Worlflow_ID = getRecord_ID(); + } // prepare + + /** + * Process + * @return info + * @throws Exception + */ + protected String doIt () throws Exception + { + MWorkflow wf = MWorkflow.get (getCtx(), p_AD_Worlflow_ID); + log.info("WF=" + wf); + + String msg = wf.validate(); + wf.save(); + if (msg.length() > 0) + throw new AdempiereUserError(Msg.getMsg(getCtx(), "WorflowNotValid") + + " - " + msg); + return wf.isValid() ? "@OK@" : "@Error@"; + } // doIt + + +} // WorkflowValidate diff --git a/base/xdoclet-build.xml b/base/xdoclet-build.xml new file mode 100644 index 0000000000..24bb7a24a5 --- /dev/null +++ b/base/xdoclet-build.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +