move branch adempire311 to trunk

This commit is contained in:
vpj-cd 2006-11-17 03:13:45 +00:00
parent 79bca7aaef
commit 9802eea0be
83 changed files with 18937 additions and 0 deletions

14
serverRoot/.classpath Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/server"/>
<classpathentry kind="src" path="src/main/servlet"/>
<classpathentry kind="src" path="src/main/ejb"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="src" path="/tools"/>
<classpathentry kind="src" path="/dbPort"/>
<classpathentry kind="src" path="/base"/>
<classpathentry kind="src" path="/looks"/>
<classpathentry kind="lib" path="/interfaces/Interfaces.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/print"/>
<classpathentry kind="output" path="build/classes"/>
</classpath>

2
serverRoot/.packaging Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<configurations/>

22
serverRoot/.project Normal file
View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>serverRoot</name>
<comment></comment>
<projects>
<project>base</project>
<project>dbPort</project>
<project>looks</project>
<project>server</project>
<project>tools</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

2
serverRoot/.xdoclet Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<configurations/>

19
serverRoot/RUN_build.bat Normal file
View File

@ -0,0 +1,19 @@
@Title Build Adempiere Root
@Rem $Header: /cvsroot/adempiere/serverRoot/RUN_build.bat,v 1.11 2005/09/16 00:50:14 jjanke Exp $
@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 main
@Echo Done ...
@sleep 60
@exit
:NOBUILD
@Echo Check myDevEnv.bat (copy from myDevEnvTemplate.bat)
@Pause

18
serverRoot/RUN_build.sh Normal file
View File

@ -0,0 +1,18 @@
# Module compiling script
# Ported from Windows script Marek Mosiewicz<marek.mosiewicz@jotel.com.pl>
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

View File

@ -0,0 +1,33 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>JBuilder Project ServerRoot.jpx</title>
</head>
<body>
<h1>Project ServerRoot Notes</h1>
<hr><table border="0">
<tr><th align="left" valign="top">Title:</th><td align="left" valign="top">
<!-- Type Title below -->
</td></tr>
<tr><th align="left" valign="top">Author:</th><td align="left" valign="top">
<!-- Type Author below -->
</td></tr>
<tr><th align="left" valign="top">Company:</th><td align="left" valign="top">
<!-- Type Company below -->
</td></tr>
<tr><th align="left" valign="top">Description:</th><td align="left" valign="top">
<!-- Type Description below -->
</td></tr>
</table><hr>
<h2>Things to do... </h2>
<ol>
<!-- Edit this section to keep track of your to do items -->
<li>First
<li>Second
</ol>
</body>
</html>

235
serverRoot/build.xml Normal file
View File

@ -0,0 +1,235 @@
<?xml version="1.0"?>
<!-- ============================================= -->
<!-- Adempiere Server Root -->
<!-- ============================================= -->
<!-- $Header: /cvs/adempiere/serverRoot/build.xml,v 1.4 2006/06/10 21:58:02 jjanke Exp $-->
<project name="adempiereRoot" default="main" basedir=".">
<property environment="env"/>
<property name="xdoclet.home" value="../tools" />
<property name="xdoclet.force" value="false" />
<property name="ejb.version" value="2.0" />
<property name="src.dir" value="${basedir}/src"/>
<property name="src.main.dir" value="${src.dir}/main"/>
<property name="src.ear.dir" value="${src.dir}/ear"/>
<property name="src.ejb.dir" value="${src.main.dir}/ejb"/>
<property name="src.servlet.dir" value="${src.main.dir}/servlet"/>
<property name="src.server.dir" value="${src.main.dir}/server"/>
<property name="src.resources.dir" value="${src.dir}/resources"/>
<property name="src.web.dir" value="${src.dir}/web"/>
<property name="build.dir" value="${basedir}/build"/>
<property name="build.tmp.dir" value="${build.dir}/tmp"/>
<property name="build.deploy.dir" value="${build.dir}/deploy"/>
<property name="build.classes.dir" value="${build.dir}/classes"/>
<property name="build.war.dir" value="${build.dir}/war"/>
<property name="interfaces.dir" value="../interfaces"/>
<property name="src.interfaces.dir" value="../interfaces/src"/>
<property name="build.interfaces.dir" value="../interfaces/classes"/>
<target name="adempiereRootInit">
<echo message="=========== Build Server Root"/>
<tstamp/>
<uptodate property="interfaces.uptodate"
targetfile="${interfaces.dir}/Interfaces.jar">
<srcfiles dir="${src.ejb.dir}" includes="**/*.java"/>
<srcfiles dir="${src.interfaces.dir}" includes="**/*.java"/>
</uptodate>
</target>
<path id="xdoclet.path">
<pathelement location="${xdoclet.home}/lib/ant.jar" />
<pathelement location="${xdoclet.home}/lib/log4j.jar" />
<pathelement location="${xdoclet.home}/lib/commons-logging.jar" />
<pathelement location="${xdoclet.home}/lib/xdoclet-1.2.3.jar" />
<pathelement location="${xdoclet.home}/lib/xdoclet-web-module-1.2.3.jar" />
<pathelement location="${xdoclet.home}/lib/xdoclet-ejb-module-1.2.3.jar" />
<pathelement location="${xdoclet.home}/lib/xjavadoc-1.1.jar" />
<pathelement location="${xdoclet.home}/lib/xdoclet-xdoclet-module-1.2.3.jar" />
<pathelement location="${xdoclet.home}/lib/commons-collections-3.1.jar" />
</path>
<path id="base.path">
<path refid="xdoclet.path"/>
<pathelement location="../lib/Adempiere.jar" />
<pathelement location="../lib/CSTools.jar" />
<pathelement location="../tools/lib/j2ee.jar" />
<pathelement location="${build.classes.dir}" />
</path>
<!-- =================================================================== -->
<!-- Generates the necessary EJB classes and deployment descriptors -->
<!-- =================================================================== -->
<target name="adempiereRootXdoclet" depends="adempiereRootInit">
<echo message="XDoclet=${xdoclet.home}"/>
<echo message="UpToDate=${interfaces.uptodate}"/>
<taskdef
name="ejbdoclet"
classname="xdoclet.modules.ejb.EjbDocletTask"
classpathref="base.path"/>
<ejbdoclet
destdir="${src.interfaces.dir}"
excludedTags="@version,@author"
ejbspec="${ejb.version}"
mergedir="${src.resources.dir}/xdoclet"
force="${xdoclet.force}">
<fileset dir="${src.ejb.dir}">
<include name="**/*Bean.java"/>
</fileset>
<packageSubstitution packages="session,entity" substituteWith="interfaces"/>
<homeinterface/>
<localinterface/>
<localhomeinterface/>
<remoteinterface/>
<deploymentdescriptor destdir="${build.dir}/META-INF"/>
</ejbdoclet>
</target>
<!-- =========================================== -->
<!-- Compiles the source code -->
<!-- =========================================== -->
<target name="adempiereRootCompile" depends="adempiereRootXdoclet">
<mkdir dir="${build.classes.dir}"/>
<!-- Compile all -->
<javac
destdir="${build.classes.dir}"
debug="on"
deprecation="off"
optimize="on"
classpathref="base.path">
<src path="${src.ejb.dir}"/>
<src path="${src.interfaces.dir}"/>
<src path="${src.servlet.dir}"/>
<src path="${src.server.dir}"/>
</javac>
</target>
<!-- =========================================== -->
<!-- Creates the jar archives -->
<!-- =========================================== -->
<target name="adempiereRootJar" depends="adempiereRootCompile">
<mkdir dir="${build.deploy.dir}"/>
<!-- Jar -->
<jar
jarfile="${build.deploy.dir}/adempiereRoot.jar">
<fileset
dir="${build.classes.dir}">
</fileset>
<fileset
dir="${build.dir}"
includes="META-INF/**">
</fileset>
<manifest>
<attribute name="Specification-Title" value="AdempiereRoot"/>
<attribute name="Specification-Version" value="${env.ADEMPIERE_VERSION}"/>
<attribute name="Specification-Vendor" value="Adempiere"/>
<attribute name="Implementation-Title" value="AdempiereRoot ${env.ADEMPIERE_VERSION}"/>
<attribute name="Implementation-Version" value="${env.ADEMPIERE_VERSION} ${DSTAMP}-${TSTAMP}"/>
<attribute name="Implementation-Vendor" value="${env.ADEMPIERE_VENDOR}"/>
<attribute name="Implementation-URL" value="http://www.adempiere.com"/>
<attribute name="Class-Path" value="Adempiere.jar AdempiereSLib.jar"/>
</manifest>
</jar>
</target>
<!-- =========================================== -->
<!-- Creates the war archives -->
<!-- =========================================== -->
<target name="adempiereRootWar" depends="adempiereRootJar">
<war
warfile="${build.deploy.dir}/adempiereRootBase.war"
webxml="${src.web.dir}/WEB-INF/web.xml">
<!-- copy from web -->
<fileset dir="${src.web.dir}" excludes="**/web.xml,**/lib/**,**/classes/**"/>
<!-- WEB-INF/lib -->
<lib dir="${src.web.dir}/WEB-INF/lib"/>
<manifest>
<attribute name="Specification-Title" value="AdempiereRootWar"/>
<attribute name="Specification-Version" value="${env.ADEMPIERE_VERSION}"/>
<attribute name="Specification-Vendor" value="Adempiere"/>
<attribute name="Implementation-Title" value="AdempiereRootWar ${env.ADEMPIERE_VERSION}"/>
<attribute name="Implementation-Version" value="${env.ADEMPIERE_VERSION} ${DSTAMP}-${TSTAMP}"/>
<attribute name="Implementation-Vendor" value="${env.ADEMPIERE_VENDOR}"/>
<attribute name="Implementation-URL" value="http://www.adempiere.com"/>
<attribute name="Class-Path" value="Adempiere.jar AdempiereSLib.jar"/>
</manifest>
</war>
</target>
<!-- =========================================== -->
<!-- Creates the interface archive -->
<!-- =========================================== -->
<target name="adempiereRootInterfaces" depends="adempiereRootCompile">
<!-- Copy MBeans to interfaces -->
<copy todir="${src.interfaces.dir}">
<fileset dir="${src.server.dir}" includes="**/*MBean.java"/>
</copy>
<!-- Compile interfaces -->
<mkdir dir="${build.interfaces.dir}"/>
<javac
srcdir="${src.interfaces.dir}"
destdir="${build.interfaces.dir}"
debug="off"
deprecation="on"
optimize="on"
classpathref="base.path">
</javac>
<!-- Jar Interfaces -->
<jar
destfile="${interfaces.dir}/Interfaces.jar"
basedir="${build.interfaces.dir}" />
</target>
<!-- =========================================== -->
<!-- Deploy Server Files -->
<!-- =========================================== -->
<target name="adempiereRootDeployServer" depends="adempiereRootJar,adempiereRootWar,adempiereRootInterfaces">
<copy todir="../lib">
<fileset dir="${build.deploy.dir}"/>
</copy>
<copy file="${src.ear.dir}/application.xml"
tofile="../lib/adempiereRoot.xml"/>
</target>
<!-- =========================================== -->
<!-- Creates the binary structure -->
<!-- =========================================== -->
<target name="main" depends="adempiereRootDeployServer">
</target>
<!-- =========================================== -->
<!-- Cleans up the current build -->
<!-- =========================================== -->
<target name="clean">
<delete dir="${build.dir}" failonerror="false"/>
<!-- This is boring to delete these
<delete>
<fileset dir="${src.interfaces.dir}" includes="**/*.java"/>
</delete>
-->
</target>
</project>

View File

@ -0,0 +1,5 @@
@Rem API Documentation for Server
call ..\doc\documentation.bat "src\main\client;src\main\ejb;src\main\server;src\main\servlet" doc -private
@pause

4
serverRoot/packages.txt Normal file
View File

@ -0,0 +1,4 @@
org.compiere.client
org.compiere.session
org.compiere.server
org.compiere.web

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project default="_generation_" name="Packaging Generator">
<target name="_generation_" depends=""/>
</project>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 1999-2005 Jorg Janke ComPiere, Inc.
@version $Id: application.xml,v 1.3 2006/06/12 00:59:05 jjanke Exp $
-->
<application version="1.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/application_1_4.xsd">
<display-name>adempiereRoot</display-name>
<description>Adempiere Root</description>
<module>
<java>AdempiereSLib.jar</java>
</module>
<module>
<java>Adempiere.jar</java>
</module>
<module>
<ejb>adempiereRoot.jar</ejb>
</module>
<module>
<web>
<web-uri>adempiereRoot.war</web-uri>
<context-root>/admin</context-root>
</web>
</module>
</application>

View File

@ -0,0 +1,669 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.session;
import java.io.*;
import java.sql.*;
import java.util.*;
import java.util.logging.*;
import javax.ejb.*;
import javax.sql.*;
import org.compiere.*;
import org.compiere.acct.*;
import org.compiere.model.*;
import org.compiere.process.*;
import org.compiere.util.*;
import org.compiere.wf.*;
/**
* Adempiere Server Bean.
*
* @ejb.bean name="adempiere/Server"
* display-name="Adempiere Server Session Bean"
* type="Stateless"
* view-type="both"
* transaction-type="Bean"
* jndi-name="adempiere/Server"
* local-jndi-name="adempiere/ServerLocal"
*
* @ejb.ejb-ref ejb-name="adempiere/Server"
* view-type="both"
* ref-name="adempiere/Server"
* @ejb.ejb-ref ejb-name="adempiere/Server"
* view-type="local"
* ref-name="adempiere/ServerLocal"
*
* @author Jorg Janke
* @version $Id: ServerBean.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class ServerBean implements SessionBean
{
/** Context */
private SessionContext m_Context;
/** Logger */
private static CLogger log = CLogger.getCLogger(ServerBean.class);
//
private static int s_no = 0;
private int m_no = 0;
//
private int m_windowCount = 0;
private int m_postCount = 0;
private int m_processCount = 0;
private int m_workflowCount = 0;
private int m_paymentCount = 0;
private int m_nextSeqCount = 0;
private int m_stmt_rowSetCount = 0;
private int m_stmt_updateCount = 0;
private int m_cacheResetCount = 0;
private int m_updateLOBCount = 0;
/**
* Get and create Window Model Value Object
* @ejb.interface-method view-type="both"
*
* @param ctx Environment Properties
* @param WindowNo number of this window
* @param AD_Window_ID the internal number of the window, if not 0, AD_Menu_ID is ignored
* @param AD_Menu_ID ine internal menu number, used when AD_Window_ID is 0
* @return initialized Window Model
*/
public GridWindowVO getWindowVO (Properties ctx, int WindowNo, int AD_Window_ID, int AD_Menu_ID)
{
log.info ("getWindowVO[" + m_no + "] Window=" + AD_Window_ID);
// log.fine(ctx);
GridWindowVO vo = GridWindowVO.create(ctx, WindowNo, AD_Window_ID, AD_Menu_ID);
m_windowCount++;
return vo;
} // getWindowVO
/**
* Post Immediate
* @ejb.interface-method view-type="both"
*
* @param ctx Client Context
* @param AD_Client_ID Client ID of Document
* @param AD_Table_ID Table ID of Document
* @param Record_ID Record ID of this document
* @param force force posting
* @param trxName transaction
* @return null, if success or error message
*/
public String postImmediate (Properties ctx,
int AD_Client_ID, int AD_Table_ID, int Record_ID, boolean force, String trxName)
{
log.info ("[" + m_no + "] Table=" + AD_Table_ID + ", Record=" + Record_ID);
m_postCount++;
MAcctSchema[] ass = MAcctSchema.getClientAcctSchema(ctx, AD_Client_ID);
return Doc.postImmediate(ass, AD_Table_ID, Record_ID, force, trxName);
} // postImmediate
/*************************************************************************
* Get Prepared Statement ResultSet
* @ejb.interface-method view-type="both"
*
* @param info Result info
* @return RowSet
* @throws NotSerializableException
*/
public RowSet pstmt_getRowSet (CStatementVO info)
throws NotSerializableException
{
log.finer("[" + m_no + "]");
m_stmt_rowSetCount++;
CPreparedStatement pstmt = new CPreparedStatement(info);
return pstmt.remote_getRowSet();
} // pstmt_getRowSet
/**
* Get Statement ResultSet
* @ejb.interface-method view-type="both"
*
* @param info Result info
* @return RowSet
*/
public RowSet stmt_getRowSet (CStatementVO info)
{
log.finer("[" + m_no + "]");
m_stmt_rowSetCount++;
CStatement stmt = new CStatement(info);
return stmt.remote_getRowSet();
} // stmt_getRowSet
/**
* Execute Update
* @ejb.interface-method view-type="both"
*
* @param info Result info
* @return row count
*/
public int stmt_executeUpdate (CStatementVO info)
{
log.finer("[" + m_no + "]");
m_stmt_updateCount++;
if (info.getParameterCount() == 0)
{
CStatement stmt = new CStatement(info);
return stmt.remote_executeUpdate();
}
CPreparedStatement pstmt = new CPreparedStatement(info);
return pstmt.remote_executeUpdate();
} // stmt_executeUpdate
/*************************************************************************
* Get next number for Key column = 0 is Error.
* @ejb.interface-method view-type="both"
*
* @param AD_Client_ID client
* @param TableName table name
* @param trxName optional Transaction Name
* @return next no
*/
public int getNextID (int AD_Client_ID, String TableName, String trxName)
{
int retValue = MSequence.getNextID (AD_Client_ID, TableName, trxName);
log.finer("[" + m_no + "] " + TableName + " = " + retValue);
m_nextSeqCount++;
return retValue;
} // getNextID
/**
* Get Document No from table
* @ejb.interface-method view-type="both"
*
* @param AD_Client_ID client
* @param TableName table name
* @param trxName optional Transaction Name
* @return document no or null
*/
public String getDocumentNo (int AD_Client_ID, String TableName, String trxName)
{
m_nextSeqCount++;
String dn = MSequence.getDocumentNo (AD_Client_ID, TableName, trxName);
if (dn == null) // try again
dn = MSequence.getDocumentNo (AD_Client_ID, TableName, trxName);
return dn;
} // GetDocumentNo
/**
* Get Document No based on Document Type
* @ejb.interface-method view-type="both"
*
* @param C_DocType_ID document type
* @param trxName optional Transaction Name
* @return document no or null
*/
public String getDocumentNo (int C_DocType_ID, String trxName)
{
m_nextSeqCount++;
String dn = MSequence.getDocumentNo (C_DocType_ID, trxName);
if (dn == null) // try again
dn = MSequence.getDocumentNo (C_DocType_ID, trxName);
return dn;
} // getDocumentNo
/*************************************************************************
* Process Remote
* @ejb.interface-method view-type="both"
*
* @param ctx Context
* @param pi Process Info
* @return resulting Process Info
*/
public ProcessInfo process (Properties ctx, ProcessInfo pi)
{
String className = pi.getClassName();
log.info(className + " - " + pi);
m_processCount++;
// Get Class
Class clazz = null;
try
{
clazz = Class.forName (className);
}
catch (ClassNotFoundException ex)
{
log.log(Level.WARNING, className, ex);
pi.setSummary ("ClassNotFound", true);
return pi;
}
// Get Process
SvrProcess process = null;
try
{
process = (SvrProcess)clazz.newInstance ();
}
catch (Exception ex)
{
log.log(Level.WARNING, "Instance for " + className, ex);
pi.setSummary ("InstanceError", true);
return pi;
}
// Start Process
Trx trx = Trx.get(Trx.createTrxName("ServerPrc"), true);
try
{
boolean ok = process.startProcess (ctx, pi, trx);
pi = process.getProcessInfo();
trx.commit();
trx.close();
}
catch (Exception ex1)
{
trx.rollback();
trx.close();
pi.setSummary ("ProcessError", true);
return pi;
}
return pi;
} // process
/*************************************************************************
* Run Workflow (and wait) on Server
* @ejb.interface-method view-type="both"
*
* @param ctx Context
* @param pi Process Info
* @param AD_Workflow_ID id
* @return process info
*/
public ProcessInfo workflow (Properties ctx, ProcessInfo pi, int AD_Workflow_ID)
{
log.info ("[" + m_no + "] " + AD_Workflow_ID);
m_workflowCount++;
MWorkflow wf = MWorkflow.get (ctx, AD_Workflow_ID);
MWFProcess wfProcess = null;
if (pi.isBatch())
wfProcess = wf.start(pi); // may return null
else
wfProcess = wf.startWait(pi); // may return null
log.fine(pi.toString());
return pi;
} // workflow
/**
* Online Payment from Server
* @ejb.interface-method view-type="both"
* Called from MPayment processOnline
* @param ctx Context
* @param C_Payment_ID payment
* @param C_PaymentProcessor_ID processor
* @param trxName transaction
* @return true if approved
*/
public boolean paymentOnline (Properties ctx,
int C_Payment_ID, int C_PaymentProcessor_ID, String trxName)
{
MPayment payment = new MPayment (ctx, C_Payment_ID, trxName);
MPaymentProcessor mpp = new MPaymentProcessor (ctx, C_PaymentProcessor_ID, null);
log.info ("[" + m_no + "] " + payment + " - " + mpp);
m_paymentCount++;
boolean approved = false;
try
{
PaymentProcessor pp = PaymentProcessor.create(mpp, payment);
if (pp == null)
payment.setErrorMessage("No Payment Processor");
else
{
approved = pp.processCC ();
if (approved)
payment.setErrorMessage(null);
else
payment.setErrorMessage("From " + payment.getCreditCardName()
+ ": " + payment.getR_RespMsg());
}
}
catch (Exception e)
{
log.log(Level.SEVERE, "", e);
payment.setErrorMessage("Payment Processor Error");
}
payment.save();
return approved;
} // paymentOnline
/**
* Create EMail from Server (Request User)
* @ejb.interface-method view-type="both"
* @param ctx Context
* @param AD_Client_ID client
* @param to recipient email address
* @param subject subject
* @param message message
* @return EMail
*/
public EMail createEMail (Properties ctx, int AD_Client_ID,
String to, String subject, String message)
{
MClient client = MClient.get(ctx, AD_Client_ID);
return client.createEMail(to, subject, message);
} // createEMail
/**
* Create EMail from Server (Request User)
* @ejb.interface-method view-type="both"
* @param ctx Context
* @param AD_Client_ID client
* @param AD_User_ID user to send email from
* @param to recipient email address
* @param subject subject
* @param message message
* @return EMail
*/
public EMail createEMail (Properties ctx, int AD_Client_ID,
int AD_User_ID,
String to, String subject, String message)
{
MClient client = MClient.get(ctx, AD_Client_ID);
MUser from = new MUser (ctx, AD_User_ID, null);
return client.createEMail(from, to, subject, message);
} // createEMail
/**
* Create EMail from Server (Request User)
* @ejb.interface-method view-type="both"
* @param AD_Task_ID task
* @return execution trace
*/
public String executeTask (int AD_Task_ID)
{
MTask task = new MTask (Env.getCtx(), AD_Task_ID, null); // Server Context
return task.execute();
} // executeTask
/**
* Cash Reset
* @ejb.interface-method view-type="both"
*
* @param tableName table name
* @param Record_ID record or 0 for all
* @return number of records reset
*/
public int cacheReset (String tableName, int Record_ID)
{
log.config(tableName + " - " + Record_ID);
m_cacheResetCount++;
return CacheMgt.get().reset(tableName, Record_ID);
} // cacheReset
/**
* LOB update
* @ejb.interface-method view-type="both"
*
* @param sql table name
* @param displayType display type (i.e. BLOB/CLOB)
* @param value the data
* @return true if updated
*/
public boolean updateLOB (String sql, int displayType, Object value)
{
if (sql == null || value == null)
{
log.fine("No sql or data");
return false;
}
log.fine(sql);
m_updateLOBCount++;
boolean success = true;
Connection con = DB.createConnection(false, Connection.TRANSACTION_READ_COMMITTED);
PreparedStatement pstmt = null;
try
{
pstmt = con.prepareStatement(sql);
if (displayType == DisplayType.TextLong)
pstmt.setString(1, (String)value);
else
pstmt.setBytes(1, (byte[])value);
int no = pstmt.executeUpdate();
//
pstmt.close();
pstmt = null;
}
catch (Exception e)
{
log.log(Level.FINE, sql, e);
success = false;
}
// Close Statement
try
{
if (pstmt != null)
pstmt.close();
pstmt = null;
}
catch (Exception e)
{
pstmt = null;
}
// Success - commit local trx
if (success)
{
try
{
con.commit();
con.close();
con = null;
}
catch (Exception e)
{
log.log(Level.SEVERE, "commit" , e);
success = false;
}
}
// Error - roll back
if (!success)
{
log.severe ("rollback");
try
{
con.rollback();
con.close();
con = null;
}
catch (Exception ee)
{
log.log(Level.SEVERE, "rollback" , ee);
}
}
// Clean Connection
try
{
if (con != null)
con.close();
con = null;
}
catch (Exception e)
{
con = null;
}
return success;
} // updateLOB
/**************************************************************************
* Describes the instance and its content for debugging purpose
* @ejb.interface-method view-type="both"
* @return Debugging information about the instance and its content
*/
public String getStatus()
{
StringBuffer sb = new StringBuffer("ServerBean[");
sb.append(m_no)
.append("-Window=").append(m_windowCount)
.append(",Post=").append(m_postCount)
.append(",Process=").append(m_processCount)
.append(",NextSeq=").append(m_nextSeqCount)
.append(",Workflow=").append(m_workflowCount)
.append(",Payment=").append(m_paymentCount)
.append(",RowSet=").append(m_stmt_rowSetCount)
.append(",Update=").append(m_stmt_updateCount)
.append(",CacheReset=").append(m_cacheResetCount)
.append(",UpdateLob=").append(m_updateLOBCount)
.append("]");
return sb.toString();
} // getStatus
/**
* String Representation
* @return info
*/
public String toString()
{
return getStatus();
} // toString
/**************************************************************************
* Create the Session Bean
* @throws EJBException
* @throws CreateException
* @ejb.create-method view-type="both"
*/
public void ejbCreate() throws EJBException, CreateException
{
m_no = ++s_no;
try
{
Adempiere.startup(false);
}
catch (Exception ex)
{
log.log(Level.SEVERE, "ejbCreate", ex);
// throw new CreateException ();
}
log.info ("#" + getStatus());
} // ejbCreate
// -------------------------------------------------------------------------
// Framework Callbacks
// -------------------------------------------------------------------------
/**
* Method setSessionContext
* @param aContext SessionContext
* @throws EJBException
* @see javax.ejb.SessionBean#setSessionContext(SessionContext)
*/
public void setSessionContext (SessionContext aContext) throws EJBException
{
m_Context = aContext;
} // setSessionContext
/**
* Method ejbActivate
* @throws EJBException
* @see javax.ejb.SessionBean#ejbActivate()
*/
public void ejbActivate() throws EJBException
{
if (log == null)
log = CLogger.getCLogger(getClass());
log.info ("ejbActivate " + getStatus());
} // ejbActivate
/**
* Method ejbPassivate
* @throws EJBException
* @see javax.ejb.SessionBean#ejbPassivate()
*/
public void ejbPassivate() throws EJBException
{
log.info ("ejbPassivate " + getStatus());
} // ejbPassivate
/**
* Method ejbRemove
* @throws EJBException
* @see javax.ejb.SessionBean#ejbRemove()
*/
public void ejbRemove() throws EJBException
{
log.info ("ejbRemove " + getStatus());
} // ejbRemove
/**************************************************************************
* Dump SerialVersionUID of class
* @param clazz class
*/
protected static void dumpSVUID (Class clazz)
{
String s = clazz.getName()
+ " ==\nstatic final long serialVersionUID = "
+ java.io.ObjectStreamClass.lookup(clazz).getSerialVersionUID()
+ "L;\n";
System.out.println (s);
} // dumpSVUID
/**
* Print UID of used classes.
* R2.5.1h
org.compiere.process.ProcessInfo ==
static final long serialVersionUID = -1993220053515488725L;
org.compiere.util.CStatementVO ==
static final long serialVersionUID = -3393389471515956399L;
org.compiere.model.MQuery ==
static final long serialVersionUID = 1511402030597166113L;
org.compiere.model.POInfo ==
static final long serialVersionUID = -5976719579744948419L;
org.compiere.model.POInfoColumn ==
static final long serialVersionUID = -3983585608504631958L;
org.compiere.model.MWindowVO ==
static final long serialVersionUID = 3802628212531678981L;
org.compiere.model.MTabVO ==
static final long serialVersionUID = 9160212869277319305L;
org.compiere.model.MFieldVO ==
static final long serialVersionUID = 4385061125114436797L;
org.compiere.model.MLookupInfo ==
static final long serialVersionUID = -7958664359250070233L;
*
* * @param args ignored
*/
public static void main (String[] args)
{
dumpSVUID(ProcessInfo.class);
dumpSVUID(CStatementVO.class);
dumpSVUID(MQuery.class);
dumpSVUID(POInfo.class);
dumpSVUID(POInfoColumn.class);
dumpSVUID(GridWindowVO.class);
dumpSVUID(GridTabVO.class);
dumpSVUID(GridFieldVO.class);
dumpSVUID(MLookupInfo.class);
} // main
} // ServerBean

View File

@ -0,0 +1,288 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.session;
import java.util.logging.*;
import javax.ejb.*;
import org.compiere.*;
import org.compiere.db.*;
import org.compiere.util.*;
/**
* Adempiere Status Bean
*
* @ejb.bean name="adempiere/Status"
* display-name="Adempiere Status Session Bean"
* type="Stateless"
* view-type="both"
* transaction-type="Bean"
* jndi-name="adempiere/Status"
* local-jndi-name="adempiere/StatusLocal"
*
* @ejb.ejb-ref ejb-name="adempiere/Status"
* view-type="both"
* ref-name="adempiere/Status"
* @ejb.ejb-ref ejb-name="adempiere/Status"
* view-type="local"
* ref-name="adempiere/StatusLocal"
*
* @author Jorg Janke
* @version $Id: StatusBean.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class StatusBean implements SessionBean
{
/** Context */
private SessionContext m_Context;
/** Logging */
private static CLogger log = CLogger.getCLogger(StatusBean.class);
private static int s_no = 0;
private int m_no = 0;
//
private int m_versionCount = 0;
private int m_databaseCount = 0;
/**
* Get Version (Date)
* @ejb.interface-method view-type="both"
* @return version e.g. 2002-09-02
*/
public String getDateVersion()
{
m_versionCount++;
log.info ("getDateVersion " + m_versionCount);
return Adempiere.DATE_VERSION;
} // getDateVersion
/**
* Get Main Version
* @ejb.interface-method view-type="both"
* @return main version - e.g. Version 2.4.3b
*/
public String getMainVersion()
{
return Adempiere.MAIN_VERSION;
} // getMainVersion
/**
* Get Database Type
* @ejb.interface-method view-type="both"
* @return Database Type
*/
public String getDbType()
{
return CConnection.get().getType();
} // getDbType
/**
* Get Database Host
* @ejb.interface-method view-type="both"
* @return Database Host Name
*/
public String getDbHost()
{
m_databaseCount++;
log.info ("getDbHost " + m_databaseCount);
return CConnection.get().getDbHost();
} // getDbHost
/**
* Get Database Port
* @ejb.interface-method view-type="both"
* @return Database Port
*/
public int getDbPort()
{
return CConnection.get().getDbPort();
} // getDbPort
/**
* Get Database SID
* @ejb.interface-method view-type="both"
* @return Database SID
*/
public String getDbName()
{
return CConnection.get().getDbName();
} // getDbSID
/**
* Get Database URL
* @ejb.interface-method view-type="both"
* @return Database URL
*/
public String getConnectionURL()
{
return CConnection.get().getConnectionURL();
} // getConnectionURL
/**
* Get Database UID
* @ejb.interface-method view-type="both"
* @return Database User Name
*/
public String getDbUid()
{
return CConnection.get().getDbUid();
} // getDbUID
/**
* Get Database PWD
* @ejb.interface-method view-type="both"
* @return Database User Password
*/
public String getDbPwd()
{
return CConnection.get().getDbPwd();
} // getDbPWD
/**
* Get Connection Manager Host
* @ejb.interface-method view-type="both"
* @return Connection Manager Host
*/
public String getFwHost()
{
return CConnection.get().getFwHost();
} // getCMHost
/**
* Get Connection Manager Port
* @ejb.interface-method view-type="both"
* @return Connection Manager Port
*/
public int getFwPort()
{
return CConnection.get().getFwPort();
} // getCMPort
/**************************************************************************
* Get Version Count
* @ejb.interface-method view-type="both"
* @return number of version inquiries
*/
public int getVersionCount()
{
return m_versionCount;
} // getVersionCount
/**
* Get Database Count
* @ejb.interface-method view-type="both"
* @return number of database inquiries
*/
public int getDatabaseCount()
{
return m_databaseCount;
} // getVersionCount
/**
* Describes the instance and its content for debugging purpose
* @ejb.interface-method view-type="both"
* @return Debugging information about the instance and its content
*/
public String getStatus()
{
StringBuffer sb = new StringBuffer("StatusBean[No=");
sb.append(m_no)
.append(",VersionCount=").append(m_versionCount)
.append(",DatabaseCount=").append(m_versionCount)
.append("]");
return sb.toString();
} // getStatus
/**
* String Representation
* @return info
*/
public String toString()
{
return getStatus();
} // toString
/**************************************************************************
* Create the Session Bean
* @throws EJBException
* @throws CreateException
* @ejb.create-method view-type="both"
*/
public void ejbCreate() throws EJBException, CreateException
{
m_no = ++s_no;
try
{
org.compiere.Adempiere.startup(false);
}
catch (Exception ex)
{
log.log(Level.SEVERE, "", ex);
// throw new CreateException ();
}
log.info("#" + m_no + " - " + getStatus());
} // ejbCreate
// -------------------------------------------------------------------------
// Framework Callbacks
// -------------------------------------------------------------------------
/**
* Set Session Context
* @param aContext context
* @throws EJBException
*/
public void setSessionContext (SessionContext aContext) throws EJBException
{
m_Context = aContext;
}
/**
* Ejb Activate
* @throws EJBException
*/
public void ejbActivate() throws EJBException
{
if (log == null)
log = CLogger.getCLogger(getClass());
log.fine("ejbActivate");
}
/**
* Ejb Passivate
* @throws EJBException
*/
public void ejbPassivate() throws EJBException
{
log.fine("ejbPassivate");
}
/**
* Ejb Remove
* @throws EJBException
*/
public void ejbRemove() throws EJBException
{
log.fine("ejbRemove");
}
} // StatusBean

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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.acct;
import java.math.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Allocation Line
*
* @author Jorg Janke
* @version $Id: DocLine_Allocation.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $
*/
public class DocLine_Allocation extends DocLine
{
/**
* DocLine_Allocation
* @param line allocation line
* @param doc header
*/
public DocLine_Allocation (MAllocationLine line, Doc doc)
{
super (line, doc);
m_C_Payment_ID = line.getC_Payment_ID();
m_C_CashLine_ID = line.getC_CashLine_ID();
m_C_Invoice_ID = line.getC_Invoice_ID();
m_C_Order_ID = line.getC_Order_ID();
//
setAmount(line.getAmount());
m_DiscountAmt = line.getDiscountAmt();
m_WriteOffAmt = line.getWriteOffAmt();
m_OverUnderAmt = line.getOverUnderAmt();
} // DocLine_Allocation
private int m_C_Invoice_ID;
private int m_C_Payment_ID;
private int m_C_CashLine_ID;
private int m_C_Order_ID;
private BigDecimal m_DiscountAmt;
private BigDecimal m_WriteOffAmt;
private BigDecimal m_OverUnderAmt;
/**
* Get Invoice C_Currency_ID
* @return 0 if no invoice -1 if not found
*/
public int getInvoiceC_Currency_ID()
{
if (m_C_Invoice_ID == 0)
return 0;
String sql = "SELECT C_Currency_ID "
+ "FROM C_Invoice "
+ "WHERE C_Invoice_ID=?";
return DB.getSQLValue(null, sql, m_C_Invoice_ID);
} // getInvoiceC_Currency_ID
/**
* String Representation
* @return info
*/
public String toString ()
{
StringBuffer sb = new StringBuffer ("DocLine_Allocation[");
sb.append(get_ID())
.append(",Amt=").append(getAmtSource())
.append(",Discount=").append(getDiscountAmt())
.append(",WriteOff=").append(getWriteOffAmt())
.append(",OverUnderAmt=").append(getOverUnderAmt())
.append(" - C_Payment_ID=").append(m_C_Payment_ID)
.append(",C_CashLine_ID=").append(m_C_CashLine_ID)
.append(",C_Invoice_ID=").append(m_C_Invoice_ID)
.append("]");
return sb.toString ();
} // toString
/**
* @return Returns the c_Order_ID.
*/
public int getC_Order_ID ()
{
return m_C_Order_ID;
}
/**
* @return Returns the discountAmt.
*/
public BigDecimal getDiscountAmt ()
{
return m_DiscountAmt;
}
/**
* @return Returns the overUnderAmt.
*/
public BigDecimal getOverUnderAmt ()
{
return m_OverUnderAmt;
}
/**
* @return Returns the writeOffAmt.
*/
public BigDecimal getWriteOffAmt ()
{
return m_WriteOffAmt;
}
/**
* @return Returns the c_CashLine_ID.
*/
public int getC_CashLine_ID ()
{
return m_C_CashLine_ID;
}
/**
* @return Returns the c_Invoice_ID.
*/
public int getC_Invoice_ID ()
{
return m_C_Invoice_ID;
}
/**
* @return Returns the c_Payment_ID.
*/
public int getC_Payment_ID ()
{
return m_C_Payment_ID;
}
} // DocLine_Allocation

View File

@ -0,0 +1,122 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.acct;
import java.math.*;
import org.compiere.model.*;
import org.compiere.util.*;
//import org.compiere.model.*;
/**
* Bank Statement Line
*
* @author Jorg Janke
* @version $Id: DocLine_Bank.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $
*/
public class DocLine_Bank extends DocLine
{
/**
* Constructor
* @param line statement line
* @param doc header
*/
public DocLine_Bank (MBankStatementLine line, Doc_Bank doc)
{
super (line, doc);
m_C_Payment_ID = line.getC_Payment_ID();
m_IsReversal = line.isReversal();
//
m_StmtAmt = line.getStmtAmt();
m_InterestAmt = line.getInterestAmt();
m_TrxAmt = line.getTrxAmt();
//
setDateDoc(line.getValutaDate());
setC_BPartner_ID(line.getC_BPartner_ID());
} // DocLine_Bank
/** Reversal Flag */
private boolean m_IsReversal = false;
/** Payment */
private int m_C_Payment_ID = 0;
private BigDecimal m_TrxAmt = Env.ZERO;
private BigDecimal m_StmtAmt = Env.ZERO;
private BigDecimal m_InterestAmt = Env.ZERO;
/**
* Get Payment
* @return C_Paymnet_ID
*/
public int getC_Payment_ID()
{
return m_C_Payment_ID;
} // getC_Payment_ID
/**
* Get AD_Org_ID
* @param payment if true get Org from payment
* @return org
*/
public int getAD_Org_ID (boolean payment)
{
if (payment && getC_Payment_ID() != 0)
{
String sql = "SELECT AD_Org_ID FROM C_Payment WHERE C_Payment_ID=?";
int id = DB.getSQLValue(null, sql, getC_Payment_ID());
if (id > 0)
return id;
}
return super.getAD_Org_ID();
} // getAD_Org_ID
/**
* Is Reversal
* @return true if reversal
*/
public boolean isReversal()
{
return m_IsReversal;
} // isReversal
/**
* Get Interest
* @return InterestAmount
*/
public BigDecimal getInterestAmt()
{
return m_InterestAmt;
} // getInterestAmt
/**
* Get Statement
* @return Starement Amount
*/
public BigDecimal getStmtAmt()
{
return m_StmtAmt;
} // getStrmtAmt
/**
* Get Transaction
* @return transaction amount
*/
public BigDecimal getTrxAmt()
{
return m_TrxAmt;
} // getTrxAmt
} // DocLine_Bank

View File

@ -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.acct;
import java.math.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Cash Journal Line
*
* @author Jorg Janke
* @version $Id: DocLine_Cash.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class DocLine_Cash extends DocLine
{
/**
* Constructor
* @param line cash line
* @param doc header
*/
public DocLine_Cash (MCashLine line, Doc_Cash doc)
{
super (line, doc);
m_CashType = line.getCashType();
m_C_BankAccount_ID = line.getC_BankAccount_ID();
m_C_Invoice_ID = line.getC_Invoice_ID();
//
if (m_C_Invoice_ID != 0)
{
MInvoice invoice = MInvoice.get(line.getCtx(), m_C_Invoice_ID);
setC_BPartner_ID(invoice.getC_BPartner_ID());
}
//
m_Amount = line.getAmount();
m_DiscountAmt = line.getDiscountAmt();
m_WriteOffAmt = line.getWriteOffAmt();
setAmount(m_Amount);
} // DocLine_Cash
/** Cash Type */
private String m_CashType = "";
// AD_Reference_ID=217
/** Charge - C */
public static final String CASHTYPE_CHARGE = "C";
/** Difference - D */
public static final String CASHTYPE_DIFFERENCE = "D";
/** Expense - E */
public static final String CASHTYPE_EXPENSE = "E";
/** Onvoice - I */
public static final String CASHTYPE_INVOICE = "I";
/** Receipt - R */
public static final String CASHTYPE_RECEIPT = "R";
/** Transfer - T */
public static final String CASHTYPE_TRANSFER = "T";
// References
private int m_C_BankAccount_ID = 0;
private int m_C_Invoice_ID = 0;
// Amounts
private BigDecimal m_Amount = Env.ZERO;
private BigDecimal m_DiscountAmt = Env.ZERO;
private BigDecimal m_WriteOffAmt = Env.ZERO;
/**
* Get Cash Type
* @return cash type
*/
public String getCashType()
{
return m_CashType;
} // getCashType
/**
* Get Bank Account
* @return Bank Account
*/
public int getC_BankAccount_ID()
{
return m_C_BankAccount_ID;
} // getC_BankAccount_ID
/**
* Get Invoice
* @return C_Invoice_ID
*/
public int getC_Invoice_ID()
{
return m_C_Invoice_ID;
} // getC_Invoice_ID
/**
* Get Amount
* @return Payment Amount
*/
public BigDecimal getAmount()
{
return m_Amount;
}
/**
* Get Discount
* @return Discount Amount
*/
public BigDecimal getDiscountAmt()
{
return m_DiscountAmt;
}
/**
* Get WriteOff
* @return Write-Off Amount
*/
public BigDecimal getWriteOffAmt()
{
return m_WriteOffAmt;
}
} // DocLine_Cash

View File

@ -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.acct;
import java.math.*;
import java.sql.*;
import org.compiere.model.*;
import java.util.logging.*;
import org.compiere.util.*;
/**
* Document Tax Line
*
* @author Jorg Janke
* @version $Id: DocTax.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public final class DocTax
{
/**
* Create Tax
* @param C_Tax_ID tax
* @param name name
* @param rate rate
* @param taxBaseAmt tax base amount
* @param amount amount
* @param salesTax sales tax flag
*/
public DocTax (int C_Tax_ID, String name, BigDecimal rate,
BigDecimal taxBaseAmt, BigDecimal amount, boolean salesTax)
{
m_C_Tax_ID = C_Tax_ID;
m_name = name;
m_rate = rate;
m_amount = amount;
m_salesTax = salesTax;
} // DocTax
/** Tax ID */
private int m_C_Tax_ID = 0;
/** Amount */
private BigDecimal m_amount = null;
/** Tax Rate */
private BigDecimal m_rate = null;
/** Name */
private String m_name = null;
/** Base Tax Amt */
private BigDecimal m_taxBaseAmt = null;
/** Included Tax */
private BigDecimal m_includedTax = Env.ZERO;
/** Sales Tax */
private boolean m_salesTax = false;
/** Logger */
private static CLogger log = CLogger.getCLogger(DocTax.class);
/** Tax Due Acct */
public static final int ACCTTYPE_TaxDue = 0;
/** Tax Liability */
public static final int ACCTTYPE_TaxLiability = 1;
/** Tax Credit */
public static final int ACCTTYPE_TaxCredit = 2;
/** Tax Receivables */
public static final int ACCTTYPE_TaxReceivables = 3;
/** Tax Expense */
public static final int ACCTTYPE_TaxExpense = 4;
/**
* Get Account
* @param AcctType see ACCTTYPE_*
* @param as account schema
* @return Account
*/
public MAccount getAccount (int AcctType, MAcctSchema as)
{
if (AcctType < 0 || AcctType > 4)
return null;
//
String sql = "SELECT T_Due_Acct, T_Liability_Acct, T_Credit_Acct, T_Receivables_Acct, T_Expense_Acct "
+ "FROM C_Tax_Acct WHERE C_Tax_ID=? AND C_AcctSchema_ID=?";
int validCombination_ID = 0;
try
{
PreparedStatement pstmt = DB.prepareStatement(sql, null);
pstmt.setInt(1, m_C_Tax_ID);
pstmt.setInt(2, as.getC_AcctSchema_ID());
ResultSet rs = pstmt.executeQuery();
if (rs.next())
validCombination_ID = rs.getInt(AcctType+1); // 1..5
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
/**
* Get Amount
* @return gross amount
*/
public BigDecimal getAmount()
{
return m_amount;
}
/**
* Get Base Amount
* @return net amount
*/
public BigDecimal getTaxBaseAmt()
{
return m_taxBaseAmt;
}
/**
* Get Rate
* @return tax rate in percent
*/
public BigDecimal getRate()
{
return m_rate;
}
/**
* Get Name of Tax
* @return name
*/
public String getName()
{
return m_name;
}
/**
* Get C_Tax_ID
* @return tax id
*/
public int getC_Tax_ID()
{
return m_C_Tax_ID;
} // getC_Tax_ID
/**
* Get Description (Tax Name and Base Amount)
* @return tax anme and base amount
*/
public String getDescription()
{
return m_name + " " + m_taxBaseAmt.toString();
} // getDescription
/**
* Add to Included Tax
* @param amt amount
*/
public void addIncludedTax (BigDecimal amt)
{
m_includedTax = m_includedTax.add(amt);
} // addIncludedTax
/**
* Get Included Tax
* @return tax amount
*/
public BigDecimal getIncludedTax()
{
return m_includedTax;
} // getIncludedTax
/**
* Get Included Tax Difference
* @return tax ampunt - included amount
*/
public BigDecimal getIncludedTaxDifference()
{
return m_amount.subtract(m_includedTax);
} // getIncludedTaxDifference
/**
* Included Tax differs from tax amount
* @return true if difference
*/
public boolean isIncludedTaxDifference()
{
return Env.ZERO.compareTo(getIncludedTaxDifference()) != 0;
} // isIncludedTaxDifference
/**
* Get AP Tax Type
* @return AP tax type (Credit or Expense)
*/
public int getAPTaxType()
{
if (isSalesTax())
return ACCTTYPE_TaxExpense;
return ACCTTYPE_TaxCredit;
} // getAPTaxAcctType
/**
* Is Sales Tax
* @return sales tax
*/
public boolean isSalesTax()
{
return m_salesTax;
} // isSalesTax
/**
* Return String representation
* @return tax anme and base amount
*/
public String toString()
{
StringBuffer sb = new StringBuffer("Tax=(");
sb.append(m_name);
sb.append(" Amt=").append(m_amount);
sb.append(")");
return sb.toString();
} // toString
} // DocTax

View File

@ -0,0 +1,892 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.acct;
import java.math.*;
import java.sql.*;
import java.util.*;
import java.util.logging.*;
import org.apache.taglibs.standard.lang.jstl.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Post Allocation Documents.
* <pre>
* Table: C_AllocationHdr
* Document Types: CMA
* </pre>
* @author Jorg Janke
* @version $Id: Doc_Allocation.java,v 1.6 2006/07/30 00:53:33 jjanke Exp $
*/
public class Doc_Allocation extends Doc
{
/**
* Constructor
* @param ass accounting schemata
* @param rs record
* @param trxName trx
*/
protected Doc_Allocation (MAcctSchema[] ass, ResultSet rs, String trxName)
{
super (ass, MAllocationHdr.class, rs, DOCTYPE_Allocation, trxName);
} // Doc_Allocation
/** Tolearance G&L */
private static final BigDecimal TOLERANCE = new BigDecimal (0.02);
/** Facts */
private ArrayList<Fact> m_facts = null;
/**
* Load Specific Document Details
* @return error message or null
*/
protected String loadDocumentDetails ()
{
MAllocationHdr alloc = (MAllocationHdr)getPO();
setDateDoc(alloc.getDateTrx());
// Contained Objects
p_lines = loadLines(alloc);
return null;
} // loadDocumentDetails
/**
* Load Invoice Line
* @param alloc header
* @return DocLine Array
*/
private DocLine[] loadLines(MAllocationHdr alloc)
{
ArrayList<DocLine> list = new ArrayList<DocLine>();
MAllocationLine[] lines = alloc.getLines(false);
for (int i = 0; i < lines.length; i++)
{
MAllocationLine line = lines[i];
DocLine_Allocation docLine = new DocLine_Allocation(line, this);
// Get Payment Conversion Rate
if (line.getC_Payment_ID() != 0)
{
MPayment payment = new MPayment (getCtx(), line.getC_Payment_ID(), getTrxName());
int C_ConversionType_ID = payment.getC_ConversionType_ID();
docLine.setC_ConversionType_ID(C_ConversionType_ID);
}
//
log.fine(docLine.toString());
list.add (docLine);
}
// Return Array
DocLine[] dls = new DocLine[list.size()];
list.toArray(dls);
return dls;
} // loadLines
/**************************************************************************
* Get Source Currency Balance - subtracts line and tax amounts from total - no rounding
* @return positive amount, if total invoice is bigger than lines
*/
public BigDecimal getBalance()
{
BigDecimal retValue = Env.ZERO;
return retValue;
} // getBalance
/**
* Create Facts (the accounting logic) for
* CMA.
* <pre>
* AR_Invoice_Payment
* UnAllocatedCash DR
* or C_Prepayment
* DiscountExp DR
* WriteOff DR
* Receivables CR
* AR_Invoice_Cash
* CashTransfer DR
* DiscountExp DR
* WriteOff DR
* Receivables CR
*
* AP_Invoice_Payment
* Liability DR
* DiscountRev CR
* WriteOff CR
* PaymentSelect CR
* or V_Prepayment
* AP_Invoice_Cash
* Liability DR
* DiscountRev CR
* WriteOff CR
* CashTransfer CR
* CashBankTransfer
* -
* ==============================
* Realized Gain & Loss
* AR/AP DR CR
* Realized G/L DR CR
*
*
* </pre>
* Tax needs to be corrected for discount & write-off;
* Currency gain & loss is realized here.
* @param as accounting schema
* @return Fact
*/
public ArrayList<Fact> createFacts (MAcctSchema as)
{
m_facts = new ArrayList<Fact>();
// create Fact Header
Fact fact = new Fact(this, as, Fact.POST_Actual);
for (int i = 0; i < p_lines.length; i++)
{
DocLine_Allocation line = (DocLine_Allocation)p_lines[i];
setC_BPartner_ID(line.getC_BPartner_ID());
// CashBankTransfer - all references null and Discount/WriteOff = 0
if (line.getC_Payment_ID() != 0
&& line.getC_Invoice_ID() == 0 && line.getC_Order_ID() == 0
&& line.getC_CashLine_ID() == 0 && line.getC_BPartner_ID() == 0
&& Env.ZERO.compareTo(line.getDiscountAmt()) == 0
&& Env.ZERO.compareTo(line.getWriteOffAmt()) == 0)
continue;
// Receivables/Liability Amt
BigDecimal allocationSource = line.getAmtSource()
.add(line.getDiscountAmt())
.add(line.getWriteOffAmt());
BigDecimal allocationAccounted = null; // AR/AP balance corrected
FactLine fl = null;
MAccount bpAcct = null; // Liability/Receivables
//
MPayment payment = null;
if (line.getC_Payment_ID() != 0)
payment = new MPayment (getCtx(), line.getC_Payment_ID(), getTrxName());
MInvoice invoice = null;
if (line.getC_Invoice_ID() != 0)
invoice = new MInvoice (getCtx(), line.getC_Invoice_ID(), null);
// No Invoice
if (invoice == null)
{
// Payment Only
if (line.getC_Invoice_ID() == 0 && line.getC_Payment_ID() != 0)
{
fl = fact.createLine (line, getPaymentAcct(as, line.getC_Payment_ID()),
getC_Currency_ID(), line.getAmtSource(), null);
if (fl != null && payment != null)
fl.setAD_Org_ID(payment.getAD_Org_ID());
}
else
{
p_Error = "Cannot determine SO/PO";
log.log(Level.SEVERE, p_Error);
return null;
}
}
// Sales Invoice
else if (invoice.isSOTrx())
{
// Payment/Cash DR
if (line.getC_Payment_ID() != 0)
{
fl = fact.createLine (line, getPaymentAcct(as, line.getC_Payment_ID()),
getC_Currency_ID(), line.getAmtSource(), null);
if (fl != null && payment != null)
fl.setAD_Org_ID(payment.getAD_Org_ID());
}
else if (line.getC_CashLine_ID() != 0)
{
fl = fact.createLine (line, getCashAcct(as, line.getC_CashLine_ID()),
getC_Currency_ID(), line.getAmtSource(), null);
MCashLine cashLine = new MCashLine (getCtx(), line.getC_CashLine_ID(), getTrxName());
if (fl != null && cashLine.get_ID() != 0)
fl.setAD_Org_ID(cashLine.getAD_Org_ID());
}
// Discount DR
if (Env.ZERO.compareTo(line.getDiscountAmt()) != 0)
{
fl = fact.createLine (line, getAccount(Doc.ACCTTYPE_DiscountExp, as),
getC_Currency_ID(), line.getDiscountAmt(), null);
if (fl != null && payment != null)
fl.setAD_Org_ID(payment.getAD_Org_ID());
}
// Write off DR
if (Env.ZERO.compareTo(line.getWriteOffAmt()) != 0)
{
fl = fact.createLine (line, getAccount(Doc.ACCTTYPE_WriteOff, as),
getC_Currency_ID(), line.getWriteOffAmt(), null);
if (fl != null && payment != null)
fl.setAD_Org_ID(payment.getAD_Org_ID());
}
// AR Invoice Amount CR
if (as.isAccrual())
{
bpAcct = getAccount(Doc.ACCTTYPE_C_Receivable, as);
fl = fact.createLine (line, bpAcct,
getC_Currency_ID(), null, allocationSource); // payment currency
if (fl != null)
allocationAccounted = fl.getAcctBalance().negate();
if (fl != null && invoice != null)
fl.setAD_Org_ID(invoice.getAD_Org_ID());
}
else // Cash Based
{
allocationAccounted = createCashBasedAcct (as, fact,
invoice, allocationSource);
}
}
// Purchase Invoice
else
{
allocationSource = allocationSource.negate(); // allocation is negative
// AP Invoice Amount DR
if (as.isAccrual())
{
bpAcct = getAccount(Doc.ACCTTYPE_V_Liability, as);
fl = fact.createLine (line, bpAcct,
getC_Currency_ID(), allocationSource, null); // payment currency
if (fl != null)
allocationAccounted = fl.getAcctBalance();
if (fl != null && invoice != null)
fl.setAD_Org_ID(invoice.getAD_Org_ID());
}
else // Cash Based
{
allocationAccounted = createCashBasedAcct (as, fact,
invoice, allocationSource);
}
// Discount CR
if (Env.ZERO.compareTo(line.getDiscountAmt()) != 0)
{
fl = fact.createLine (line, getAccount(Doc.ACCTTYPE_DiscountRev, as),
getC_Currency_ID(), null, line.getDiscountAmt().negate());
if (fl != null && payment != null)
fl.setAD_Org_ID(payment.getAD_Org_ID());
}
// Write off CR
if (Env.ZERO.compareTo(line.getWriteOffAmt()) != 0)
{
fl = fact.createLine (line, getAccount(Doc.ACCTTYPE_WriteOff, as),
getC_Currency_ID(), null, line.getWriteOffAmt().negate());
if (fl != null && payment != null)
fl.setAD_Org_ID(payment.getAD_Org_ID());
}
// Payment/Cash CR
if (line.getC_Payment_ID() != 0)
{
fl = fact.createLine (line, getPaymentAcct(as, line.getC_Payment_ID()),
getC_Currency_ID(), null, line.getAmtSource().negate());
if (fl != null && payment != null)
fl.setAD_Org_ID(payment.getAD_Org_ID());
}
else if (line.getC_CashLine_ID() != 0)
{
fl = fact.createLine (line, getCashAcct(as, line.getC_CashLine_ID()),
getC_Currency_ID(), null, line.getAmtSource().negate());
MCashLine cashLine = new MCashLine (getCtx(), line.getC_CashLine_ID(), getTrxName());
if (fl != null && cashLine.get_ID() != 0)
fl.setAD_Org_ID(cashLine.getAD_Org_ID());
}
}
// VAT Tax Correction
if (invoice != null && as.isTaxCorrection())
{
BigDecimal taxCorrectionAmt = Env.ZERO;
if (as.isTaxCorrectionDiscount())
taxCorrectionAmt = line.getDiscountAmt();
if (as.isTaxCorrectionWriteOff())
taxCorrectionAmt = taxCorrectionAmt.add(line.getWriteOffAmt());
//
if (taxCorrectionAmt.signum() != 0)
{
if (!createTaxCorrection(as, fact, line,
getAccount(invoice.isSOTrx() ? Doc.ACCTTYPE_DiscountExp : Doc.ACCTTYPE_DiscountRev, as),
getAccount(Doc.ACCTTYPE_WriteOff, as)))
{
p_Error = "Cannot create Tax correction";
return null;
}
}
}
// Realized Gain & Loss
if (invoice != null
&& (getC_Currency_ID() != as.getC_Currency_ID() // payment allocation in foreign currency
|| getC_Currency_ID() != line.getInvoiceC_Currency_ID())) // allocation <> invoice currency
{
p_Error = createRealizedGainLoss (as, fact, bpAcct, invoice,
allocationSource, allocationAccounted);
if (p_Error != null)
return null;
}
} // for all lines
// reset line info
setC_BPartner_ID(0);
//
m_facts.add(fact);
return m_facts;
} // createFact
/**
* Create Cash Based Acct
* @param as accounting schema
* @param fact fact
* @param invoice invoice
* @param allocationSource allocation amount (incl discount, writeoff)
* @return Accounted Amt
*/
private BigDecimal createCashBasedAcct (MAcctSchema as, Fact fact, MInvoice invoice,
BigDecimal allocationSource)
{
BigDecimal allocationAccounted = Env.ZERO;
// Multiplier
double percent = invoice.getGrandTotal().doubleValue() / allocationSource.doubleValue();
if (percent > 0.99 && percent < 1.01)
percent = 1.0;
log.config("Multiplier=" + percent + " - GrandTotal=" + invoice.getGrandTotal()
+ " - Allocation Source=" + allocationSource);
// Get Invoice Postings
Doc_Invoice docInvoice = (Doc_Invoice)Doc.get(new MAcctSchema[]{as},
MInvoice.Table_ID, invoice.getC_Invoice_ID(), getTrxName());
docInvoice.loadDocumentDetails();
allocationAccounted = docInvoice.createFactCash(as, fact, new BigDecimal(percent));
log.config("Allocation Accounted=" + allocationAccounted);
// Cash Based Commitment Release
if (as.isCreateCommitment() && !invoice.isSOTrx())
{
MInvoiceLine[] lines = invoice.getLines();
for (int i = 0; i < lines.length; i++)
{
Fact factC = Doc_Order.getCommitmentRelease(as, this,
lines[i].getQtyInvoiced(), lines[i].getC_InvoiceLine_ID(), new BigDecimal(percent));
if (factC == null)
return null;
m_facts.add(factC);
}
} // Commitment
return allocationAccounted;
} // createCashBasedAcct
/**
* Get Payment (Unallocated Payment or Payment Selection) Acct of Bank Account
* @param as accounting schema
* @param C_Payment_ID payment
* @return acct
*/
private MAccount getPaymentAcct (MAcctSchema as, int C_Payment_ID)
{
setC_BankAccount_ID(0);
// Doc.ACCTTYPE_UnallocatedCash (AR) or C_Prepayment
// or Doc.ACCTTYPE_PaymentSelect (AP) or V_Prepayment
int accountType = Doc.ACCTTYPE_UnallocatedCash;
//
String sql = "SELECT p.C_BankAccount_ID, d.DocBaseType, p.IsReceipt, p.IsPrepayment "
+ "FROM C_Payment p INNER JOIN C_DocType d ON (p.C_DocType_ID=d.C_DocType_ID) "
+ "WHERE C_Payment_ID=?";
PreparedStatement pstmt = null;
try
{
pstmt = DB.prepareStatement (sql, getTrxName());
pstmt.setInt (1, C_Payment_ID);
ResultSet rs = pstmt.executeQuery ();
if (rs.next ())
{
setC_BankAccount_ID(rs.getInt(1));
if (DOCTYPE_APPayment.equals(rs.getString(2)))
accountType = Doc.ACCTTYPE_PaymentSelect;
// Prepayment
if ("Y".equals(rs.getString(4))) // Prepayment
{
if ("Y".equals(rs.getString(3))) // Receipt
accountType = Doc.ACCTTYPE_C_Prepayment;
else
accountType = Doc.ACCTTYPE_V_Prepayment;
}
}
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 (getC_BankAccount_ID() <= 0)
{
log.log(Level.SEVERE, "NONE for C_Payment_ID=" + C_Payment_ID);
return null;
}
return getAccount (accountType, as);
} // getPaymentAcct
/**
* Get Cash (Transfer) Acct of CashBook
* @param as accounting schema
* @param C_CashLine_ID
* @return acct
*/
private MAccount getCashAcct (MAcctSchema as, int C_CashLine_ID)
{
String sql = "SELECT c.C_CashBook_ID "
+ "FROM C_Cash c, C_CashLine cl "
+ "WHERE c.C_Cash_ID=cl.C_Cash_ID AND cl.C_CashLine_ID=?";
setC_CashBook_ID(DB.getSQLValue(null, sql, C_CashLine_ID));
if (getC_CashBook_ID() <= 0)
{
log.log(Level.SEVERE, "NONE for C_CashLine_ID=" + C_CashLine_ID);
return null;
}
return getAccount(Doc.ACCTTYPE_CashTransfer, as);
} // getCashAcct
/**************************************************************************
* Create Realized Gain & Loss.
* Compares the Accounted Amount of the Invoice to the
* Accounted Amount of the Allocation
* @param as accounting schema
* @param fact fact
* @param acct account
* @param invoice invoice
* @param allocationSource source amt
* @param allocationAccounted acct amt
* @return Error Message or null if OK
*/
private String createRealizedGainLoss (MAcctSchema as, Fact fact, MAccount acct,
MInvoice invoice, BigDecimal allocationSource, BigDecimal allocationAccounted)
{
BigDecimal invoiceSource = null;
BigDecimal invoiceAccounted = null;
//
String sql = "SELECT "
+ (invoice.isSOTrx()
? "SUM(AmtSourceDr), SUM(AmtAcctDr)" // so
: "SUM(AmtSourceCr), SUM(AmtAcctCr)") // po
+ " FROM Fact_Acct "
+ "WHERE AD_Table_ID=318 AND Record_ID=?" // Invoice
+ " AND C_AcctSchema_ID=?"
+ " AND PostingType='A'";
//AND C_Currency_ID=102
PreparedStatement pstmt = null;
try
{
pstmt = DB.prepareStatement(sql, getTrxName());
pstmt.setInt(1, invoice.getC_Invoice_ID());
pstmt.setInt(2, as.getC_AcctSchema_ID());
ResultSet rs = pstmt.executeQuery();
if (rs.next())
{
invoiceSource = rs.getBigDecimal(1);
invoiceAccounted = 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;
}
// Requires that Invoice is Posted
if (invoiceSource == null || invoiceAccounted == null)
return "Gain/Loss - Invoice not posted yet";
//
String description = "Invoice=(" + invoice.getC_Currency_ID() + ")" + invoiceSource + "/" + invoiceAccounted
+ " - Allocation=(" + getC_Currency_ID() + ")" + allocationSource + "/" + allocationAccounted;
log.fine(description);
// Allocation not Invoice Currency
if (getC_Currency_ID() != invoice.getC_Currency_ID())
{
BigDecimal allocationSourceNew = MConversionRate.convert(getCtx(),
allocationSource, getC_Currency_ID(),
invoice.getC_Currency_ID(), getDateAcct(),
invoice.getC_ConversionType_ID(), invoice.getAD_Client_ID(), invoice.getAD_Org_ID());
if (allocationSourceNew == null)
return "Gain/Loss - No Conversion from Allocation->Invoice";
String d2 = "Allocation=(" + getC_Currency_ID() + ")" + allocationSource
+ "->(" + invoice.getC_Currency_ID() + ")" + allocationSourceNew;
log.fine(d2);
description += " - " + d2;
allocationSource = allocationSourceNew;
}
BigDecimal acctDifference = null; // gain is negative
// Full Payment in currency
if (allocationSource.compareTo(invoiceSource) == 0)
{
acctDifference = invoiceAccounted.subtract(allocationAccounted); // gain is negative
String d2 = "(full) = " + acctDifference;
log.fine(d2);
description += " - " + d2;
}
else // partial or MC
{
// percent of total payment
double multiplier = allocationSource.doubleValue() / invoiceSource.doubleValue();
// Reduce Orig Invoice Accounted
invoiceAccounted = invoiceAccounted.multiply(new BigDecimal(multiplier));
// Difference based on percentage of Orig Invoice
acctDifference = invoiceAccounted.subtract(allocationAccounted); // gain is negative
// ignore Tolerance
if (acctDifference.abs().compareTo(TOLERANCE) < 0)
acctDifference = Env.ZERO;
// Round
int precision = as.getStdPrecision();
if (acctDifference.scale() > precision)
acctDifference = acctDifference.setScale(precision, BigDecimal.ROUND_HALF_UP);
String d2 = "(partial) = " + acctDifference + " - Multiplier=" + multiplier;
log.fine(d2);
description += " - " + d2;
}
if (acctDifference.signum() == 0)
{
log.fine("No Difference");
return null;
}
MAccount gain = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedGain_Acct());
MAccount loss = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedLoss_Acct());
//
if (invoice.isSOTrx())
{
FactLine fl = fact.createLine (null, loss, gain,
as.getC_Currency_ID(), acctDifference);
fl.setDescription(description);
fact.createLine (null, acct,
as.getC_Currency_ID(), acctDifference.negate());
fl.setDescription(description);
}
else
{
fact.createLine (null, acct,
as.getC_Currency_ID(), acctDifference);
FactLine fl = fact.createLine (null, loss, gain,
as.getC_Currency_ID(), acctDifference.negate());
}
return null;
} // createRealizedGainLoss
/**************************************************************************
* Create Tax Correction.
* Requirement: Adjust the tax amount, if you did not receive the full
* amount of the invoice (payment discount, write-off).
* Applies to many countries with VAT.
* Example:
* Invoice: Net $100 + Tax1 $15 + Tax2 $5 = Total $120
* Payment: $115 (i.e. $5 underpayment)
* Tax Adjustment = Tax1 = 0.63 (15/120*5) Tax2 = 0.21 (5/120/5)
*
* @param as accounting schema
* @param fact fact
* @param line Allocation line
* @param DiscountAccount discount acct
* @param WriteOffAccoint write off acct
* @return true if created
*/
private boolean createTaxCorrection (MAcctSchema as, Fact fact,
DocLine_Allocation line,
MAccount DiscountAccount, MAccount WriteOffAccoint)
{
log.info (line.toString());
BigDecimal discount = Env.ZERO;
if (as.isTaxCorrectionDiscount())
discount = line.getDiscountAmt();
BigDecimal writeOff = Env.ZERO;
if (as.isTaxCorrectionWriteOff())
writeOff = line.getWriteOffAmt();
Doc_AllocationTax tax = new Doc_AllocationTax (
DiscountAccount, discount, WriteOffAccoint, writeOff);
// Get Source Amounts with account
String sql = "SELECT * "
+ "FROM Fact_Acct "
+ "WHERE AD_Table_ID=318 AND Record_ID=?" // Invoice
+ " AND C_AcctSchema_ID=?"
+ " AND Line_ID IS NULL"; // header lines like tax or total
PreparedStatement pstmt = null;
try
{
pstmt = DB.prepareStatement(sql, getTrxName());
pstmt.setInt(1, line.getC_Invoice_ID());
pstmt.setInt(2, as.getC_AcctSchema_ID());
ResultSet rs = pstmt.executeQuery();
while (rs.next())
tax.addInvoiceFact (new MFactAcct(getCtx(), rs, fact.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;
}
// Invoice Not posted
if (tax.getLineCount() == 0)
{
log.warning ("Invoice not posted yet - " + line);
return false;
}
// size = 1 if no tax
if (tax.getLineCount() < 2)
return true;
return tax.createEntries (as, fact, line);
} // createTaxCorrection
} // Doc_Allocation
/**
* Allocation Document Tax Handing
*
* @author Jorg Janke
* @version $Id: Doc_Allocation.java,v 1.6 2006/07/30 00:53:33 jjanke Exp $
*/
class Doc_AllocationTax
{
/**
* Allocation Tax Adjustment
* @param DiscountAccount discount acct
* @param DiscountAmt discount amt
* @param WriteOffAccount write off acct
* @param WriteOffAmt write off amt
*/
public Doc_AllocationTax (MAccount DiscountAccount, BigDecimal DiscountAmt,
MAccount WriteOffAccount, BigDecimal WriteOffAmt)
{
m_DiscountAccount = DiscountAccount;
m_DiscountAmt = DiscountAmt;
m_WriteOffAccount = WriteOffAccount;
m_WriteOffAmt = WriteOffAmt;
} // Doc_AllocationTax
private CLogger log = CLogger.getCLogger(getClass());
private MAccount m_DiscountAccount;
private BigDecimal m_DiscountAmt;
private MAccount m_WriteOffAccount;
private BigDecimal m_WriteOffAmt;
private ArrayList<MFactAcct> m_facts = new ArrayList<MFactAcct>();
private int m_totalIndex = 0;
/**
* Add Invoice Fact Line
* @param fact fact line
*/
public void addInvoiceFact (MFactAcct fact)
{
m_facts.add(fact);
} // addInvoiceLine
/**
* Get Line Count
* @return number of lines
*/
public int getLineCount()
{
return m_facts.size();
} // getLineCount
/**
* Create Accounting Entries
* @param as account schema
* @param fact fact to add lines
* @param line line
* @return true if created
*/
public boolean createEntries (MAcctSchema as, Fact fact, DocLine line)
{
// get total index (the Receivables/Liabilities line)
BigDecimal total = Env.ZERO;
for (int i = 0; i < m_facts.size(); i++)
{
MFactAcct factAcct = (MFactAcct)m_facts.get(i);
if (factAcct.getAmtSourceDr().compareTo(total) > 0)
{
total = factAcct.getAmtSourceDr();
m_totalIndex = i;
}
if (factAcct.getAmtSourceCr().compareTo(total) > 0)
{
total = factAcct.getAmtSourceCr();
m_totalIndex = i;
}
}
MFactAcct factAcct = (MFactAcct)m_facts.get(m_totalIndex);
log.info ("Total Invoice = " + total + " - " + factAcct);
int precision = as.getStdPrecision();
for (int i = 0; i < m_facts.size(); i++)
{
// No Tax Line
if (i == m_totalIndex)
continue;
factAcct = (MFactAcct)m_facts.get(i);
log.info (i + ": " + factAcct);
// Create Tax Account
MAccount taxAcct = factAcct.getMAccount();
if (taxAcct == null || taxAcct.get_ID() == 0)
{
log.severe ("Tax Account not found/created");
return false;
}
// Discount Amount
if (m_DiscountAmt.signum() != 0)
{
// Original Tax is DR - need to correct it CR
if (Env.ZERO.compareTo(factAcct.getAmtSourceDr()) != 0)
{
BigDecimal amount = calcAmount(factAcct.getAmtSourceDr(),
total, m_DiscountAmt, precision);
if (amount.signum() != 0)
{
fact.createLine (line, m_DiscountAccount,
as.getC_Currency_ID(), amount, null);
fact.createLine (line, taxAcct,
as.getC_Currency_ID(), null, amount);
}
}
// Original Tax is CR - need to correct it DR
else
{
BigDecimal amount = calcAmount(factAcct.getAmtSourceCr(),
total, m_DiscountAmt, precision);
if (amount.signum() != 0)
{
fact.createLine (line, taxAcct,
as.getC_Currency_ID(), amount, null);
fact.createLine (line, m_DiscountAccount,
as.getC_Currency_ID(), null, amount);
}
}
} // Discount
// WriteOff Amount
if (m_WriteOffAmt.signum() != 0)
{
// Original Tax is DR - need to correct it CR
if (Env.ZERO.compareTo(factAcct.getAmtSourceDr()) != 0)
{
BigDecimal amount = calcAmount(factAcct.getAmtSourceDr(),
total, m_WriteOffAmt, precision);
if (amount.signum() != 0)
{
fact.createLine (line, m_WriteOffAccount,
as.getC_Currency_ID(), amount, null);
fact.createLine (line, taxAcct,
as.getC_Currency_ID(), null, amount);
}
}
// Original Tax is CR - need to correct it DR
else
{
BigDecimal amount = calcAmount(factAcct.getAmtSourceCr(),
total, m_WriteOffAmt, precision);
if (amount.signum() != 0)
{
fact.createLine (line, taxAcct,
as.getC_Currency_ID(), amount, null);
fact.createLine (line, m_WriteOffAccount,
as.getC_Currency_ID(), null, amount);
}
}
} // WriteOff
} // for all lines
return true;
} // createEntries
/**
* Calc Amount tax / (total-tax) * amt
* @param tax tax
* @param total total
* @param amt reduction amt
* @param precision precision
* @return tax / total * amt
*/
private BigDecimal calcAmount (BigDecimal tax, BigDecimal total, BigDecimal amt, int precision)
{
log.fine("Amt=" + amt + " - Total=" + total + ", Tax=" + tax);
if (tax.signum() == 0
|| total.signum() == 0
|| amt.signum() == 0)
return Env.ZERO;
//
BigDecimal devisor = total.subtract(tax);
BigDecimal multiplier = tax.divide(devisor, 10, BigDecimal.ROUND_HALF_UP);
BigDecimal retValue = multiplier.multiply(amt);
if (retValue.scale() > precision)
retValue = retValue.setScale(precision, BigDecimal.ROUND_HALF_UP);
log.fine(retValue + " (Mult=" + multiplier + "(Prec=" + precision + ")");
return retValue;
} // calcAmount
} // Doc_AllocationTax

View File

@ -0,0 +1,223 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.acct;
import java.math.*;
import java.sql.*;
import java.util.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Post Invoice Documents.
* <pre>
* Table: C_BankStatement (392)
* Document Types: CMB
* </pre>
* @author Jorg Janke
* @version $Id: Doc_Bank.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class Doc_Bank extends Doc
{
/**
* Constructor
* @param ass accounting schemata
* @param rs record
* @param trxName trx
*/
protected Doc_Bank (MAcctSchema[] ass, ResultSet rs, String trxName)
{
super (ass, MBankStatement.class, rs, DOCTYPE_BankStatement, trxName);
} // Doc_Bank
/** Bank Account */
private int m_C_BankAccount_ID = 0;
/**
* Load Specific Document Details
* @return error message or null
*/
protected String loadDocumentDetails ()
{
MBankStatement bs = (MBankStatement)getPO();
setDateDoc(bs.getStatementDate());
setDateAcct(bs.getStatementDate()); // Overwritten on Line Level
m_C_BankAccount_ID = bs.getC_BankAccount_ID();
// Amounts
setAmount(AMTTYPE_Gross, bs.getStatementDifference());
// Set Bank Account Info (Currency)
MBankAccount ba = MBankAccount.get (getCtx(), m_C_BankAccount_ID);
setC_Currency_ID (ba.getC_Currency_ID());
// Contained Objects
p_lines = loadLines(bs);
log.fine("Lines=" + p_lines.length);
return null;
} // loadDocumentDetails
/**
* Load Invoice Line.
* @param bs bank statement
* 4 amounts
* AMTTYPE_Payment
* AMTTYPE_Statement2
* AMTTYPE_Charge
* AMTTYPE_Interest
* @return DocLine Array
*/
private DocLine[] loadLines(MBankStatement bs)
{
ArrayList<DocLine> list = new ArrayList<DocLine>();
MBankStatementLine[] lines = bs.getLines(false);
for (int i = 0; i < lines.length; i++)
{
MBankStatementLine line = lines[i];
DocLine_Bank docLine = new DocLine_Bank(line, this);
// Set Date Acct
if (i == 0)
setDateAcct(line.getDateAcct());
MPeriod period = MPeriod.get(getCtx(), line.getDateAcct());
if (period != null && period.isOpen(DOCTYPE_BankStatement))
docLine.setC_Period_ID(period.getC_Period_ID());
//
list.add(docLine);
}
// Return Array
DocLine[] dls = new DocLine[list.size()];
list.toArray(dls);
return dls;
} // loadLines
/**************************************************************************
* Get Source Currency Balance - subtracts line amounts from total - no rounding
* @return positive amount, if total invoice is bigger than lines
*/
public BigDecimal getBalance()
{
BigDecimal retValue = Env.ZERO;
StringBuffer sb = new StringBuffer (" [");
// Total
retValue = retValue.add(getAmount(Doc.AMTTYPE_Gross));
sb.append(getAmount(Doc.AMTTYPE_Gross));
// - Lines
for (int i = 0; i < p_lines.length; i++)
{
BigDecimal lineBalance = ((DocLine_Bank)p_lines[i]).getStmtAmt();
retValue = retValue.subtract(lineBalance);
sb.append("-").append(lineBalance);
}
sb.append("]");
//
log.fine(toString() + " Balance=" + retValue + sb.toString());
return retValue;
} // getBalance
/**
* Create Facts (the accounting logic) for
* CMB.
* <pre>
* BankAsset DR CR (Statement)
* BankInTransit DR CR (Payment)
* Charge DR (Charge)
* Interest DR CR (Interest)
* </pre>
* @param as accounting schema
* @return Fact
*/
public ArrayList<Fact> createFacts (MAcctSchema as)
{
// create Fact Header
Fact fact = new Fact(this, as, Fact.POST_Actual);
// Header -- there may be different currency amounts
FactLine fl = null;
int AD_Org_ID = getBank_Org_ID(); // Bank Account Org
// Lines
for (int i = 0; i < p_lines.length; i++)
{
DocLine_Bank line = (DocLine_Bank)p_lines[i];
int C_BPartner_ID = line.getC_BPartner_ID();
// BankAsset DR CR (Statement)
fl = fact.createLine(line,
getAccount(Doc.ACCTTYPE_BankAsset, as),
line.getC_Currency_ID(), line.getStmtAmt());
if (fl != null && AD_Org_ID != 0)
fl.setAD_Org_ID(AD_Org_ID);
if (fl != null && C_BPartner_ID != 0)
fl.setC_BPartner_ID(C_BPartner_ID);
// BankInTransit DR CR (Payment)
fl = fact.createLine(line,
getAccount(Doc.ACCTTYPE_BankInTransit, as),
line.getC_Currency_ID(), line.getTrxAmt().negate());
if (fl != null)
{
if (C_BPartner_ID != 0)
fl.setC_BPartner_ID(C_BPartner_ID);
if (AD_Org_ID != 0)
fl.setAD_Org_ID(AD_Org_ID);
else
fl.setAD_Org_ID(line.getAD_Org_ID(true)); // from payment
}
// Charge DR (Charge)
fl = fact.createLine(line,
line.getChargeAccount(as, line.getChargeAmt().negate()),
line.getC_Currency_ID(), line.getChargeAmt().negate(), null);
if (fl != null && C_BPartner_ID != 0)
fl.setC_BPartner_ID(C_BPartner_ID);
// Interest DR CR (Interest)
if (line.getInterestAmt().signum() < 0)
fl = fact.createLine(line,
getAccount(Doc.ACCTTYPE_InterestExp, as), getAccount(Doc.ACCTTYPE_InterestExp, as),
line.getC_Currency_ID(), line.getInterestAmt().negate());
else
fl = fact.createLine(line,
getAccount(Doc.ACCTTYPE_InterestRev, as), getAccount(Doc.ACCTTYPE_InterestRev, as),
line.getC_Currency_ID(), line.getInterestAmt().negate());
if (fl != null && C_BPartner_ID != 0)
fl.setC_BPartner_ID(C_BPartner_ID);
//
// fact.createTaxCorrection();
}
//
ArrayList<Fact> facts = new ArrayList<Fact>();
facts.add(fact);
return facts;
} // createFact
/**
* Get AD_Org_ID from Bank Account
* @return AD_Org_ID or 0
*/
private int getBank_Org_ID ()
{
if (m_C_BankAccount_ID == 0)
return 0;
//
MBankAccount ba = MBankAccount.get(getCtx(), m_C_BankAccount_ID);
return ba.getAD_Org_ID();
} // getBank_Org_ID
} // Doc_Bank

View File

@ -0,0 +1,254 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.acct;
import java.math.*;
import java.sql.*;
import java.util.*;
import org.compiere.model.*;
import java.util.logging.*;
import org.compiere.util.*;
/**
* Post Invoice Documents.
* <pre>
* Table: C_Cash (407)
* Document Types: CMC
* </pre>
* @author Jorg Janke
* @version $Id: Doc_Cash.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class Doc_Cash extends Doc
{
/**
* Constructor
* @param ass accounting schemata
* @param rs record
* @param trxName trx
*/
protected Doc_Cash (MAcctSchema[] ass, ResultSet rs, String trxName)
{
super(ass, MCash.class, rs, DOCTYPE_CashJournal, trxName);
} // Doc_Cash
/**
* Load Specific Document Details
* @return error message or null
*/
protected String loadDocumentDetails ()
{
MCash cash = (MCash)getPO();
setDateDoc(cash.getStatementDate());
// Amounts
setAmount(Doc.AMTTYPE_Gross, cash.getStatementDifference());
// Set CashBook Org & Currency
MCashBook cb = MCashBook.get(getCtx(), cash.getC_CashBook_ID());
setC_CashBook_ID(cb.getC_CashBook_ID());
setC_Currency_ID(cb.getC_Currency_ID());
// Contained Objects
p_lines = loadLines(cash, cb);
log.fine("Lines=" + p_lines.length);
return null;
} // loadDocumentDetails
/**
* Load Cash Line
* @param cash journal
* @param cb cash book
* @return DocLine Array
*/
private DocLine[] loadLines(MCash cash, MCashBook cb)
{
ArrayList<DocLine> list = new ArrayList<DocLine>();
MCashLine[] lines = cash.getLines(false);
for (int i = 0; i < lines.length; i++)
{
MCashLine line = lines[i];
DocLine_Cash docLine = new DocLine_Cash (line, this);
//
list.add(docLine);
}
// Return Array
DocLine[] dls = new DocLine[list.size()];
list.toArray(dls);
return dls;
} // loadLines
/**************************************************************************
* Get Source Currency Balance - subtracts line amounts from total - no rounding
* @return positive amount, if total invoice is bigger than lines
*/
public BigDecimal getBalance()
{
BigDecimal retValue = Env.ZERO;
StringBuffer sb = new StringBuffer (" [");
// Total
retValue = retValue.add(getAmount(Doc.AMTTYPE_Gross));
sb.append(getAmount(Doc.AMTTYPE_Gross));
// - Lines
for (int i = 0; i < p_lines.length; i++)
{
retValue = retValue.subtract(p_lines[i].getAmtSource());
sb.append("-").append(p_lines[i].getAmtSource());
}
sb.append("]");
//
log.fine(toString() + " Balance=" + retValue + sb.toString());
// return retValue;
return Env.ZERO; // Lines are balanced
} // getBalance
/**
* Create Facts (the accounting logic) for
* CMC.
* <pre>
* Expense
* CashExpense DR
* CashAsset CR
* Receipt
* CashAsset DR
* CashReceipt CR
* Charge
* Charge DR
* CashAsset CR
* Difference
* CashDifference DR
* CashAsset CR
* Invoice
* CashAsset DR
* CashTransfer CR
* Transfer
* BankInTransit DR
* CashAsset CR
* </pre>
* @param as account schema
* @return Fact
*/
public ArrayList<Fact> createFacts (MAcctSchema as)
{
// Need to have CashBook
if (getC_CashBook_ID() == 0)
{
p_Error = "C_CashBook_ID not set";
log.log(Level.SEVERE, p_Error);
return null;
}
// create Fact Header
Fact fact = new Fact(this, as, Fact.POST_Actual);
// Header posting amt as Invoices and Transfer could be differenet currency
// CashAsset Total
BigDecimal assetAmt = Env.ZERO;
// Lines
for (int i = 0; i < p_lines.length; i++)
{
DocLine_Cash line = (DocLine_Cash)p_lines[i];
String CashType = line.getCashType();
if (CashType.equals(DocLine_Cash.CASHTYPE_EXPENSE))
{ // amount is negative
// CashExpense DR
// CashAsset CR
fact.createLine(line, getAccount(Doc.ACCTTYPE_CashExpense, as),
getC_Currency_ID(), line.getAmount().negate(), null);
// fact.createLine(line, getAccount(Doc.ACCTTYPE_CashAsset, as),
// p_vo.C_Currency_ID, null, line.getAmount().negate());
assetAmt = assetAmt.subtract(line.getAmount().negate());
}
else if (CashType.equals(DocLine_Cash.CASHTYPE_RECEIPT))
{ // amount is positive
// CashAsset DR
// CashReceipt CR
// fact.createLine(line, getAccount(Doc.ACCTTYPE_CashAsset, as),
// p_vo.C_Currency_ID, line.getAmount(), null);
assetAmt = assetAmt.add(line.getAmount());
fact.createLine(line, getAccount(Doc.ACCTTYPE_CashReceipt, as),
getC_Currency_ID(), null, line.getAmount());
}
else if (CashType.equals(DocLine_Cash.CASHTYPE_CHARGE))
{ // amount is negative
// Charge DR
// CashAsset CR
fact.createLine(line, line.getChargeAccount(as, getAmount()),
getC_Currency_ID(), line.getAmount().negate(), null);
// fact.createLine(line, getAccount(Doc.ACCTTYPE_CashAsset, as),
// p_vo.C_Currency_ID, null, line.getAmount().negate());
assetAmt = assetAmt.subtract(line.getAmount().negate());
}
else if (CashType.equals(DocLine_Cash.CASHTYPE_DIFFERENCE))
{ // amount is pos/neg
// CashDifference DR
// CashAsset CR
fact.createLine(line, getAccount(Doc.ACCTTYPE_CashDifference, as),
getC_Currency_ID(), line.getAmount().negate());
// fact.createLine(line, getAccount(Doc.ACCTTYPE_CashAsset, as),
// p_vo.C_Currency_ID, line.getAmount());
assetAmt = assetAmt.add(line.getAmount());
}
else if (CashType.equals(DocLine_Cash.CASHTYPE_INVOICE))
{ // amount is pos/neg
// CashAsset DR dr -- Invoice is in Invoice Currency !
// CashTransfer cr CR
if (line.getC_Currency_ID() == getC_Currency_ID())
assetAmt = assetAmt.add (line.getAmount());
else
fact.createLine(line,
getAccount(Doc.ACCTTYPE_CashAsset, as),
line.getC_Currency_ID(), line.getAmount());
fact.createLine(line,
getAccount(Doc.ACCTTYPE_CashTransfer, as),
line.getC_Currency_ID(), line.getAmount().negate());
}
else if (CashType.equals(DocLine_Cash.CASHTYPE_TRANSFER))
{ // amount is pos/neg
// BankInTransit DR dr -- Transfer is in Bank Account Currency
// CashAsset dr CR
int temp = getC_BankAccount_ID();
setC_BankAccount_ID (line.getC_BankAccount_ID());
fact.createLine(line,
getAccount(Doc.ACCTTYPE_BankInTransit, as),
line.getC_Currency_ID(), line.getAmount().negate());
setC_BankAccount_ID(temp);
if (line.getC_Currency_ID() == getC_Currency_ID())
assetAmt = assetAmt.add (line.getAmount());
else
fact.createLine(line,
getAccount(Doc.ACCTTYPE_CashAsset, as),
line.getC_Currency_ID(), line.getAmount());
}
} // lines
// Cash Asset
fact.createLine(null, getAccount(Doc.ACCTTYPE_CashAsset, as),
getC_Currency_ID(), assetAmt);
//
ArrayList<Fact> facts = new ArrayList<Fact>();
facts.add(fact);
return facts;
} // createFact
} // Doc_Cash

View File

@ -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.acct;
import java.math.*;
import java.sql.*;
import java.util.*;
import org.compiere.model.*;
import java.util.logging.*;
import org.compiere.util.*;
/**
* Post Invoice Documents.
* <pre>
* Table: GL_Journal (224)
* Document Types: GLJ
* </pre>
* @author Jorg Janke
* @version $Id: Doc_GLJournal.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class Doc_GLJournal extends Doc
{
/**
* Constructor
* @param ass accounting schemata
* @param rs record
* @param trxName trx
*/
protected Doc_GLJournal (MAcctSchema[] ass, ResultSet rs, String trxName)
{
super(ass, MJournal.class, rs, null, trxName);
} // Foc_GL_Journal
/** Posting Type */
private String m_PostingType = null;
private int m_C_AcctSchema_ID = 0;
/**
* Load Specific Document Details
* @return error message or null
*/
protected String loadDocumentDetails ()
{
MJournal journal = (MJournal)getPO();
m_PostingType = journal.getPostingType();
m_C_AcctSchema_ID = journal.getC_AcctSchema_ID();
// Contained Objects
p_lines = loadLines(journal);
log.fine("Lines=" + p_lines.length);
return null;
} // loadDocumentDetails
/**
* Load Invoice Line
* @param journal journal
* @return DocLine Array
*/
private DocLine[] loadLines(MJournal journal)
{
ArrayList<DocLine> list = new ArrayList<DocLine>();
MJournalLine[] lines = journal.getLines(false);
for (int i = 0; i < lines.length; i++)
{
MJournalLine line = lines[i];
DocLine docLine = new DocLine (line, this);
// -- Source Amounts
docLine.setAmount (line.getAmtSourceDr(), line.getAmtSourceCr());
// -- Converted Amounts
docLine.setConvertedAmt (m_C_AcctSchema_ID, line.getAmtAcctDr(), line.getAmtAcctCr());
// -- Account
MAccount account = line.getAccount();
docLine.setAccount (account);
// -- Organization of Line was set to Org of Account
list.add(docLine);
}
// Return Array
int size = list.size();
DocLine[] dls = new DocLine[size];
list.toArray(dls);
return dls;
} // loadLines
/**************************************************************************
* Get Source Currency Balance - subtracts line and tax amounts from total - no rounding
* @return positive amount, if total invoice is bigger than lines
*/
public BigDecimal getBalance()
{
BigDecimal retValue = Env.ZERO;
StringBuffer sb = new StringBuffer (" [");
// Lines
for (int i = 0; i < p_lines.length; i++)
{
retValue = retValue.add(p_lines[i].getAmtSource());
sb.append("+").append(p_lines[i].getAmtSource());
}
sb.append("]");
//
log.fine(toString() + " Balance=" + retValue + sb.toString());
return retValue;
} // getBalance
/**
* Create Facts (the accounting logic) for
* GLJ.
* (only for the accounting scheme, it was created)
* <pre>
* account DR CR
* </pre>
* @param as acct schema
* @return Fact
*/
public ArrayList<Fact> createFacts (MAcctSchema as)
{
ArrayList<Fact> facts = new ArrayList<Fact>();
// Other Acct Schema
if (as.getC_AcctSchema_ID() != m_C_AcctSchema_ID)
return facts;
// create Fact Header
Fact fact = new Fact (this, as, m_PostingType);
// GLJ
if (getDocumentType().equals(DOCTYPE_GLJournal))
{
// account DR CR
for (int i = 0; i < p_lines.length; i++)
{
if (p_lines[i].getC_AcctSchema_ID () == as.getC_AcctSchema_ID ())
{
FactLine line = fact.createLine (p_lines[i],
p_lines[i].getAccount (),
getC_Currency_ID(),
p_lines[i].getAmtSourceDr (),
p_lines[i].getAmtSourceCr ());
}
} // for all lines
}
else
{
p_Error = "DocumentType unknown: " + getDocumentType();
log.log(Level.SEVERE, p_Error);
fact = null;
}
//
facts.add(fact);
return facts;
} // createFact
} // Doc_GLJournal

View File

@ -0,0 +1,283 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.acct;
import java.math.*;
import java.sql.*;
import java.util.*;
import org.compiere.model.*;
import java.util.logging.*;
import org.compiere.util.*;
/**
* Post Shipment/Receipt Documents.
* <pre>
* Table: M_InOut (319)
* Document Types: MMS, MMR
* </pre>
* @author Jorg Janke
* @version $Id: Doc_InOut.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class Doc_InOut extends Doc
{
/**
* Constructor
* @param ass accounting schemata
* @param rs record
* @param trxName trx
*/
public Doc_InOut (MAcctSchema[] ass, ResultSet rs, String trxName)
{
super (ass, MInOut.class, rs, null, trxName);
} // DocInOut
/**
* Load Document Details
* @return error message or null
*/
protected String loadDocumentDetails()
{
setC_Currency_ID(NO_CURRENCY);
MInOut inout = (MInOut)getPO();
setDateDoc (inout.getMovementDate());
// Contained Objects
p_lines = loadLines(inout);
log.fine("Lines=" + p_lines.length);
return null;
} // loadDocumentDetails
/**
* Load Invoice Line
* @param inout shipment/receipt
* @return DocLine Array
*/
private DocLine[] loadLines(MInOut inout)
{
ArrayList<DocLine> list = new ArrayList<DocLine>();
MInOutLine[] lines = inout.getLines(false);
for (int i = 0; i < lines.length; i++)
{
MInOutLine line = lines[i];
if (line.isDescription()
|| line.getM_Product_ID() == 0
|| line.getMovementQty().signum() == 0)
{
log.finer("Ignored: " + line);
continue;
}
DocLine docLine = new DocLine (line, this);
BigDecimal Qty = line.getMovementQty();
docLine.setQty (Qty, getDocumentType().equals(DOCTYPE_MatShipment)); // sets Trx and Storage Qty
//
log.fine(docLine.toString());
list.add (docLine);
}
// Return Array
DocLine[] dls = new DocLine[list.size()];
list.toArray(dls);
return dls;
} // loadLines
/**
* Get Balance
* @return Zero (always balanced)
*/
public BigDecimal getBalance()
{
BigDecimal retValue = Env.ZERO;
return retValue;
} // getBalance
/**
* Create Facts (the accounting logic) for
* MMS, MMR.
* <pre>
* Shipment
* CoGS (RevOrg) DR
* Inventory CR
* Shipment of Project Issue
* CoGS DR
* Project CR
* Receipt
* Inventory DR
* NotInvoicedReceipt CR
* </pre>
* @param as accounting schema
* @return Fact
*/
public ArrayList<Fact> createFacts (MAcctSchema as)
{
// create Fact Header
Fact fact = new Fact(this, as, Fact.POST_Actual);
setC_Currency_ID (as.getC_Currency_ID());
// Line pointers
FactLine dr = null;
FactLine cr = null;
// *** Sales - Shipment
if (getDocumentType().equals(DOCTYPE_MatShipment))
{
for (int i = 0; i < p_lines.length; i++)
{
DocLine line = p_lines[i];
BigDecimal costs = line.getProductCosts(as, line.getAD_Org_ID(), true);
if (costs == null || costs.signum() == 0) // zero costs OK
{
MProduct product = line.getProduct();
if (product.isStocked())
{
p_Error = "No Costs for " + line.getProduct().getName();
log.log(Level.WARNING, p_Error);
return null;
}
else // ignore service
continue;
}
// CoGS DR
dr = fact.createLine(line,
line.getAccount(ProductCost.ACCTTYPE_P_Cogs, as),
as.getC_Currency_ID(), costs, null);
if (dr == null)
{
p_Error = "FactLine DR not created: " + line;
log.log(Level.WARNING, p_Error);
return null;
}
dr.setM_Locator_ID(line.getM_Locator_ID());
dr.setLocationFromLocator(line.getM_Locator_ID(), true); // from Loc
dr.setLocationFromBPartner(getC_BPartner_Location_ID(), false); // to Loc
dr.setAD_Org_ID(line.getOrder_Org_ID()); // Revenue X-Org
dr.setQty(line.getQty().negate());
// Inventory CR
cr = fact.createLine(line,
line.getAccount(ProductCost.ACCTTYPE_P_Asset, as),
as.getC_Currency_ID(), null, costs);
if (cr == null)
{
p_Error = "FactLine CR not created: " + line;
log.log(Level.WARNING, p_Error);
return null;
}
cr.setM_Locator_ID(line.getM_Locator_ID());
cr.setLocationFromLocator(line.getM_Locator_ID(), true); // from Loc
cr.setLocationFromBPartner(getC_BPartner_Location_ID(), false); // to Loc
//
if (line.getM_Product_ID() != 0)
{
MCostDetail.createShipment(as, line.getAD_Org_ID(),
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
line.get_ID(), 0,
costs, line.getQty(),
line.getDescription(), true, getTrxName());
}
} // for all lines
updateProductInfo(as.getC_AcctSchema_ID()); // only for SO!
} // Shipment
// *** Purchasing - Receipt
else if (getDocumentType().equals(DOCTYPE_MatReceipt))
{
for (int i = 0; i < p_lines.length; i++)
{
DocLine line = p_lines[i];
BigDecimal costs = line.getProductCosts(as, line.getAD_Org_ID(), false); // non-zero costs
MProduct product = line.getProduct();
if (costs == null || costs.signum() == 0)
{
p_Error = "Resubmit - No Costs for " + product.getName();
log.log(Level.WARNING, p_Error);
return null;
}
// Inventory/Asset DR
MAccount assets = line.getAccount(ProductCost.ACCTTYPE_P_Asset, as);
if (product.isService())
assets = line.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
dr = fact.createLine(line, assets,
as.getC_Currency_ID(), costs, null);
if (dr == null)
{
p_Error = "DR not created: " + line;
log.log(Level.WARNING, p_Error);
return null;
}
dr.setM_Locator_ID(line.getM_Locator_ID());
dr.setLocationFromBPartner(getC_BPartner_Location_ID(), true); // from Loc
dr.setLocationFromLocator(line.getM_Locator_ID(), false); // to Loc
// NotInvoicedReceipt CR
cr = fact.createLine(line,
getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as),
as.getC_Currency_ID(), null, costs);
if (cr == null)
{
p_Error = "CR not created: " + line;
log.log(Level.WARNING, p_Error);
return null;
}
cr.setM_Locator_ID(line.getM_Locator_ID());
cr.setLocationFromBPartner(getC_BPartner_Location_ID(), true); // from Loc
cr.setLocationFromLocator(line.getM_Locator_ID(), false); // to Loc
cr.setQty(line.getQty().negate());
}
} // Receipt
else
{
p_Error = "DocumentType unknown: " + getDocumentType();
log.log(Level.SEVERE, p_Error);
return null;
}
//
ArrayList<Fact> facts = new ArrayList<Fact>();
facts.add(fact);
return facts;
} // createFact
/**
* Update Sales Order Costing Product Info (old).
* Purchase side handeled in Invoice Matching.
* <br>
* decrease average cumulatives
* @param C_AcctSchema_ID accounting schema
* @deprecated old costing
*/
private void updateProductInfo (int C_AcctSchema_ID)
{
log.fine("M_InOut_ID=" + get_ID());
// Old Model
StringBuffer sql = new StringBuffer(
"UPDATE M_Product_Costing pc "
+ "SET (CostAverageCumQty, CostAverageCumAmt)="
+ "(SELECT CostAverageCumQty - SUM(il.MovementQty),"
+ " CostAverageCumAmt - SUM(il.MovementQty*CurrentCostPrice) "
+ "FROM M_InOutLine il "
+ "WHERE pc.M_Product_ID=il.M_Product_ID"
+ " AND il.M_InOut_ID=").append(get_ID()).append(") ")
.append("WHERE EXISTS (SELECT * "
+ "FROM M_InOutLine il "
+ "WHERE pc.M_Product_ID=il.M_Product_ID"
+ " AND il.M_InOut_ID=").append(get_ID()).append(")");
int no = DB.executeUpdate(sql.toString(), getTrxName());
log.fine("M_Product_Costing - Updated=" + no);
//
} // updateProductInfo
} // Doc_InOut

View File

@ -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.acct;
import java.math.*;
import java.sql.*;
import java.util.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Post Inventory Documents.
* <pre>
* Table: M_Inventory (321)
* Document Types: MMI
* </pre>
* @author Jorg Janke
* @version $Id: Doc_Inventory.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class Doc_Inventory extends Doc
{
/**
* Constructor
* @param ass accounting schemata
* @param rs record
* @param trxName trx
*/
public Doc_Inventory (MAcctSchema[] ass, ResultSet rs, String trxName)
{
super (ass, MInventory.class, rs, DOCTYPE_MatInventory, trxName);
} // Doc_Inventory
/**
* Load Document Details
* @return error message or null
*/
protected String loadDocumentDetails()
{
setC_Currency_ID (NO_CURRENCY);
MInventory inventory = (MInventory)getPO();
setDateDoc (inventory.getMovementDate());
setDateAcct(inventory.getMovementDate());
// Contained Objects
p_lines = loadLines(inventory);
log.fine("Lines=" + p_lines.length);
return null;
} // loadDocumentDetails
/**
* Load Invoice Line
* @param inventory inventory
* @return DocLine Array
*/
private DocLine[] loadLines(MInventory inventory)
{
ArrayList<DocLine> list = new ArrayList<DocLine>();
MInventoryLine[] lines = inventory.getLines(false);
for (int i = 0; i < lines.length; i++)
{
MInventoryLine line = lines[i];
// nothing to post
if (line.getQtyBook().compareTo(line.getQtyCount()) == 0
&& line.getQtyInternalUse().signum() == 0)
continue;
//
DocLine docLine = new DocLine (line, this);
BigDecimal Qty = line.getQtyInternalUse();
if (Qty.signum() != 0)
Qty = Qty.negate(); // Internal Use entered positive
else
{
BigDecimal QtyBook = line.getQtyBook();
BigDecimal QtyCount = line.getQtyCount();
Qty = QtyCount.subtract(QtyBook);
}
docLine.setQty (Qty, false); // -5 => -5
//
log.fine(docLine.toString());
list.add (docLine);
}
// Return Array
DocLine[] dls = new DocLine[list.size()];
list.toArray(dls);
return dls;
} // loadLines
/**
* Get Balance
* @return Zero (always balanced)
*/
public BigDecimal getBalance()
{
BigDecimal retValue = Env.ZERO;
return retValue;
} // getBalance
/**
* Create Facts (the accounting logic) for
* MMI.
* <pre>
* Inventory
* Inventory DR CR
* InventoryDiff DR CR (or Charge)
* </pre>
* @param as account schema
* @return Fact
*/
public ArrayList<Fact> createFacts (MAcctSchema as)
{
// create Fact Header
Fact fact = new Fact(this, as, Fact.POST_Actual);
setC_Currency_ID(as.getC_Currency_ID());
// Line pointers
FactLine dr = null;
FactLine cr = null;
for (int i = 0; i < p_lines.length; i++)
{
DocLine line = p_lines[i];
BigDecimal costs = line.getProductCosts(as, line.getAD_Org_ID(), false);
if (costs == null || costs.signum() == 0)
{
p_Error = "No Costs for " + line.getProduct().getName();
return null;
}
// Inventory DR CR
dr = fact.createLine(line,
line.getAccount(ProductCost.ACCTTYPE_P_Asset, as),
as.getC_Currency_ID(), costs);
// may be zero difference - no line created.
if (dr == null)
continue;
dr.setM_Locator_ID(line.getM_Locator_ID());
// InventoryDiff DR CR
// or Charge
MAccount invDiff = line.getChargeAccount(as, costs.negate());
if (invDiff == null)
invDiff = getAccount(Doc.ACCTTYPE_InvDifferences, as);
cr = fact.createLine(line, invDiff,
as.getC_Currency_ID(), costs.negate());
if (cr == null)
continue;
cr.setM_Locator_ID(line.getM_Locator_ID());
cr.setQty(line.getQty().negate());
if (line.getC_Charge_ID() != 0) // explicit overwrite for charge
cr.setAD_Org_ID(line.getAD_Org_ID());
// Cost Detail
MCostDetail.createInventory(as, line.getAD_Org_ID(),
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
line.get_ID(), 0,
costs, line.getQty(),
line.getDescription(), getTrxName());
}
//
ArrayList<Fact> facts = new ArrayList<Fact>();
facts.add(fact);
return facts;
} // createFact
} // Doc_Inventory

View File

@ -0,0 +1,953 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.acct;
import java.math.*;
import java.sql.*;
import java.util.*;
import java.util.logging.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Post Invoice Documents.
* <pre>
* Table: C_Invoice (318)
* Document Types: ARI, ARC, ARF, API, APC
* </pre>
* @author Jorg Janke
* @version $Id: Doc_Invoice.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $
*/
public class Doc_Invoice extends Doc
{
/**
* Constructor
* @param ass accounting schemata
* @param rs record
* @param trxName trx
*/
protected Doc_Invoice(MAcctSchema[] ass, ResultSet rs, String trxName)
{
super (ass, MInvoice.class, rs, null, trxName);
} // Doc_Invoice
/** Contained Optional Tax Lines */
private DocTax[] m_taxes = null;
/** Currency Precision */
private int m_precision = -1;
/** All lines are Service */
private boolean m_allLinesService = true;
/** All lines are product item */
private boolean m_allLinesItem = true;
/**
* Load Specific Document Details
* @return error message or null
*/
protected String loadDocumentDetails ()
{
MInvoice invoice = (MInvoice)getPO();
setDateDoc(invoice.getDateInvoiced());
setIsTaxIncluded(invoice.isTaxIncluded());
// Amounts
setAmount(Doc.AMTTYPE_Gross, invoice.getGrandTotal());
setAmount(Doc.AMTTYPE_Net, invoice.getTotalLines());
setAmount(Doc.AMTTYPE_Charge, invoice.getChargeAmt());
// Contained Objects
m_taxes = loadTaxes();
p_lines = loadLines(invoice);
log.fine("Lines=" + p_lines.length + ", Taxes=" + m_taxes.length);
return null;
} // loadDocumentDetails
/**
* Load Invoice Taxes
* @return DocTax Array
*/
private DocTax[] loadTaxes()
{
ArrayList<DocTax> list = new ArrayList<DocTax>();
String sql = "SELECT it.C_Tax_ID, t.Name, t.Rate, it.TaxBaseAmt, it.TaxAmt, t.IsSalesTax "
+ "FROM C_Tax t, C_InvoiceTax it "
+ "WHERE t.C_Tax_ID=it.C_Tax_ID AND it.C_Invoice_ID=?";
try
{
PreparedStatement pstmt = DB.prepareStatement(sql, getTrxName());
pstmt.setInt(1, get_ID());
ResultSet rs = pstmt.executeQuery();
//
while (rs.next())
{
int C_Tax_ID = rs.getInt(1);
String name = rs.getString(2);
BigDecimal rate = rs.getBigDecimal(3);
BigDecimal taxBaseAmt = rs.getBigDecimal(4);
BigDecimal amount = rs.getBigDecimal(5);
boolean salesTax = "Y".equals(rs.getString(6));
//
DocTax taxLine = new DocTax(C_Tax_ID, name, rate,
taxBaseAmt, amount, salesTax);
log.fine(taxLine.toString());
list.add(taxLine);
}
//
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, sql, e);
return null;
}
// Return Array
DocTax[] tl = new DocTax[list.size()];
list.toArray(tl);
return tl;
} // loadTaxes
/**
* Load Invoice Line
* @param invoice invoice
* @return DocLine Array
*/
private DocLine[] loadLines (MInvoice invoice)
{
ArrayList<DocLine> list = new ArrayList<DocLine>();
//
MInvoiceLine[] lines = invoice.getLines(false);
for (int i = 0; i < lines.length; i++)
{
MInvoiceLine line = lines[i];
if (line.isDescription())
continue;
DocLine docLine = new DocLine(line, this);
// Qty
BigDecimal Qty = line.getQtyInvoiced();
boolean cm = getDocumentType().equals(DOCTYPE_ARCredit)
|| getDocumentType().equals(DOCTYPE_APCredit);
docLine.setQty(cm ? Qty.negate() : Qty, invoice.isSOTrx());
//
BigDecimal LineNetAmt = line.getLineNetAmt();
BigDecimal PriceList = line.getPriceList();
int C_Tax_ID = docLine.getC_Tax_ID();
// Correct included Tax
if (isTaxIncluded() && C_Tax_ID != 0)
{
MTax tax = MTax.get(getCtx(), C_Tax_ID);
if (!tax.isZeroTax())
{
BigDecimal LineNetAmtTax = tax.calculateTax(LineNetAmt, true, getStdPercision());
log.fine("LineNetAmt=" + LineNetAmt + " - Tax=" + LineNetAmtTax);
LineNetAmt = LineNetAmt.subtract(LineNetAmtTax);
for (int t = 0; t < m_taxes.length; t++)
{
if (m_taxes[t].getC_Tax_ID() == C_Tax_ID)
{
m_taxes[t].addIncludedTax(LineNetAmtTax);
break;
}
}
BigDecimal PriceListTax = tax.calculateTax(PriceList, true, getStdPercision());
PriceList = PriceList.subtract(PriceListTax);
}
} // correct included Tax
docLine.setAmount (LineNetAmt, PriceList, Qty); // qty for discount calc
if (docLine.isItem())
m_allLinesService = false;
else
m_allLinesItem = false;
//
log.fine(docLine.toString());
list.add(docLine);
}
// Convert to Array
DocLine[] dls = new DocLine[list.size()];
list.toArray(dls);
// Included Tax - make sure that no difference
if (isTaxIncluded())
{
for (int i = 0; i < m_taxes.length; i++)
{
if (m_taxes[i].isIncludedTaxDifference())
{
BigDecimal diff = m_taxes[i].getIncludedTaxDifference();
for (int j = 0; j < dls.length; j++)
{
if (dls[j].getC_Tax_ID() == m_taxes[i].getC_Tax_ID())
{
dls[j].setLineNetAmtDifference(diff);
break;
}
} // for all lines
} // tax difference
} // for all taxes
} // Included Tax difference
// Return Array
return dls;
} // loadLines
/**
* Get Currency Percision
* @return precision
*/
private int getStdPercision()
{
if (m_precision == -1)
m_precision = MCurrency.getStdPrecision(getCtx(), getC_Currency_ID());
return m_precision;
} // getPrecision
/**************************************************************************
* Get Source Currency Balance - subtracts line and tax amounts from total - no rounding
* @return positive amount, if total invoice is bigger than lines
*/
public BigDecimal getBalance()
{
BigDecimal retValue = Env.ZERO;
StringBuffer sb = new StringBuffer (" [");
// Total
retValue = retValue.add(getAmount(Doc.AMTTYPE_Gross));
sb.append(getAmount(Doc.AMTTYPE_Gross));
// - Header Charge
retValue = retValue.subtract(getAmount(Doc.AMTTYPE_Charge));
sb.append("-").append(getAmount(Doc.AMTTYPE_Charge));
// - Tax
for (int i = 0; i < m_taxes.length; i++)
{
retValue = retValue.subtract(m_taxes[i].getAmount());
sb.append("-").append(m_taxes[i].getAmount());
}
// - Lines
for (int i = 0; i < p_lines.length; i++)
{
retValue = retValue.subtract(p_lines[i].getAmtSource());
sb.append("-").append(p_lines[i].getAmtSource());
}
sb.append("]");
//
log.fine(toString() + " Balance=" + retValue + sb.toString());
return retValue;
} // getBalance
/**
* Create Facts (the accounting logic) for
* ARI, ARC, ARF, API, APC.
* <pre>
* ARI, ARF
* Receivables DR
* Charge CR
* TaxDue CR
* Revenue CR
*
* ARC
* Receivables CR
* Charge DR
* TaxDue DR
* Revenue RR
*
* API
* Payables CR
* Charge DR
* TaxCredit DR
* Expense DR
*
* APC
* Payables DR
* Charge CR
* TaxCredit CR
* Expense CR
* </pre>
* @param as accounting schema
* @return Fact
*/
public ArrayList<Fact> createFacts (MAcctSchema as)
{
//
ArrayList<Fact> facts = new ArrayList<Fact>();
// create Fact Header
Fact fact = new Fact(this, as, Fact.POST_Actual);
// Cash based accounting
if (!as.isAccrual())
return facts;
// ** ARI, ARF
if (getDocumentType().equals(DOCTYPE_ARInvoice)
|| getDocumentType().equals(DOCTYPE_ARProForma))
{
BigDecimal grossAmt = getAmount(Doc.AMTTYPE_Gross);
BigDecimal serviceAmt = Env.ZERO;
// Header Charge CR
BigDecimal amt = getAmount(Doc.AMTTYPE_Charge);
if (amt != null && amt.signum() != 0)
fact.createLine(null, getAccount(Doc.ACCTTYPE_Charge, as),
getC_Currency_ID(), null, amt);
// TaxDue CR
for (int i = 0; i < m_taxes.length; i++)
{
amt = m_taxes[i].getAmount();
if (amt != null && amt.signum() != 0)
{
FactLine tl = fact.createLine(null, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxDue, as),
getC_Currency_ID(), null, amt);
if (tl != null)
tl.setC_Tax_ID(m_taxes[i].getC_Tax_ID());
}
}
// Revenue CR
for (int i = 0; i < p_lines.length; i++)
{
amt = p_lines[i].getAmtSource();
BigDecimal dAmt = null;
if (as.isTradeDiscountPosted())
{
BigDecimal discount = p_lines[i].getDiscount();
if (discount != null && discount.signum() != 0)
{
amt = amt.add(discount);
dAmt = discount;
}
}
fact.createLine (p_lines[i],
p_lines[i].getAccount(ProductCost.ACCTTYPE_P_Revenue, as),
getC_Currency_ID(), dAmt, amt);
if (!p_lines[i].isItem())
{
grossAmt = grossAmt.subtract(amt);
serviceAmt = serviceAmt.add(amt);
}
}
// Set Locations
FactLine[] fLines = fact.getLines();
for (int i = 0; i < fLines.length; i++)
{
if (fLines[i] != null)
{
fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(), true); // from Loc
fLines[i].setLocationFromBPartner(getC_BPartner_Location_ID(), false); // to Loc
}
}
// Receivables DR
int receivables_ID = getValidCombination_ID(Doc.ACCTTYPE_C_Receivable, as);
int receivablesServices_ID = getValidCombination_ID (Doc.ACCTTYPE_C_Receivable_Services, as);
if (m_allLinesItem || !as.isPostServices()
|| receivables_ID == receivablesServices_ID)
{
grossAmt = getAmount(Doc.AMTTYPE_Gross);
serviceAmt = Env.ZERO;
}
else if (m_allLinesService)
{
serviceAmt = getAmount(Doc.AMTTYPE_Gross);
grossAmt = Env.ZERO;
}
if (grossAmt.signum() != 0)
fact.createLine(null, MAccount.get(getCtx(), receivables_ID),
getC_Currency_ID(), grossAmt, null);
if (serviceAmt.signum() != 0)
fact.createLine(null, MAccount.get(getCtx(), receivablesServices_ID),
getC_Currency_ID(), serviceAmt, null);
}
// ARC
else if (getDocumentType().equals(DOCTYPE_ARCredit))
{
BigDecimal grossAmt = getAmount(Doc.AMTTYPE_Gross);
BigDecimal serviceAmt = Env.ZERO;
// Header Charge DR
BigDecimal amt = getAmount(Doc.AMTTYPE_Charge);
if (amt != null && amt.signum() != 0)
fact.createLine(null, getAccount(Doc.ACCTTYPE_Charge, as),
getC_Currency_ID(), amt, null);
// TaxDue DR
for (int i = 0; i < m_taxes.length; i++)
{
amt = m_taxes[i].getAmount();
if (amt != null && amt.signum() != 0)
{
FactLine tl = fact.createLine(null, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxDue, as),
getC_Currency_ID(), amt, null);
if (tl != null)
tl.setC_Tax_ID(m_taxes[i].getC_Tax_ID());
}
}
// Revenue CR
for (int i = 0; i < p_lines.length; i++)
{
amt = p_lines[i].getAmtSource();
BigDecimal dAmt = null;
if (as.isTradeDiscountPosted())
{
BigDecimal discount = p_lines[i].getDiscount();
if (discount != null && discount.signum() != 0)
{
amt = amt.add(discount);
dAmt = discount;
}
}
fact.createLine (p_lines[i],
p_lines[i].getAccount (ProductCost.ACCTTYPE_P_Revenue, as),
getC_Currency_ID(), amt, dAmt);
if (!p_lines[i].isItem())
{
grossAmt = grossAmt.subtract(amt);
serviceAmt = serviceAmt.add(amt);
}
}
// Set Locations
FactLine[] fLines = fact.getLines();
for (int i = 0; i < fLines.length; i++)
{
if (fLines[i] != null)
{
fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(), true); // from Loc
fLines[i].setLocationFromBPartner(getC_BPartner_Location_ID(), false); // to Loc
}
}
// Receivables CR
int receivables_ID = getValidCombination_ID (Doc.ACCTTYPE_C_Receivable, as);
int receivablesServices_ID = getValidCombination_ID (Doc.ACCTTYPE_C_Receivable_Services, as);
if (m_allLinesItem || !as.isPostServices()
|| receivables_ID == receivablesServices_ID)
{
grossAmt = getAmount(Doc.AMTTYPE_Gross);
serviceAmt = Env.ZERO;
}
else if (m_allLinesService)
{
serviceAmt = getAmount(Doc.AMTTYPE_Gross);
grossAmt = Env.ZERO;
}
if (grossAmt.signum() != 0)
fact.createLine(null, MAccount.get(getCtx(), receivables_ID),
getC_Currency_ID(), null, grossAmt);
if (serviceAmt.signum() != 0)
fact.createLine(null, MAccount.get(getCtx(), receivablesServices_ID),
getC_Currency_ID(), null, serviceAmt);
}
// ** API
else if (getDocumentType().equals(DOCTYPE_APInvoice))
{
BigDecimal grossAmt = getAmount(Doc.AMTTYPE_Gross);
BigDecimal serviceAmt = Env.ZERO;
// Charge DR
fact.createLine(null, getAccount(Doc.ACCTTYPE_Charge, as),
getC_Currency_ID(), getAmount(Doc.AMTTYPE_Charge), null);
// TaxCredit DR
for (int i = 0; i < m_taxes.length; i++)
{
FactLine tl = fact.createLine(null, m_taxes[i].getAccount(m_taxes[i].getAPTaxType(), as),
getC_Currency_ID(), m_taxes[i].getAmount(), null);
if (tl != null)
tl.setC_Tax_ID(m_taxes[i].getC_Tax_ID());
}
// Expense DR
for (int i = 0; i < p_lines.length; i++)
{
DocLine line = p_lines[i];
boolean landedCost = landedCost(as, fact, line, true);
if (landedCost && as.isExplicitCostAdjustment())
{
fact.createLine (line, line.getAccount(ProductCost.ACCTTYPE_P_Expense, as),
getC_Currency_ID(), line.getAmtSource(), null);
//
FactLine fl = fact.createLine (line, line.getAccount(ProductCost.ACCTTYPE_P_Expense, as),
getC_Currency_ID(), null, line.getAmtSource());
String desc = line.getDescription();
if (desc == null)
desc = "100%";
else
desc += " 100%";
fl.setDescription(desc);
}
if (!landedCost)
{
MAccount expense = line.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
if (line.isItem())
expense = line.getAccount (ProductCost.ACCTTYPE_P_InventoryClearing, as);
BigDecimal amt = line.getAmtSource();
BigDecimal dAmt = null;
if (as.isTradeDiscountPosted() && !line.isItem())
{
BigDecimal discount = line.getDiscount();
if (discount != null && discount.signum() != 0)
{
amt = amt.add(discount);
dAmt = discount;
}
}
fact.createLine (line, expense,
getC_Currency_ID(), amt, dAmt);
if (!line.isItem())
{
grossAmt = grossAmt.subtract(amt);
serviceAmt = serviceAmt.add(amt);
}
//
if (line.getM_Product_ID() != 0
&& line.getProduct().isService()) // otherwise Inv Matching
MCostDetail.createInvoice(as, line.getAD_Org_ID(),
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
line.get_ID(), 0, // No Cost Element
line.getAmtSource(), line.getQty(),
line.getDescription(), getTrxName());
}
}
// Set Locations
FactLine[] fLines = fact.getLines();
for (int i = 0; i < fLines.length; i++)
{
if (fLines[i] != null)
{
fLines[i].setLocationFromBPartner(getC_BPartner_Location_ID(), true); // from Loc
fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(), false); // to Loc
}
}
// Liability CR
int payables_ID = getValidCombination_ID (Doc.ACCTTYPE_V_Liability, as);
int payablesServices_ID = getValidCombination_ID (Doc.ACCTTYPE_V_Liability_Services, as);
if (m_allLinesItem || !as.isPostServices()
|| payables_ID == payablesServices_ID)
{
grossAmt = getAmount(Doc.AMTTYPE_Gross);
serviceAmt = Env.ZERO;
}
else if (m_allLinesService)
{
serviceAmt = getAmount(Doc.AMTTYPE_Gross);
grossAmt = Env.ZERO;
}
if (grossAmt.signum() != 0)
fact.createLine(null, MAccount.get(getCtx(), payables_ID),
getC_Currency_ID(), null, grossAmt);
if (serviceAmt.signum() != 0)
fact.createLine(null, MAccount.get(getCtx(), payablesServices_ID),
getC_Currency_ID(), null, serviceAmt);
//
updateProductPO(as); // Only API
updateProductInfo (as.getC_AcctSchema_ID()); // only API
}
// APC
else if (getDocumentType().equals(DOCTYPE_APCredit))
{
BigDecimal grossAmt = getAmount(Doc.AMTTYPE_Gross);
BigDecimal serviceAmt = Env.ZERO;
// Charge CR
fact.createLine (null, getAccount(Doc.ACCTTYPE_Charge, as),
getC_Currency_ID(), null, getAmount(Doc.AMTTYPE_Charge));
// TaxCredit CR
for (int i = 0; i < m_taxes.length; i++)
{
FactLine tl = fact.createLine (null, m_taxes[i].getAccount(m_taxes[i].getAPTaxType(), as),
getC_Currency_ID(), null, m_taxes[i].getAmount());
if (tl != null)
tl.setC_Tax_ID(m_taxes[i].getC_Tax_ID());
}
// Expense CR
for (int i = 0; i < p_lines.length; i++)
{
DocLine line = p_lines[i];
boolean landedCost = landedCost(as, fact, line, false);
if (landedCost && as.isExplicitCostAdjustment())
{
fact.createLine (line, line.getAccount(ProductCost.ACCTTYPE_P_Expense, as),
getC_Currency_ID(), null, line.getAmtSource());
//
FactLine fl = fact.createLine (line, line.getAccount(ProductCost.ACCTTYPE_P_Expense, as),
getC_Currency_ID(), line.getAmtSource(), null);
String desc = line.getDescription();
if (desc == null)
desc = "100%";
else
desc += " 100%";
fl.setDescription(desc);
}
if (!landedCost)
{
MAccount expense = line.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
if (line.isItem())
expense = line.getAccount (ProductCost.ACCTTYPE_P_InventoryClearing, as);
BigDecimal amt = line.getAmtSource();
BigDecimal dAmt = null;
if (as.isTradeDiscountPosted() && !line.isItem())
{
BigDecimal discount = line.getDiscount();
if (discount != null && discount.signum() != 0)
{
amt = amt.add(discount);
dAmt = discount;
}
}
fact.createLine (line, expense,
getC_Currency_ID(), dAmt, amt);
if (!line.isItem())
{
grossAmt = grossAmt.subtract(amt);
serviceAmt = serviceAmt.add(amt);
}
//
if (line.getM_Product_ID() != 0
&& line.getProduct().isService()) // otherwise Inv Matching
MCostDetail.createInvoice(as, line.getAD_Org_ID(),
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
line.get_ID(), 0, // No Cost Element
line.getAmtSource().negate(), line.getQty(),
line.getDescription(), getTrxName());
}
}
// Set Locations
FactLine[] fLines = fact.getLines();
for (int i = 0; i < fLines.length; i++)
{
if (fLines[i] != null)
{
fLines[i].setLocationFromBPartner(getC_BPartner_Location_ID(), true); // from Loc
fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(), false); // to Loc
}
}
// Liability DR
int payables_ID = getValidCombination_ID (Doc.ACCTTYPE_V_Liability, as);
int payablesServices_ID = getValidCombination_ID (Doc.ACCTTYPE_V_Liability_Services, as);
if (m_allLinesItem || !as.isPostServices()
|| payables_ID == payablesServices_ID)
{
grossAmt = getAmount(Doc.AMTTYPE_Gross);
serviceAmt = Env.ZERO;
}
else if (m_allLinesService)
{
serviceAmt = getAmount(Doc.AMTTYPE_Gross);
grossAmt = Env.ZERO;
}
if (grossAmt.signum() != 0)
fact.createLine(null, MAccount.get(getCtx(), payables_ID),
getC_Currency_ID(), grossAmt, null);
if (serviceAmt.signum() != 0)
fact.createLine(null, MAccount.get(getCtx(), payablesServices_ID),
getC_Currency_ID(), serviceAmt, null);
}
else
{
p_Error = "DocumentType unknown: " + getDocumentType();
log.log(Level.SEVERE, p_Error);
fact = null;
}
//
facts.add(fact);
return facts;
} // createFact
/**
* Create Fact Cash Based (i.e. only revenue/expense)
* @param as accounting schema
* @param fact fact to add lines to
* @param multiplier source amount multiplier
* @return accounted amount
*/
public BigDecimal createFactCash (MAcctSchema as, Fact fact, BigDecimal multiplier)
{
boolean creditMemo = getDocumentType().equals(DOCTYPE_ARCredit)
|| getDocumentType().equals(DOCTYPE_APCredit);
boolean payables = getDocumentType().equals(DOCTYPE_APInvoice)
|| getDocumentType().equals(DOCTYPE_APCredit);
BigDecimal acctAmt = Env.ZERO;
FactLine fl = null;
// Revenue/Cost
for (int i = 0; i < p_lines.length; i++)
{
DocLine line = p_lines[i];
boolean landedCost = false;
if (payables)
landedCost = landedCost(as, fact, line, false);
if (landedCost && as.isExplicitCostAdjustment())
{
fact.createLine (line, line.getAccount(ProductCost.ACCTTYPE_P_Expense, as),
getC_Currency_ID(), null, line.getAmtSource());
//
fl = fact.createLine (line, line.getAccount(ProductCost.ACCTTYPE_P_Expense, as),
getC_Currency_ID(), line.getAmtSource(), null);
String desc = line.getDescription();
if (desc == null)
desc = "100%";
else
desc += " 100%";
fl.setDescription(desc);
}
if (!landedCost)
{
MAccount acct = line.getAccount(
payables ? ProductCost.ACCTTYPE_P_Expense : ProductCost.ACCTTYPE_P_Revenue, as);
if (payables)
{
// if Fixed Asset
if (line.isItem())
acct = line.getAccount (ProductCost.ACCTTYPE_P_InventoryClearing, as);
}
BigDecimal amt = line.getAmtSource().multiply(multiplier);
BigDecimal amt2 = null;
if (creditMemo)
{
amt2 = amt;
amt = null;
}
if (payables) // Vendor = DR
fl = fact.createLine (line, acct,
getC_Currency_ID(), amt, amt2);
else // Customer = CR
fl = fact.createLine (line, acct,
getC_Currency_ID(), amt2, amt);
if (fl != null)
acctAmt = acctAmt.add(fl.getAcctBalance());
}
}
// Tax
for (int i = 0; i < m_taxes.length; i++)
{
BigDecimal amt = m_taxes[i].getAmount();
BigDecimal amt2 = null;
if (creditMemo)
{
amt2 = amt;
amt = null;
}
FactLine tl = null;
if (payables)
tl = fact.createLine (null, m_taxes[i].getAccount(m_taxes[i].getAPTaxType(), as),
getC_Currency_ID(), amt, amt2);
else
tl = fact.createLine (null, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxDue, as),
getC_Currency_ID(), amt2, amt);
if (tl != null)
tl.setC_Tax_ID(m_taxes[i].getC_Tax_ID());
}
// Set Locations
FactLine[] fLines = fact.getLines();
for (int i = 0; i < fLines.length; i++)
{
if (fLines[i] != null)
{
if (payables)
{
fLines[i].setLocationFromBPartner(getC_BPartner_Location_ID(), true); // from Loc
fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(), false); // to Loc
}
else
{
fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(), true); // from Loc
fLines[i].setLocationFromBPartner(getC_BPartner_Location_ID(), false); // to Loc
}
}
}
return acctAmt;
} // createFactCash
/**
* Create Landed Cost accounting & Cost lines
* @param as accounting schema
* @param fact fact
* @param line document line
* @param dr DR entry (normal api)
* @return true if landed costs were created
*/
private boolean landedCost (MAcctSchema as, Fact fact, DocLine line, boolean dr)
{
int C_InvoiceLine_ID = line.get_ID();
MLandedCostAllocation[] lcas = MLandedCostAllocation.getOfInvoiceLine(
getCtx(), C_InvoiceLine_ID, getTrxName());
if (lcas.length == 0)
return false;
// Delete Old
String sql = "DELETE M_CostDetail WHERE C_InvoiceLine_ID=" + C_InvoiceLine_ID;
int no = DB.executeUpdate(sql, getTrxName());
if (no != 0)
log.config("CostDetail Deleted #" + no);
// Calculate Total Base
double totalBase = 0;
for (int i = 0; i < lcas.length; i++)
totalBase += lcas[i].getBase().doubleValue();
// Create New
MInvoiceLine il = new MInvoiceLine (getCtx(), C_InvoiceLine_ID, getTrxName());
for (int i = 0; i < lcas.length; i++)
{
MLandedCostAllocation lca = lcas[i];
if (lca.getBase().signum() == 0)
continue;
double percent = totalBase / lca.getBase().doubleValue();
String desc = il.getDescription();
if (desc == null)
desc = percent + "%";
else
desc += " - " + percent + "%";
if (line.getDescription() != null)
desc += " - " + line.getDescription();
// Accounting
ProductCost pc = new ProductCost (Env.getCtx(),
lca.getM_Product_ID(), lca.getM_AttributeSetInstance_ID(), getTrxName());
BigDecimal drAmt = null;
BigDecimal crAmt = null;
if (dr)
drAmt = lca.getAmt();
else
crAmt = lca.getAmt();
FactLine fl = fact.createLine (line, pc.getAccount(ProductCost.ACCTTYPE_P_CostAdjustment, as),
getC_Currency_ID(), drAmt, crAmt);
fl.setDescription(desc);
// Cost Detail - Convert to AcctCurrency
BigDecimal allocationAmt = lca.getAmt();
if (getC_Currency_ID() != as.getC_Currency_ID())
allocationAmt = MConversionRate.convert(getCtx(), allocationAmt,
getC_Currency_ID(), as.getC_Currency_ID(),
getDateAcct(), getC_ConversionType_ID(),
getAD_Client_ID(), getAD_Org_ID());
if (allocationAmt.scale() > as.getCostingPrecision())
allocationAmt = allocationAmt.setScale(as.getCostingPrecision(), BigDecimal.ROUND_HALF_UP);
if (!dr)
allocationAmt = allocationAmt.negate();
MCostDetail cd = new MCostDetail (as, lca.getAD_Org_ID(),
lca.getM_Product_ID(), lca.getM_AttributeSetInstance_ID(),
lca.getM_CostElement_ID(),
allocationAmt, Env.ZERO, // Qty
desc, getTrxName());
cd.setC_InvoiceLine_ID(C_InvoiceLine_ID);
boolean ok = cd.save();
if (ok && !cd.isProcessed())
{
MClient client = MClient.get(as.getCtx(), as.getAD_Client_ID());
if (client.isCostImmediate())
cd.process();
}
}
log.config("Created #" + lcas.length);
return true;
} // landedCosts
/**
* Update ProductPO PriceLastInv
* @param as accounting schema
*/
private void updateProductPO (MAcctSchema as)
{
MClientInfo ci = MClientInfo.get(getCtx(), as.getAD_Client_ID());
if (ci.getC_AcctSchema1_ID() != as.getC_AcctSchema_ID())
return;
StringBuffer sql = new StringBuffer (
"UPDATE M_Product_PO po "
+ "SET PriceLastInv = "
// select
+ "(SELECT currencyConvert(il.PriceActual,i.C_Currency_ID,po.C_Currency_ID,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID) "
+ "FROM C_Invoice i, C_InvoiceLine il "
+ "WHERE i.C_Invoice_ID=il.C_Invoice_ID"
+ " AND po.M_Product_ID=il.M_Product_ID AND po.C_BPartner_ID=i.C_BPartner_ID"
+ " AND ROWNUM=1 AND i.C_Invoice_ID=").append(get_ID()).append(") ")
// update
.append("WHERE EXISTS (SELECT * "
+ "FROM C_Invoice i, C_InvoiceLine il "
+ "WHERE i.C_Invoice_ID=il.C_Invoice_ID"
+ " AND po.M_Product_ID=il.M_Product_ID AND po.C_BPartner_ID=i.C_BPartner_ID"
+ " AND i.C_Invoice_ID=").append(get_ID()).append(")");
int no = DB.executeUpdate(sql.toString(), getTrxName());
log.fine("Updated=" + no);
} // updateProductPO
/**
* Update Product Info (old).
* - Costing (PriceLastInv)
* - PO (PriceLastInv)
* @param C_AcctSchema_ID accounting schema
* @deprecated old costing
*/
private void updateProductInfo (int C_AcctSchema_ID)
{
log.fine("C_Invoice_ID=" + get_ID());
/** @todo Last.. would need to compare document/last updated date
* would need to maintain LastPriceUpdateDate on _PO and _Costing */
// update Product Costing
// requires existence of currency conversion !!
// if there are multiple lines of the same product last price uses first
// -> TotalInvAmt is sometimes NULL !! -> error
// begin globalqss 2005-10-19
// postgresql doesn't support LIMIT on UPDATE or DELETE statements
/*
StringBuffer sql = new StringBuffer (
"UPDATE M_Product_Costing pc "
+ "SET (PriceLastInv, TotalInvAmt,TotalInvQty) = "
// select
+ "(SELECT currencyConvert(il.PriceActual,i.C_Currency_ID,a.C_Currency_ID,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID),"
+ " currencyConvert(il.LineNetAmt,i.C_Currency_ID,a.C_Currency_ID,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID),il.QtyInvoiced "
+ "FROM C_Invoice i, C_InvoiceLine il, C_AcctSchema a "
+ "WHERE i.C_Invoice_ID=il.C_Invoice_ID"
+ " AND pc.M_Product_ID=il.M_Product_ID AND pc.C_AcctSchema_ID=a.C_AcctSchema_ID"
+ " AND ROWNUM=1"
+ " AND pc.C_AcctSchema_ID=").append(C_AcctSchema_ID).append(" AND i.C_Invoice_ID=")
.append(get_ID()).append(") ")
// update
.append("WHERE EXISTS (SELECT * "
+ "FROM C_Invoice i, C_InvoiceLine il, C_AcctSchema a "
+ "WHERE i.C_Invoice_ID=il.C_Invoice_ID"
+ " AND pc.M_Product_ID=il.M_Product_ID AND pc.C_AcctSchema_ID=a.C_AcctSchema_ID"
+ " AND pc.C_AcctSchema_ID=").append(C_AcctSchema_ID).append(" AND i.C_Invoice_ID=")
.append(get_ID()).append(")");
*/
// the next command is equivalent and works in postgresql and oracle
StringBuffer sql = new StringBuffer (
"UPDATE M_Product_Costing pc "
+ "SET (PriceLastInv, TotalInvAmt,TotalInvQty) = "
// select
+ "(SELECT currencyConvert(il.PriceActual,i.C_Currency_ID,a.C_Currency_ID,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID),"
+ " currencyConvert(il.LineNetAmt,i.C_Currency_ID,a.C_Currency_ID,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID),il.QtyInvoiced "
+ "FROM C_Invoice i, C_InvoiceLine il, C_AcctSchema a "
+ "WHERE i.C_Invoice_ID=il.C_Invoice_ID"
+ " AND il.c_invoiceline_id = (SELECT MIN(C_InvoiceLine_ID) FROM C_InvoiceLine WHERE C_Invoice_ID=")
.append(get_ID()).append(")"
+ " AND pc.M_Product_ID=il.M_Product_ID AND pc.C_AcctSchema_ID=a.C_AcctSchema_ID"
+ " AND pc.C_AcctSchema_ID=").append(C_AcctSchema_ID).append(" AND i.C_Invoice_ID=")
.append(get_ID()).append(") ")
// update
.append("WHERE EXISTS (SELECT * "
+ "FROM C_Invoice i, C_InvoiceLine il, C_AcctSchema a "
+ "WHERE i.C_Invoice_ID=il.C_Invoice_ID"
+ " AND pc.M_Product_ID=il.M_Product_ID AND pc.C_AcctSchema_ID=a.C_AcctSchema_ID"
+ " AND pc.C_AcctSchema_ID=").append(C_AcctSchema_ID).append(" AND i.C_Invoice_ID=")
.append(get_ID()).append(")");
// end globalqss 2005-10-19
int no = DB.executeUpdate(sql.toString(), getTrxName());
log.fine("M_Product_Costing - Updated=" + no);
} // updateProductInfo
} // Doc_Invoice

View File

@ -0,0 +1,327 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.acct;
import java.math.*;
import java.sql.*;
import java.util.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Post MatchInv Documents.
* <pre>
* Table: M_MatchInv (472)
* Document Types: MXI
* </pre>
* Update Costing Records
* @author Jorg Janke
* @version $Id: Doc_MatchInv.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class Doc_MatchInv extends Doc
{
/**
* Constructor
* @param ass accounting schemata
* @param rs record
* @param trxName trx
*/
protected Doc_MatchInv (MAcctSchema[] ass, ResultSet rs, String trxName)
{
super(ass, MMatchInv.class, rs, DOCTYPE_MatMatchInv, trxName);
} // Doc_MatchInv
/** Invoice Line */
private MInvoiceLine m_invoiceLine = null;
/** Material Receipt */
private MInOutLine m_receiptLine = null;
private ProductCost m_pc = null;
/** Commitments */
private DocLine[] m_commitments = null;
/**
* Load Specific Document Details
* @return error message or null
*/
protected String loadDocumentDetails ()
{
setC_Currency_ID (Doc.NO_CURRENCY);
MMatchInv matchInv = (MMatchInv)getPO();
setDateDoc(matchInv.getDateTrx());
setQty (matchInv.getQty());
// Invoice Info
int C_InvoiceLine_ID = matchInv.getC_InvoiceLine_ID();
m_invoiceLine = new MInvoiceLine (getCtx(), C_InvoiceLine_ID, null);
// BP for NotInvoicedReceipts
int C_BPartner_ID = m_invoiceLine.getParent().getC_BPartner_ID();
setC_BPartner_ID(C_BPartner_ID);
//
int M_InOutLine_ID = matchInv.getM_InOutLine_ID();
m_receiptLine = new MInOutLine (getCtx(), M_InOutLine_ID, null);
//
m_pc = new ProductCost (Env.getCtx(),
getM_Product_ID(), matchInv.getM_AttributeSetInstance_ID(), null);
m_pc.setQty(getQty());
return null;
} // loadDocumentDetails
/**************************************************************************
* Get Source Currency Balance - subtracts line and tax amounts from total - no rounding
* @return Zero (always balanced)
*/
public BigDecimal getBalance()
{
return Env.ZERO;
} // getBalance
/**
* Create Facts (the accounting logic) for
* MXI.
* (single line)
* <pre>
* NotInvoicedReceipts DR (Receipt Org)
* InventoryClearing CR
* InvoicePV DR CR (difference)
* Commitment
* Expense CR
* Offset DR
* </pre>
* @param as accounting schema
* @return Fact
*/
public ArrayList<Fact> createFacts (MAcctSchema as)
{
ArrayList<Fact> facts = new ArrayList<Fact>();
// Nothing to do
if (getM_Product_ID() == 0 // no Product
|| getQty().signum() == 0
|| m_receiptLine.getMovementQty().signum() == 0) // Qty = 0
{
log.fine("No Product/Qty - M_Product_ID=" + getM_Product_ID()
+ ",Qty=" + getQty() + ",InOutQty=" + m_receiptLine.getMovementQty());
return facts;
}
MMatchInv matchInv = (MMatchInv)getPO();
// create Fact Header
Fact fact = new Fact(this, as, Fact.POST_Actual);
setC_Currency_ID (as.getC_Currency_ID());
/** Needs to be handeled in PO Matching as no Receipt info
if (m_pc.isService())
{
log.fine("Service - skipped");
return fact;
}
**/
// NotInvoicedReceipt DR
// From Receipt
BigDecimal multiplier = getQty()
.divide(m_receiptLine.getMovementQty(), 12, BigDecimal.ROUND_HALF_UP)
.abs();
FactLine dr = fact.createLine (null,
getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as),
as.getC_Currency_ID(), Env.ONE, null); // updated below
if (dr == null)
{
p_Error = "No Product Costs";
return null;
}
dr.setQty(getQty());
// dr.setM_Locator_ID(m_receiptLine.getM_Locator_ID());
// MInOut receipt = m_receiptLine.getParent();
// dr.setLocationFromBPartner(receipt.getC_BPartner_Location_ID(), true); // from Loc
// dr.setLocationFromLocator(m_receiptLine.getM_Locator_ID(), false); // to Loc
BigDecimal temp = dr.getAcctBalance();
// Set AmtAcctCr/Dr from Receipt (sets also Project)
if (!dr.updateReverseLine (MInOut.Table_ID, // Amt updated
m_receiptLine.getM_InOut_ID(), m_receiptLine.getM_InOutLine_ID(),
multiplier))
{
p_Error = "Mat.Receipt not posted yet";
return null;
}
log.fine("CR - Amt(" + temp + "->" + dr.getAcctBalance()
+ ") - " + dr.toString());
// InventoryClearing CR
// From Invoice
MAccount expense = m_pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as);
if (m_pc.isService())
expense = m_pc.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
BigDecimal LineNetAmt = m_invoiceLine.getLineNetAmt();
multiplier = getQty()
.divide(m_invoiceLine.getQtyInvoiced(), 12, BigDecimal.ROUND_HALF_UP)
.abs();
if (multiplier.compareTo(Env.ONE) != 0)
LineNetAmt = LineNetAmt.multiply(multiplier);
if (m_pc.isService())
LineNetAmt = dr.getAcctBalance(); // book out exact receipt amt
FactLine cr = null;
if (as.isAccrual())
{
cr = fact.createLine (null, expense,
as.getC_Currency_ID(), null, LineNetAmt); // updated below
if (cr == null)
{
log.fine("Line Net Amt=0 - M_Product_ID=" + getM_Product_ID()
+ ",Qty=" + getQty() + ",InOutQty=" + m_receiptLine.getMovementQty());
facts.add(fact);
return facts;
}
cr.setQty(getQty().negate());
temp = cr.getAcctBalance();
// Set AmtAcctCr/Dr from Invoice (sets also Project)
if (as.isAccrual() && !cr.updateReverseLine (MInvoice.Table_ID, // Amt updated
m_invoiceLine.getC_Invoice_ID(), m_invoiceLine.getC_InvoiceLine_ID(), multiplier))
{
p_Error = "Invoice not posted yet";
return null;
}
log.fine("DR - Amt(" + temp + "->" + cr.getAcctBalance()
+ ") - " + cr.toString());
}
else // Cash Acct
{
MInvoice invoice = m_invoiceLine.getParent();
if (as.getC_Currency_ID() == invoice.getC_Currency_ID())
LineNetAmt = MConversionRate.convert(getCtx(), LineNetAmt,
invoice.getC_Currency_ID(), as.getC_Currency_ID(),
invoice.getDateAcct(), invoice.getC_ConversionType_ID(),
invoice.getAD_Client_ID(), invoice.getAD_Org_ID());
cr = fact.createLine (null, expense,
as.getC_Currency_ID(), null, LineNetAmt);
cr.setQty(getQty().multiply(multiplier).negate());
}
cr.setC_Activity_ID(m_invoiceLine.getC_Activity_ID());
cr.setC_Campaign_ID(m_invoiceLine.getC_Campaign_ID());
cr.setC_Project_ID(m_invoiceLine.getC_Project_ID());
cr.setC_UOM_ID(m_invoiceLine.getC_UOM_ID());
cr.setUser1_ID(m_invoiceLine.getUser1_ID());
cr.setUser2_ID(m_invoiceLine.getUser2_ID());
// Invoice Price Variance difference
BigDecimal ipv = cr.getAcctBalance().add(dr.getAcctBalance()).negate();
if (ipv.signum() != 0)
{
FactLine pv = fact.createLine(null,
m_pc.getAccount(ProductCost.ACCTTYPE_P_IPV, as),
as.getC_Currency_ID(), ipv);
pv.setC_Activity_ID(m_invoiceLine.getC_Activity_ID());
pv.setC_Campaign_ID(m_invoiceLine.getC_Campaign_ID());
pv.setC_Project_ID(m_invoiceLine.getC_Project_ID());
pv.setC_UOM_ID(m_invoiceLine.getC_UOM_ID());
pv.setUser1_ID(m_invoiceLine.getUser1_ID());
pv.setUser2_ID(m_invoiceLine.getUser2_ID());
}
log.fine("IPV=" + ipv + "; Balance=" + fact.getSourceBalance());
// Cost Detail Record - data from Expense/IncClearing (CR) record
MCostDetail.createInvoice(as, getAD_Org_ID(),
getM_Product_ID(), matchInv.getM_AttributeSetInstance_ID(),
m_invoiceLine.getC_InvoiceLine_ID(), 0, // No cost element
cr.getAcctBalance().negate(), getQty(), // correcting
getDescription(), getTrxName());
// Update Costing
updateProductInfo(as.getC_AcctSchema_ID(),
MAcctSchema.COSTINGMETHOD_StandardCosting.equals(as.getCostingMethod()));
//
facts.add(fact);
/** Commitment release ****/
if (as.isAccrual() && as.isCreateCommitment())
{
fact = Doc_Order.getCommitmentRelease(as, this,
getQty(), m_invoiceLine.getC_InvoiceLine_ID(), Env.ONE);
if (fact == null)
return null;
facts.add(fact);
} // Commitment
return facts;
} // createFact
/**
* Update Product Info (old).
* - Costing (CostStandardCumQty, CostStandardCumAmt, CostAverageCumQty, CostAverageCumAmt)
* @param C_AcctSchema_ID accounting schema
* @param standardCosting true if std costing
* @return true if updated
* @deprecated old costing
*/
private boolean updateProductInfo (int C_AcctSchema_ID, boolean standardCosting)
{
log.fine("M_MatchInv_ID=" + get_ID());
// update Product Costing Qty/Amt
// requires existence of currency conversion !!
StringBuffer sql = new StringBuffer (
"UPDATE M_Product_Costing pc "
+ "SET (CostStandardCumQty,CostStandardCumAmt, CostAverageCumQty,CostAverageCumAmt) = "
+ "(SELECT pc.CostStandardCumQty + m.Qty,"
+ "pc.CostStandardCumAmt + currencyConvert(il.PriceActual,i.C_Currency_ID,a.C_Currency_ID,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID)*m.Qty, "
+ "pc.CostAverageCumQty + m.Qty,"
+ "pc.CostAverageCumAmt + currencyConvert(il.PriceActual,i.C_Currency_ID,a.C_Currency_ID,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID)*m.Qty "
+ "FROM M_MatchInv m"
+ " INNER JOIN C_InvoiceLine il ON (m.C_InvoiceLine_ID=il.C_InvoiceLine_ID)"
+ " INNER JOIN C_Invoice i ON (il.C_Invoice_ID=i.C_Invoice_ID),"
+ " C_AcctSchema a "
+ "WHERE pc.C_AcctSchema_ID=a.C_AcctSchema_ID"
+ " AND pc.M_Product_ID=m.M_Product_ID"
+ " AND m.M_MatchInv_ID=").append(get_ID()).append(")"
//
+ "WHERE pc.C_AcctSchema_ID=").append(C_AcctSchema_ID).append(
" AND EXISTS (SELECT * FROM M_MatchInv m "
+ "WHERE pc.M_Product_ID=m.M_Product_ID"
+ " AND m.M_MatchInv_ID=").append(get_ID()).append(")");
int no = DB.executeUpdate(sql.toString(), getTrxName());
log.fine("M_Product_Costing - Qty/Amt Updated #=" + no);
// Update Average Cost
sql = new StringBuffer (
"UPDATE M_Product_Costing "
+ "SET CostAverage = CostAverageCumAmt/DECODE(CostAverageCumQty, 0,1, CostAverageCumQty) "
+ "WHERE C_AcctSchema_ID=").append(C_AcctSchema_ID)
.append(" AND M_Product_ID=").append(getM_Product_ID());
no = DB.executeUpdate(sql.toString(), getTrxName());
log.fine("M_Product_Costing - AvgCost Updated #=" + no);
// Update Current Cost
if (!standardCosting)
{
sql = new StringBuffer (
"UPDATE M_Product_Costing "
+ "SET CurrentCostPrice = CostAverage "
+ "WHERE C_AcctSchema_ID=").append(C_AcctSchema_ID)
.append(" AND M_Product_ID=").append(getM_Product_ID());
no = DB.executeUpdate(sql.toString(), getTrxName());
log.fine("M_Product_Costing - CurrentCost Updated=" + no);
}
return true;
} // updateProductInfo
} // Doc_MatchInv

View File

@ -0,0 +1,243 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.acct;
import java.math.*;
import java.sql.*;
import java.util.*;
import java.util.logging.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Post MatchPO Documents.
* <pre>
* Table: C_MatchPO (473)
* Document Types: MXP
* </pre>
* @author Jorg Janke
* @version $Id: Doc_MatchPO.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class Doc_MatchPO extends Doc
{
/**
* Constructor
* @param ass accounting schemata
* @param rs record
* @param trxName trx
*/
protected Doc_MatchPO (MAcctSchema[] ass, ResultSet rs, String trxName)
{
super(ass, MMatchPO.class, rs, DOCTYPE_MatMatchPO, trxName);
} // Doc_MatchPO
private int m_C_OrderLine_ID = 0;
private MOrderLine m_oLine = null;
//
private int m_M_InOutLine_ID = 0;
private int m_C_InvoiceLine_ID = 0;
private ProductCost m_pc;
private int m_M_AttributeSetInstance_ID = 0;
/**
* Load Specific Document Details
* @return error message or null
*/
protected String loadDocumentDetails ()
{
setC_Currency_ID (Doc.NO_CURRENCY);
MMatchPO matchPO = (MMatchPO)getPO();
setDateDoc(matchPO.getDateTrx());
//
m_M_AttributeSetInstance_ID = matchPO.getM_AttributeSetInstance_ID();
setQty (matchPO.getQty());
//
m_C_OrderLine_ID = matchPO.getC_OrderLine_ID();
m_oLine = new MOrderLine (getCtx(), m_C_OrderLine_ID, getTrxName());
//
m_M_InOutLine_ID = matchPO.getM_InOutLine_ID();
m_C_InvoiceLine_ID = matchPO.getC_InvoiceLine_ID();
//
m_pc = new ProductCost (Env.getCtx(),
getM_Product_ID(), m_M_AttributeSetInstance_ID, getTrxName());
m_pc.setQty(getQty());
return null;
} // loadDocumentDetails
/**************************************************************************
* Get Source Currency Balance - subtracts line and tax amounts from total - no rounding
* @return Zero - always balanced
*/
public BigDecimal getBalance()
{
return Env.ZERO;
} // getBalance
/**
* Create Facts (the accounting logic) for
* MXP.
* <pre>
* Product PPV <difference>
* PPV_Offset <difference>
* </pre>
* @param as accounting schema
* @return Fact
*/
public ArrayList<Fact> createFacts (MAcctSchema as)
{
ArrayList<Fact> facts = new ArrayList<Fact>();
//
if (getM_Product_ID() == 0 // Nothing to do if no Product
|| getQty().signum() == 0
|| m_M_InOutLine_ID == 0) // No posting if not matched to Shipment
{
log.fine("No Product/Qty - M_Product_ID=" + getM_Product_ID()
+ ",Qty=" + getQty());
return facts;
}
// create Fact Header
Fact fact = new Fact(this, as, Fact.POST_Actual);
setC_Currency_ID(as.getC_Currency_ID());
// Purchase Order Line
BigDecimal poCost = m_oLine.getPriceCost();
if (poCost == null || poCost.signum() == 0)
poCost = m_oLine.getPriceActual();
poCost = poCost.multiply(getQty()); // Delivered so far
// Different currency
if (m_oLine.getC_Currency_ID() != as.getC_Currency_ID())
{
MOrder order = m_oLine.getParent();
BigDecimal rate = MConversionRate.getRate(
order.getC_Currency_ID(), as.getC_Currency_ID(),
order.getDateAcct(), order.getC_ConversionType_ID(),
m_oLine.getAD_Client_ID(), m_oLine.getAD_Org_ID());
if (rate == null)
{
p_Error = "Purchase Order not convertible - " + as.getName();
return null;
}
poCost = poCost.multiply(rate);
if (poCost.scale() > as.getCostingPrecision())
poCost = poCost.setScale(as.getCostingPrecision(), BigDecimal.ROUND_HALF_UP);
}
// Create PO Cost Detail Record firs
MCostDetail.createOrder(as, m_oLine.getAD_Org_ID(),
getM_Product_ID(), m_M_AttributeSetInstance_ID,
m_C_OrderLine_ID, 0, // no cost element
poCost, getQty(), // Delivered
m_oLine.getDescription(), getTrxName());
// Current Costs
String costingMethod = as.getCostingMethod();
MProduct product = MProduct.get(getCtx(), getM_Product_ID());
MProductCategoryAcct pca = MProductCategoryAcct.get(getCtx(),
product.getM_Product_Category_ID(), as.getC_AcctSchema_ID(), getTrxName());
if (pca.getCostingMethod() != null)
costingMethod = pca.getCostingMethod();
BigDecimal costs = m_pc.getProductCosts(as, getAD_Org_ID(),
costingMethod, m_C_OrderLine_ID, false); // non-zero costs
// No Costs yet - no PPV
if (costs == null || costs.signum() == 0)
{
p_Error = "Resubmit - No Costs for " + product.getName();
log.log(Level.SEVERE, p_Error);
return null;
}
// Difference
BigDecimal difference = poCost.subtract(costs);
// Nothing to post
if (difference.signum() == 0)
{
log.log(Level.FINE, "No Cost Difference for M_Product_ID=" + getM_Product_ID());
facts.add(fact);
return facts;
}
// Product PPV
FactLine cr = fact.createLine(null,
m_pc.getAccount(ProductCost.ACCTTYPE_P_PPV, as),
as.getC_Currency_ID(), difference);
if (cr != null)
{
cr.setQty(getQty());
cr.setC_BPartner_ID(m_oLine.getC_BPartner_ID());
cr.setC_Activity_ID(m_oLine.getC_Activity_ID());
cr.setC_Campaign_ID(m_oLine.getC_Campaign_ID());
cr.setC_Project_ID(m_oLine.getC_Project_ID());
cr.setC_UOM_ID(m_oLine.getC_UOM_ID());
cr.setUser1_ID(m_oLine.getUser1_ID());
cr.setUser2_ID(m_oLine.getUser2_ID());
}
// PPV Offset
FactLine dr = fact.createLine(null,
getAccount(Doc.ACCTTYPE_PPVOffset, as),
as.getC_Currency_ID(), difference.negate());
if (dr != null)
{
dr.setQty(getQty().negate());
dr.setC_BPartner_ID(m_oLine.getC_BPartner_ID());
dr.setC_Activity_ID(m_oLine.getC_Activity_ID());
dr.setC_Campaign_ID(m_oLine.getC_Campaign_ID());
dr.setC_Project_ID(m_oLine.getC_Project_ID());
dr.setC_UOM_ID(m_oLine.getC_UOM_ID());
dr.setUser1_ID(m_oLine.getUser1_ID());
dr.setUser2_ID(m_oLine.getUser2_ID());
}
//
facts.add(fact);
return facts;
} // createFact
/**
* Update Product Info (old).
* - Costing (CostStandardPOQty, CostStandardPOAmt)
* @param C_AcctSchema_ID accounting schema
* @deprecated old costing
*/
private void updateProductInfo (int C_AcctSchema_ID)
{
log.fine("M_MatchPO_ID=" + get_ID());
// update Product Costing
// requires existence of currency conversion !!
StringBuffer sql = new StringBuffer (
"UPDATE M_Product_Costing pc "
+ "SET (CostStandardPOQty,CostStandardPOAmt) = "
+ "(SELECT CostStandardPOQty + m.Qty,"
+ " CostStandardPOAmt + currencyConvert(ol.PriceActual,ol.C_Currency_ID,a.C_Currency_ID,ol.DateOrdered,null,ol.AD_Client_ID,ol.AD_Org_ID)*m.Qty "
+ "FROM M_MatchPO m, C_OrderLine ol, C_AcctSchema a "
+ "WHERE m.C_OrderLine_ID=ol.C_OrderLine_ID"
+ " AND pc.M_Product_ID=ol.M_Product_ID"
+ " AND pc.C_AcctSchema_ID=a.C_AcctSchema_ID"
+ "AND m.M_MatchPO_ID=").append(get_ID()).append(") ")
.append("WHERE pc.C_AcctSchema_ID=").append(C_AcctSchema_ID)
.append(" AND pc.M_Product_ID=").append(getM_Product_ID());
int no = DB.executeUpdate(sql.toString(), getTrxName());
log.fine("M_Product_Costing - Updated=" + no);
} // updateProductInfo
} // Doc_MatchPO

View File

@ -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.acct;
import java.math.*;
import java.sql.*;
import java.util.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Post Invoice Documents.
* <pre>
* Table: M_Movement (323)
* Document Types: MMM
* </pre>
* @author Jorg Janke
* @version $Id: Doc_Movement.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class Doc_Movement extends Doc
{
/**
* Constructor
* @param ass accounting schemata
* @param rs record
* @param trxName trx
*/
public Doc_Movement (MAcctSchema[] ass, ResultSet rs, String trxName)
{
super (ass, MMovement.class, rs, DOCTYPE_MatMovement, trxName);
} // Doc_Movement
/**
* Load Document Details
* @return error message or null
*/
protected String loadDocumentDetails()
{
setC_Currency_ID(NO_CURRENCY);
MMovement move = (MMovement)getPO();
setDateDoc (move.getMovementDate());
setDateAcct(move.getMovementDate());
// Contained Objects
p_lines = loadLines(move);
log.fine("Lines=" + p_lines.length);
return null;
} // loadDocumentDetails
/**
* Load Invoice Line
* @param move move
* @return document lines (DocLine_Material)
*/
private DocLine[] loadLines(MMovement move)
{
ArrayList<DocLine> list = new ArrayList<DocLine>();
MMovementLine[] lines = move.getLines(false);
for (int i = 0; i < lines.length; i++)
{
MMovementLine line = lines[i];
DocLine docLine = new DocLine (line, this);
docLine.setQty(line.getMovementQty(), false);
//
log.fine(docLine.toString());
list.add (docLine);
}
// Return Array
DocLine[] dls = new DocLine[list.size()];
list.toArray(dls);
return dls;
} // loadLines
/**
* Get Balance
* @return balance (ZERO) - always balanced
*/
public BigDecimal getBalance()
{
BigDecimal retValue = Env.ZERO;
return retValue;
} // getBalance
/**
* Create Facts (the accounting logic) for
* MMM.
* <pre>
* Movement
* Inventory DR CR
* InventoryTo DR CR
* </pre>
* @param as account schema
* @return Fact
*/
public ArrayList<Fact> createFacts (MAcctSchema as)
{
// create Fact Header
Fact fact = new Fact(this, as, Fact.POST_Actual);
setC_Currency_ID(as.getC_Currency_ID());
// Line pointers
FactLine dr = null;
FactLine cr = null;
for (int i = 0; i < p_lines.length; i++)
{
DocLine line = p_lines[i];
BigDecimal costs = line.getProductCosts(as, line.getAD_Org_ID(), false);
// ** Inventory DR CR
dr = fact.createLine(line,
line.getAccount(ProductCost.ACCTTYPE_P_Asset, as),
as.getC_Currency_ID(), costs.negate()); // from (-) CR
if (dr == null)
continue;
dr.setM_Locator_ID(line.getM_Locator_ID());
dr.setQty(line.getQty().negate()); // outgoing
// ** InventoryTo DR CR
cr = fact.createLine(line,
line.getAccount(ProductCost.ACCTTYPE_P_Asset, as),
as.getC_Currency_ID(), costs); // to (+) DR
if (cr == null)
continue;
cr.setM_Locator_ID(line.getM_LocatorTo_ID());
cr.setQty(line.getQty());
// Only for between-org movements
if (dr.getAD_Org_ID() != cr.getAD_Org_ID())
{
String costingLevel = as.getCostingLevel();
MProductCategoryAcct pca = MProductCategoryAcct.get(getCtx(),
line.getProduct().getM_Product_Category_ID(),
as.getC_AcctSchema_ID(), getTrxName());
if (pca.getCostingLevel() != null)
costingLevel = pca.getCostingLevel();
if (!MAcctSchema.COSTINGLEVEL_Organization.equals(costingLevel))
continue;
//
String description = line.getDescription();
if (description == null)
description = "";
// Cost Detail From
MCostDetail.createMovement(as, dr.getAD_Org_ID(), // locator org
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
line.get_ID(), 0,
costs.negate(), line.getQty().negate(), true,
description + "(|->)", getTrxName());
// Cost Detail To
MCostDetail.createMovement(as, cr.getAD_Org_ID(), // locator org
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
line.get_ID(), 0,
costs, line.getQty(), false,
description + "(|<-)", getTrxName());
}
}
//
ArrayList<Fact> facts = new ArrayList<Fact>();
facts.add(fact);
return facts;
} // createFact
} // Doc_Movement

View File

@ -0,0 +1,624 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.acct;
import java.math.*;
import java.sql.*;
import java.util.*;
import java.util.logging.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Post Order Documents.
* <pre>
* Table: C_Order (259)
* Document Types: SOO, POO
* </pre>
* @author Jorg Janke
* @version $Id: Doc_Order.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class Doc_Order extends Doc
{
/**
* Constructor
* @param ass accounting schemata
* @param rs record
* @param trxName trx
*/
protected Doc_Order (MAcctSchema[] ass, ResultSet rs, String trxName)
{
super (ass, MOrder.class, rs, null, trxName);
} // Doc_Order
/** Contained Optional Tax Lines */
private DocTax[] m_taxes = null;
/** Requisitions */
private DocLine[] m_requisitions = null;
/** Order Currency Precision */
private int m_precision = -1;
/**
* Load Specific Document Details
* @return error message or null
*/
protected String loadDocumentDetails ()
{
MOrder order = (MOrder)getPO();
setDateDoc(order.getDateOrdered());
setIsTaxIncluded(order.isTaxIncluded());
// Amounts
setAmount(AMTTYPE_Gross, order.getGrandTotal());
setAmount(AMTTYPE_Net, order.getTotalLines());
setAmount(AMTTYPE_Charge, order.getChargeAmt());
// Contained Objects
m_taxes = loadTaxes();
p_lines = loadLines(order);
// log.fine( "Lines=" + p_lines.length + ", Taxes=" + m_taxes.length);
return null;
} // loadDocumentDetails
/**
* Load Invoice Line
* @param order order
* @return DocLine Array
*/
private DocLine[] loadLines(MOrder order)
{
ArrayList<DocLine> list = new ArrayList<DocLine>();
MOrderLine[] lines = order.getLines();
for (int i = 0; i < lines.length; i++)
{
MOrderLine line = lines[i];
DocLine docLine = new DocLine (line, this);
BigDecimal Qty = line.getQtyOrdered();
docLine.setQty(Qty, order.isSOTrx());
//
BigDecimal PriceActual = line.getPriceActual();
BigDecimal PriceCost = null;
if (getDocumentType().equals(DOCTYPE_POrder)) // PO
PriceCost = line.getPriceCost();
BigDecimal LineNetAmt = null;
if (PriceCost != null && PriceCost.signum() != 0)
LineNetAmt = Qty.multiply(PriceCost);
else
LineNetAmt = line.getLineNetAmt();
docLine.setAmount (LineNetAmt); // DR
BigDecimal PriceList = line.getPriceList();
int C_Tax_ID = docLine.getC_Tax_ID();
// Correct included Tax
if (isTaxIncluded() && C_Tax_ID != 0)
{
MTax tax = MTax.get(getCtx(), C_Tax_ID);
if (!tax.isZeroTax())
{
BigDecimal LineNetAmtTax = tax.calculateTax(LineNetAmt, true, getStdPrecision());
log.fine("LineNetAmt=" + LineNetAmt + " - Tax=" + LineNetAmtTax);
LineNetAmt = LineNetAmt.subtract(LineNetAmtTax);
for (int t = 0; t < m_taxes.length; t++)
{
if (m_taxes[t].getC_Tax_ID() == C_Tax_ID)
{
m_taxes[t].addIncludedTax(LineNetAmtTax);
break;
}
}
BigDecimal PriceListTax = tax.calculateTax(PriceList, true, getStdPrecision());
PriceList = PriceList.subtract(PriceListTax);
}
} // correct included Tax
docLine.setAmount (LineNetAmt, PriceList, Qty);
list.add(docLine);
}
// Return Array
DocLine[] dl = new DocLine[list.size()];
list.toArray(dl);
return dl;
} // loadLines
/**
* Load Requisitions
* @return requisition lines of Order
*/
private DocLine[] loadRequisitions ()
{
MOrder order = (MOrder)getPO();
MOrderLine[] oLines = order.getLines();
HashMap<Integer,BigDecimal> qtys = new HashMap<Integer,BigDecimal>();
for (int i = 0; i < oLines.length; i++)
{
MOrderLine line = oLines[i];
qtys.put(new Integer(line.getC_OrderLine_ID()), line.getQtyOrdered());
}
//
ArrayList<DocLine> list = new ArrayList<DocLine>();
String sql = "SELECT * FROM M_RequisitionLine rl "
+ "WHERE EXISTS (SELECT * FROM C_Order o "
+ " INNER JOIN C_OrderLine ol ON (o.C_Order_ID=ol.C_Order_ID) "
+ "WHERE ol.C_OrderLine_ID=rl.C_OrderLine_ID"
+ " AND o.C_Order_ID=?) "
+ "ORDER BY rl.C_OrderLine_ID";
PreparedStatement pstmt = null;
try
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setInt (1, order.getC_Order_ID());
ResultSet rs = pstmt.executeQuery ();
while (rs.next ())
{
MRequisitionLine line = new MRequisitionLine (getCtx(), rs, null);
DocLine docLine = new DocLine (line, this);
// Quantity - not more then OrderLine
// Issue: Split of Requisition to multiple POs & different price
Integer key = new Integer(line.getC_OrderLine_ID());
BigDecimal maxQty = qtys.get(key);
BigDecimal Qty = line.getQty().max(maxQty);
if (Qty.signum() == 0)
continue;
docLine.setQty (Qty, false);
qtys.put(key, maxQty.subtract(Qty));
//
BigDecimal PriceActual = line.getPriceActual();
BigDecimal LineNetAmt = line.getLineNetAmt();
if (line.getQty().compareTo(Qty) != 0)
LineNetAmt = PriceActual.multiply(Qty);
docLine.setAmount (LineNetAmt); // DR
list.add (docLine);
}
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 Array
DocLine[] dls = new DocLine[list.size ()];
list.toArray (dls);
return dls;
} // loadRequisitions
/**
* Get Currency Precision
* @return precision
*/
private int getStdPrecision()
{
if (m_precision == -1)
m_precision = MCurrency.getStdPrecision(getCtx(), getC_Currency_ID());
return m_precision;
} // getPrecision
/**
* Load Invoice Taxes
* @return DocTax Array
*/
private DocTax[] loadTaxes()
{
ArrayList<DocTax> list = new ArrayList<DocTax>();
String sql = "SELECT it.C_Tax_ID, t.Name, t.Rate, it.TaxBaseAmt, it.TaxAmt, t.IsSalesTax "
+ "FROM C_Tax t, C_OrderTax it "
+ "WHERE t.C_Tax_ID=it.C_Tax_ID AND it.C_Order_ID=?";
try
{
PreparedStatement pstmt = DB.prepareStatement(sql, getTrxName());
pstmt.setInt(1, get_ID());
ResultSet rs = pstmt.executeQuery();
//
while (rs.next())
{
int C_Tax_ID = rs.getInt(1);
String name = rs.getString(2);
BigDecimal rate = rs.getBigDecimal(3);
BigDecimal taxBaseAmt = rs.getBigDecimal(4);
BigDecimal amount = rs.getBigDecimal(5);
boolean salesTax = "Y".equals(rs.getString(6));
//
DocTax taxLine = new DocTax(C_Tax_ID, name, rate,
taxBaseAmt, amount, salesTax);
list.add(taxLine);
}
//
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, sql, e);
}
// Return Array
DocTax[] tl = new DocTax[list.size()];
list.toArray(tl);
return tl;
} // loadTaxes
/**************************************************************************
* Get Source Currency Balance - subtracts line and tax amounts from total - no rounding
* @return positive amount, if total invoice is bigger than lines
*/
public BigDecimal getBalance()
{
BigDecimal retValue = new BigDecimal(0.0);
StringBuffer sb = new StringBuffer (" [");
// Total
retValue = retValue.add(getAmount(Doc.AMTTYPE_Gross));
sb.append(getAmount(Doc.AMTTYPE_Gross));
// - Header Charge
retValue = retValue.subtract(getAmount(Doc.AMTTYPE_Charge));
sb.append("-").append(getAmount(Doc.AMTTYPE_Charge));
// - Tax
if (m_taxes != null)
{
for (int i = 0; i < m_taxes.length; i++)
{
retValue = retValue.subtract(m_taxes[i].getAmount());
sb.append("-").append(m_taxes[i].getAmount());
}
}
// - Lines
if (p_lines != null)
{
for (int i = 0; i < p_lines.length; i++)
{
retValue = retValue.subtract(p_lines[i].getAmtSource());
sb.append("-").append(p_lines[i].getAmtSource());
}
sb.append("]");
}
//
if (retValue.signum() != 0 // Sum of Cost(vs. Price) in lines may not add up
&& getDocumentType().equals(DOCTYPE_POrder)) // PO
{
log.fine(toString() + " Balance=" + retValue + sb.toString() + " (ignored)");
retValue = Env.ZERO;
}
else
log.fine(toString() + " Balance=" + retValue + sb.toString());
return retValue;
} // getBalance
/*************************************************************************
* Create Facts (the accounting logic) for
* SOO, POO.
* <pre>
* Reservation (release)
* Expense DR
* Offset CR
* Commitment
* (to be released by Invoice Matching)
* Expense CR
* Offset DR
* </pre>
* @param as accounting schema
* @return Fact
*/
public ArrayList<Fact> createFacts (MAcctSchema as)
{
ArrayList<Fact> facts = new ArrayList<Fact>();
// Purchase Order
if (getDocumentType().equals(DOCTYPE_POrder))
{
updateProductPO(as);
updateProductInfo(as.getC_AcctSchema_ID());
BigDecimal grossAmt = getAmount(Doc.AMTTYPE_Gross);
// Commitment
if (as.isCreateCommitment())
{
Fact fact = new Fact(this, as, Fact.POST_Commitment);
BigDecimal total = Env.ZERO;
for (int i = 0; i < p_lines.length; i++)
{
DocLine line = p_lines[i];
BigDecimal cost = line.getAmtSource();
total = total.add(cost);
// Account
MAccount expense = line.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
FactLine fl = fact.createLine (line, expense,
getC_Currency_ID(), cost, null);
}
// Offset
MAccount offset = getAccount(ACCTTYPE_CommitmentOffset, as);
if (offset == null)
{
p_Error = "@NotFound@ @CommitmentOffset_Acct@";
log.log(Level.SEVERE, p_Error);
return null;
}
fact.createLine (null, offset,
getC_Currency_ID(), null, total);
//
facts.add(fact);
}
// Reverse Reservation
if (as.isCreateReservation())
{
Fact fact = new Fact(this, as, Fact.POST_Reservation);
BigDecimal total = Env.ZERO;
if (m_requisitions == null)
m_requisitions = loadRequisitions();
for (int i = 0; i < m_requisitions.length; i++)
{
DocLine line = m_requisitions[i];
BigDecimal cost = line.getAmtSource();
total = total.add(cost);
// Account
MAccount expense = line.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
FactLine fl = fact.createLine (line, expense,
getC_Currency_ID(), null, cost);
}
// Offset
MAccount offset = getAccount(ACCTTYPE_CommitmentOffset, as);
if (offset == null)
{
p_Error = "@NotFound@ @CommitmentOffset_Acct@";
log.log(Level.SEVERE, p_Error);
return null;
}
fact.createLine (null, offset,
getC_Currency_ID(), total, null);
//
facts.add(fact);
} // reservations
}
// SO
return facts;
} // createFact
/**
* Update ProductPO PriceLastPO
* @param as accounting schema
*/
private void updateProductPO(MAcctSchema as)
{
MClientInfo ci = MClientInfo.get(getCtx(), as.getAD_Client_ID());
if (ci.getC_AcctSchema1_ID() != as.getC_AcctSchema_ID())
return;
StringBuffer sql = new StringBuffer (
"UPDATE M_Product_PO po "
+ "SET PriceLastPO = (SELECT currencyConvert(ol.PriceActual,ol.C_Currency_ID,po.C_Currency_ID,o.DateOrdered,o.C_ConversionType_ID,o.AD_Client_ID,o.AD_Org_ID) "
+ "FROM C_Order o, C_OrderLine ol "
+ "WHERE o.C_Order_ID=ol.C_Order_ID"
+ " AND po.M_Product_ID=ol.M_Product_ID AND po.C_BPartner_ID=o.C_BPartner_ID"
+ " AND ROWNUM=1 AND o.C_Order_ID=").append(get_ID()).append(") ")
.append("WHERE EXISTS (SELECT * "
+ "FROM C_Order o, C_OrderLine ol "
+ "WHERE o.C_Order_ID=ol.C_Order_ID"
+ " AND po.M_Product_ID=ol.M_Product_ID AND po.C_BPartner_ID=o.C_BPartner_ID"
+ " AND o.C_Order_ID=").append(get_ID()).append(")");
int no = DB.executeUpdate(sql.toString(), getTrxName());
log.fine("Updated=" + no);
} // updateProductPO
/**
* Get Commitments
* @param doc document
* @param maxQty Qty invoiced/matched
* @param C_InvoiceLine_ID invoice line
* @return commitments (order lines)
*/
protected static DocLine[] getCommitments(Doc doc, BigDecimal maxQty, int C_InvoiceLine_ID)
{
int precision = -1;
//
ArrayList<DocLine> list = new ArrayList<DocLine>();
String sql = "SELECT * FROM C_OrderLine ol "
+ "WHERE EXISTS "
+ "(SELECT * FROM C_InvoiceLine il "
+ "WHERE il.C_OrderLine_ID=ol.C_OrderLine_ID"
+ " AND il.C_InvoiceLine_ID=?)"
+ " OR EXISTS "
+ "(SELECT * FROM M_MatchPO po "
+ "WHERE po.C_OrderLine_ID=ol.C_OrderLine_ID"
+ " AND po.C_InvoiceLine_ID=?)";
PreparedStatement pstmt = null;
try
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setInt (1, C_InvoiceLine_ID);
pstmt.setInt (2, C_InvoiceLine_ID);
ResultSet rs = pstmt.executeQuery ();
while (rs.next ())
{
if (maxQty.signum() == 0)
continue;
MOrderLine line = new MOrderLine (doc.getCtx(), rs, null);
DocLine docLine = new DocLine (line, doc);
// Currency
if (precision == -1)
{
doc.setC_Currency_ID(docLine.getC_Currency_ID());
precision = MCurrency.getStdPrecision(doc.getCtx(), docLine.getC_Currency_ID());
}
// Qty
BigDecimal Qty = line.getQtyOrdered().max(maxQty);
docLine.setQty(Qty, false);
//
BigDecimal PriceActual = line.getPriceActual();
BigDecimal PriceCost = line.getPriceCost();
BigDecimal LineNetAmt = null;
if (PriceCost != null && PriceCost.signum() != 0)
LineNetAmt = Qty.multiply(PriceCost);
else if (Qty.equals(maxQty))
LineNetAmt = line.getLineNetAmt();
else
LineNetAmt = Qty.multiply(PriceActual);
maxQty = maxQty.subtract(Qty);
docLine.setAmount (LineNetAmt); // DR
BigDecimal PriceList = line.getPriceList();
int C_Tax_ID = docLine.getC_Tax_ID();
// Correct included Tax
if (C_Tax_ID != 0 && line.getParent().isTaxIncluded())
{
MTax tax = MTax.get(doc.getCtx(), C_Tax_ID);
if (!tax.isZeroTax())
{
BigDecimal LineNetAmtTax = tax.calculateTax(LineNetAmt, true, precision);
s_log.fine("LineNetAmt=" + LineNetAmt + " - Tax=" + LineNetAmtTax);
LineNetAmt = LineNetAmt.subtract(LineNetAmtTax);
BigDecimal PriceListTax = tax.calculateTax(PriceList, true, precision);
PriceList = PriceList.subtract(PriceListTax);
}
} // correct included Tax
docLine.setAmount (LineNetAmt, PriceList, Qty);
list.add(docLine);
}
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 Array
DocLine[] dl = new DocLine[list.size()];
list.toArray(dl);
return dl;
} // getCommitments
/**
* Get Commitment Release.
* Called from MatchInv for accrual and Allocation for Cash Based
* @param as accounting schema
* @param doc doc
* @param Qty qty invoiced/matched
* @param C_InvoiceLine_ID line
* @param multiplier 1 for accrual
* @return Fact
*/
protected static Fact getCommitmentRelease(MAcctSchema as, Doc doc,
BigDecimal Qty, int C_InvoiceLine_ID, BigDecimal multiplier)
{
Fact fact = new Fact(doc, as, Fact.POST_Commitment);
DocLine[] commitments = Doc_Order.getCommitments(doc, Qty,
C_InvoiceLine_ID);
BigDecimal total = Env.ZERO;
int C_Currency_ID = -1;
for (int i = 0; i < commitments.length; i++)
{
DocLine line = commitments[i];
if (C_Currency_ID == -1)
C_Currency_ID = line.getC_Currency_ID();
else if (C_Currency_ID != line.getC_Currency_ID())
{
doc.p_Error = "Different Currencies of Order Lines";
s_log.log(Level.SEVERE, doc.p_Error);
return null;
}
BigDecimal cost = line.getAmtSource().multiply(multiplier);
total = total.add(cost);
// Account
MAccount expense = line.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
FactLine fl = fact.createLine (line, expense,
C_Currency_ID, null, cost);
}
// Offset
MAccount offset = doc.getAccount(ACCTTYPE_CommitmentOffset, as);
if (offset == null)
{
doc.p_Error = "@NotFound@ @CommitmentOffset_Acct@";
s_log.log(Level.SEVERE, doc.p_Error);
return null;
}
fact.createLine (null, offset,
C_Currency_ID, total, null);
return fact;
} // getCommitmentRelease
/**************************************************************************
* Update Product Info (old)
* - Costing (PriceLastPO)
* - PO (PriceLastPO)
* @param C_AcctSchema_ID accounting schema
* @deprecated old costing
*/
private void updateProductInfo (int C_AcctSchema_ID)
{
log.fine("C_Order_ID=" + get_ID());
/** @todo Last.. would need to compare document/last updated date
* would need to maintain LastPriceUpdateDate on _PO and _Costing */
// update Product Costing
// requires existence of currency conversion !!
// if there are multiple lines of the same product last price uses first
StringBuffer sql = new StringBuffer (
"UPDATE M_Product_Costing pc "
+ "SET PriceLastPO = "
+ "(SELECT currencyConvert(ol.PriceActual,ol.C_Currency_ID,a.C_Currency_ID,o.DateOrdered,o.C_ConversionType_ID,o.AD_Client_ID,o.AD_Org_ID) "
+ "FROM C_Order o, C_OrderLine ol, C_AcctSchema a "
+ "WHERE o.C_Order_ID=ol.C_Order_ID"
+ " AND pc.M_Product_ID=ol.M_Product_ID AND pc.C_AcctSchema_ID=a.C_AcctSchema_ID"
+ " AND ROWNUM=1"
+ " AND pc.C_AcctSchema_ID=").append(C_AcctSchema_ID).append(" AND o.C_Order_ID=")
.append(get_ID()).append(") ")
.append("WHERE EXISTS (SELECT * "
+ "FROM C_Order o, C_OrderLine ol, C_AcctSchema a "
+ "WHERE o.C_Order_ID=ol.C_Order_ID"
+ " AND pc.M_Product_ID=ol.M_Product_ID AND pc.C_AcctSchema_ID=a.C_AcctSchema_ID"
+ " AND pc.C_AcctSchema_ID=").append(C_AcctSchema_ID).append(" AND o.C_Order_ID=")
.append(get_ID()).append(")");
int no = DB.executeUpdate(sql.toString(), getTrxName());
log.fine("M_Product_Costing - Updated=" + no);
} // updateProductInfo
} // Doc_Order

View File

@ -0,0 +1,183 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.acct;
import java.math.*;
import java.sql.*;
import java.util.*;
import java.util.logging.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Post Invoice Documents.
* <pre>
* Table: C_Payment (335)
* Document Types ARP, APP
* </pre>
* @author Jorg Janke
* @version $Id: Doc_Payment.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class Doc_Payment extends Doc
{
/**
* Constructor
* @param ass accounting schemata
* @param rs record
* @param trxName trx
*/
protected Doc_Payment (MAcctSchema[] ass, ResultSet rs, String trxName)
{
super (ass, MPayment.class, rs, null, trxName);
} // Doc_Payment
/** Tender Type */
private String m_TenderType = null;
/** Prepayment */
private boolean m_Prepayment = false;
/** Bank Account */
private int m_C_BankAccount_ID = 0;
/**
* Load Specific Document Details
* @return error message or null
*/
protected String loadDocumentDetails ()
{
MPayment pay = (MPayment)getPO();
setDateDoc(pay.getDateTrx());
m_TenderType = pay.getTenderType();
m_Prepayment = pay.isPrepayment();
m_C_BankAccount_ID = pay.getC_BankAccount_ID();
// Amount
setAmount(Doc.AMTTYPE_Gross, pay.getPayAmt());
return null;
} // loadDocumentDetails
/**************************************************************************
* Get Source Currency Balance - always zero
* @return Zero (always balanced)
*/
public BigDecimal getBalance()
{
BigDecimal retValue = Env.ZERO;
// log.config( toString() + " Balance=" + retValue);
return retValue;
} // getBalance
/**
* Create Facts (the accounting logic) for
* ARP, APP.
* <pre>
* ARP
* BankInTransit DR
* UnallocatedCash CR
* or Charge/C_Prepayment
* APP
* PaymentSelect DR
* or Charge/V_Prepayment
* BankInTransit CR
* CashBankTransfer
* -
* </pre>
* @param as accounting schema
* @return Fact
*/
public ArrayList<Fact> createFacts (MAcctSchema as)
{
// create Fact Header
Fact fact = new Fact(this, as, Fact.POST_Actual);
// Cash Transfer
if ("X".equals(m_TenderType))
{
ArrayList<Fact> facts = new ArrayList<Fact>();
facts.add(fact);
return facts;
}
int AD_Org_ID = getBank_Org_ID(); // Bank Account Org
if (getDocumentType().equals(DOCTYPE_ARReceipt))
{
// Asset
FactLine fl = fact.createLine(null, getAccount(Doc.ACCTTYPE_BankInTransit, as),
getC_Currency_ID(), getAmount(), null);
if (fl != null && AD_Org_ID != 0)
fl.setAD_Org_ID(AD_Org_ID);
//
MAccount acct = null;
if (getC_Charge_ID() != 0)
acct = MCharge.getAccount(getC_Charge_ID(), as, getAmount());
else if (m_Prepayment)
acct = getAccount(Doc.ACCTTYPE_C_Prepayment, as);
else
acct = getAccount(Doc.ACCTTYPE_UnallocatedCash, as);
fl = fact.createLine(null, acct,
getC_Currency_ID(), null, getAmount());
if (fl != null && AD_Org_ID != 0
&& getC_Charge_ID() == 0) // don't overwrite charge
fl.setAD_Org_ID(AD_Org_ID);
}
// APP
else if (getDocumentType().equals(DOCTYPE_APPayment))
{
MAccount acct = null;
if (getC_Charge_ID() != 0)
acct = MCharge.getAccount(getC_Charge_ID(), as, getAmount());
else if (m_Prepayment)
acct = getAccount(Doc.ACCTTYPE_V_Prepayment, as);
else
acct = getAccount(Doc.ACCTTYPE_PaymentSelect, as);
FactLine fl = fact.createLine(null, acct,
getC_Currency_ID(), getAmount(), null);
if (fl != null && AD_Org_ID != 0
&& getC_Charge_ID() == 0) // don't overwrite charge
fl.setAD_Org_ID(AD_Org_ID);
// Asset
fl = fact.createLine(null, getAccount(Doc.ACCTTYPE_BankInTransit, as),
getC_Currency_ID(), null, getAmount());
if (fl != null && AD_Org_ID != 0)
fl.setAD_Org_ID(AD_Org_ID);
}
else
{
p_Error = "DocumentType unknown: " + getDocumentType();
log.log(Level.SEVERE, p_Error);
fact = null;
}
//
ArrayList<Fact> facts = new ArrayList<Fact>();
facts.add(fact);
return facts;
} // createFact
/**
* Get AD_Org_ID from Bank Account
* @return AD_Org_ID or 0
*/
private int getBank_Org_ID ()
{
if (m_C_BankAccount_ID == 0)
return 0;
//
MBankAccount ba = MBankAccount.get(getCtx(), m_C_BankAccount_ID);
return ba.getAD_Org_ID();
} // getBank_Org_ID
} // Doc_Payment

View File

@ -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.acct;
import java.math.*;
import java.sql.*;
import java.util.*;
import org.compiere.model.*;
import java.util.logging.*;
import org.compiere.util.*;
/**
* Post Invoice Documents.
* <pre>
* Table: M_Production (325)
* Document Types: MMP
* </pre>
* @author Jorg Janke
* @version $Id: Doc_Production.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class Doc_Production extends Doc
{
/**
* Constructor
* @param ass accounting schemata
* @param rs record
* @param trxName trx
*/
public Doc_Production (MAcctSchema[] ass, ResultSet rs, String trxName)
{
super (ass, X_M_Production.class, rs, DOCTYPE_MatProduction, trxName);
} // Doc_Production
/**
* Load Document Details
* @return error message or null
*/
protected String loadDocumentDetails()
{
setC_Currency_ID (NO_CURRENCY);
X_M_Production prod = (X_M_Production)getPO();
setDateDoc (prod.getMovementDate());
setDateAcct(prod.getMovementDate());
// Contained Objects
p_lines = loadLines(prod);
log.fine("Lines=" + p_lines.length);
return null;
} // loadDocumentDetails
/**
* Load Invoice Line
* @param prod production
* @return DoaLine Array
*/
private DocLine[] loadLines(X_M_Production prod)
{
ArrayList<DocLine> list = new ArrayList<DocLine>();
// Production
// -- ProductionPlan
// -- -- ProductionLine - the real level
String sqlPP = "SELECT * FROM M_ProductionPlan pp "
+ "WHERE pp.M_Production_ID=? "
+ "ORDER BY pp.Line";
String sqlPL = "SELECT * FROM M_ProductionLine pl "
+ "WHERE pl.M_ProductionPlan_ID=? "
+ "ORDER BY pl.Line";
try
{
PreparedStatement pstmtPP = DB.prepareStatement(sqlPP, getTrxName());
pstmtPP.setInt(1, get_ID());
ResultSet rsPP = pstmtPP.executeQuery();
//
while (rsPP.next())
{
int M_Product_ID = rsPP.getInt("M_Product_ID");
int M_ProductionPlan_ID = rsPP.getInt("M_ProductionPlan_ID");
//
try
{
PreparedStatement pstmtPL = DB.prepareStatement(sqlPL, getTrxName());
pstmtPL.setInt(1, M_ProductionPlan_ID);
ResultSet rsPL = pstmtPL.executeQuery();
while (rsPL.next())
{
X_M_ProductionLine line = new X_M_ProductionLine(getCtx(), rsPL, getTrxName());
if (line.getMovementQty().signum() == 0)
{
log.info("LineQty=0 - " + line);
continue;
}
DocLine docLine = new DocLine (line, this);
docLine.setQty (line.getMovementQty(), false);
// Identify finished BOM Product
docLine.setProductionBOM(line.getM_Product_ID() == M_Product_ID);
//
log.fine(docLine.toString());
list.add (docLine);
}
rsPL.close();
pstmtPL.close();
}
catch (Exception ee)
{
log.log(Level.SEVERE, sqlPL, ee);
}
}
rsPP.close();
pstmtPP.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, sqlPP, e);
}
// Return Array
DocLine[] dl = new DocLine[list.size()];
list.toArray(dl);
return dl;
} // loadLines
/**
* Get Balance
* @return Zero (always balanced)
*/
public BigDecimal getBalance()
{
BigDecimal retValue = Env.ZERO;
return retValue;
} // getBalance
/**
* Create Facts (the accounting logic) for
* MMP.
* <pre>
* Production
* Inventory DR CR
* </pre>
* @param as account schema
* @return Fact
*/
public ArrayList<Fact> createFacts (MAcctSchema as)
{
// create Fact Header
Fact fact = new Fact(this, as, Fact.POST_Actual);
setC_Currency_ID (as.getC_Currency_ID());
// Line pointer
FactLine fl = null;
for (int i = 0; i < p_lines.length; i++)
{
DocLine line = p_lines[i];
// Calculate Costs
BigDecimal costs = null;
if (line.isProductionBOM())
{
// Get BOM Cost - Sum of individual lines
BigDecimal bomCost = Env.ZERO;
for (int ii = 0; ii < p_lines.length; ii++)
{
DocLine line0 = p_lines[ii];
if (line0.getM_ProductionPlan_ID() != line.getM_ProductionPlan_ID())
continue;
if (!line0.isProductionBOM())
bomCost = bomCost.add(line0.getProductCosts(as, line.getAD_Org_ID(), false));
}
costs = bomCost.negate();
}
else
costs = line.getProductCosts(as, line.getAD_Org_ID(), false);
// Inventory DR CR
fl = fact.createLine(line,
line.getAccount(ProductCost.ACCTTYPE_P_Asset, as),
as.getC_Currency_ID(), costs);
if (fl == null)
{
p_Error = "No Costs for Line " + line.getLine() + " - " + line;
return null;
}
fl.setM_Locator_ID(line.getM_Locator_ID());
fl.setQty(line.getQty());
// Cost Detail
String description = line.getDescription();
if (description == null)
description = "";
if (line.isProductionBOM())
description += "(*)";
MCostDetail.createProduction(as, line.getAD_Org_ID(),
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
line.get_ID(), 0,
costs, line.getQty(),
description, getTrxName());
}
//
ArrayList<Fact> facts = new ArrayList<Fact>();
facts.add(fact);
return facts;
} // createFact
} // Doc_Production

View File

@ -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.acct;
import java.math.*;
import java.sql.*;
import org.compiere.model.*;
import java.util.*;
import java.util.logging.*;
import org.compiere.util.*;
/**
* Project Issue.
* Note:
* Will load the default GL Category.
* Set up a document type to set the GL Category.
*
* @author Jorg Janke
* @version $Id: Doc_ProjectIssue.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $
*/
public class Doc_ProjectIssue extends Doc
{
/**
* Constructor
* @param ass accounting schemata
* @param rs record
* @param trxName trx
*/
public Doc_ProjectIssue (MAcctSchema[] ass, ResultSet rs, String trxName)
{
super (ass, MProjectIssue.class, rs, DOCTYPE_ProjectIssue, trxName);
} // Doc_ProjectIssue
/** Pseudo Line */
private DocLine m_line = null;
/** Issue */
private MProjectIssue m_issue = null;
/**
* Load Document Details
* @return error message or null
*/
protected String loadDocumentDetails()
{
setC_Currency_ID(NO_CURRENCY);
m_issue = (MProjectIssue)getPO();
setDateDoc (m_issue.getMovementDate());
setDateAcct(m_issue.getMovementDate());
// Pseudo Line
m_line = new DocLine (m_issue, this);
m_line.setQty (m_issue.getMovementQty(), true); // sets Trx and Storage Qty
// Pseudo Line Check
if (m_line.getM_Product_ID() == 0)
log.warning(m_line.toString() + " - No Product");
log.fine(m_line.toString());
return null;
} // loadDocumentDetails
/**
* Get DocumentNo
* @return document no
*/
public String getDocumentNo ()
{
MProject p = m_issue.getParent();
if (p != null)
return p.getValue() + " #" + m_issue.getLine();
return "(" + m_issue.get_ID() + ")";
} // getDocumentNo
/**
* Get Balance
* @return Zero (always balanced)
*/
public BigDecimal getBalance()
{
BigDecimal retValue = Env.ZERO;
return retValue;
} // getBalance
/**
* Create Facts (the accounting logic) for
* PJI
* <pre>
* Issue
* ProjectWIP DR
* Inventory CR
* </pre>
* Project Account is either Asset or WIP depending on Project Type
* @param as accounting schema
* @return Fact
*/
public ArrayList<Fact> createFacts (MAcctSchema as)
{
// create Fact Header
Fact fact = new Fact(this, as, Fact.POST_Actual);
setC_Currency_ID (as.getC_Currency_ID());
MProject project = new MProject (getCtx(), m_issue.getC_Project_ID(), null);
String ProjectCategory = project.getProjectCategory();
MProduct product = MProduct.get(getCtx(), m_issue.getM_Product_ID());
// Line pointers
FactLine dr = null;
FactLine cr = null;
// Issue Cost
BigDecimal cost = null;
if (m_issue.getM_InOutLine_ID() != 0)
cost = getPOCost(as);
else if (m_issue.getS_TimeExpenseLine_ID() != 0)
cost = getLaborCost(as);
if (cost == null) // standard Product Costs
cost = m_line.getProductCosts(as, getAD_Org_ID(), false);
// Project DR
int acctType = ACCTTYPE_ProjectWIP;
if (MProject.PROJECTCATEGORY_AssetProject.equals(ProjectCategory))
acctType = ACCTTYPE_ProjectAsset;
dr = fact.createLine(m_line,
getAccount(acctType, as), as.getC_Currency_ID(), cost, null);
dr.setQty(m_line.getQty().negate());
// Inventory CR
acctType = ProductCost.ACCTTYPE_P_Asset;
if (product.isService())
acctType = ProductCost.ACCTTYPE_P_Expense;
cr = fact.createLine(m_line,
m_line.getAccount(acctType, as),
as.getC_Currency_ID(), null, cost);
cr.setM_Locator_ID(m_line.getM_Locator_ID());
cr.setLocationFromLocator(m_line.getM_Locator_ID(), true); // from Loc
//
ArrayList<Fact> facts = new ArrayList<Fact>();
facts.add(fact);
return facts;
} // createFact
/**
* Get PO Costs in Currency of AcctSchema
* @param as Account Schema
* @return Unit PO Cost
*/
private BigDecimal getPOCost(MAcctSchema as)
{
BigDecimal retValue = null;
// Uses PO Date
String sql = "SELECT currencyConvert(ol.PriceActual, o.C_Currency_ID, ?, o.DateOrdered, o.C_ConversionType_ID, ?, ?) "
+ "FROM C_OrderLine ol"
+ " INNER JOIN M_InOutLine iol ON (iol.C_OrderLine_ID=ol.C_OrderLine_ID)"
+ " INNER JOIN C_Order o ON (o.C_Order_ID=ol.C_Order_ID) "
+ "WHERE iol.M_InOutLine_ID=?";
PreparedStatement pstmt = null;
try
{
pstmt = DB.prepareStatement(sql, null);
pstmt.setInt(1, as.getC_Currency_ID());
pstmt.setInt(2, getAD_Client_ID());
pstmt.setInt(3, getAD_Org_ID());
pstmt.setInt(4, m_issue.getM_InOutLine_ID());
ResultSet rs = pstmt.executeQuery();
if (rs.next())
{
retValue = rs.getBigDecimal(1);
log.fine("POCost = " + retValue);
}
else
log.warning("Not found for M_InOutLine_ID=" + m_issue.getM_InOutLine_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 retValue;
} // getPOCost();
/**
* Get Labor Cost from Expense Report
* @param as Account Schema
* @return Unit Labor Cost
*/
private BigDecimal getLaborCost(MAcctSchema as)
{
BigDecimal retValue = null;
/** TODO Labor Cost */
return retValue;
} // getLaborCost
} // DocProjectIssue

View File

@ -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.acct;
import java.math.*;
import java.util.*;
import java.util.logging.*;
import java.sql.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Post Order Documents.
*
* <pre>
* Table: M_Requisition
* Document Types: POR (Requisition)
* </pre>
*
* @author Jorg Janke
* @version $Id: Doc_Requisition.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class Doc_Requisition extends Doc
{
/**
* Constructor
* @param ass accounting schemata
* @param rs record
* @param trxName trx
*/
protected Doc_Requisition (MAcctSchema[] ass, ResultSet rs, String trxName)
{
super (ass, MRequisition.class, rs, DOCTYPE_PurchaseRequisition, trxName);
} // Doc_Requisition
/**
* Load Specific Document Details
* @return error message or null
*/
protected String loadDocumentDetails ()
{
setC_Currency_ID(NO_CURRENCY);
MRequisition req = (MRequisition)getPO();
setDateDoc (req.getDateDoc());
setDateAcct (req.getDateDoc());
// Amounts
setAmount(AMTTYPE_Gross, req.getTotalLines());
setAmount(AMTTYPE_Net, req.getTotalLines());
// Contained Objects
p_lines = loadLines (req);
// log.fine( "Lines=" + p_lines.length + ", Taxes=" + m_taxes.length);
return null;
} // loadDocumentDetails
/**
* Load Requisition Lines
* @param req requisition
* @return DocLine Array
*/
private DocLine[] loadLines (MRequisition req)
{
ArrayList<DocLine> list = new ArrayList<DocLine> ();
MRequisitionLine[] lines = req.getLines();
for (int i = 0; i < lines.length; i++)
{
MRequisitionLine line = lines[i];
DocLine docLine = new DocLine (line, this);
BigDecimal Qty = line.getQty();
docLine.setQty (Qty, false);
BigDecimal PriceActual = line.getPriceActual();
BigDecimal LineNetAmt = line.getLineNetAmt();
docLine.setAmount (LineNetAmt); // DR
list.add (docLine);
}
// Return Array
DocLine[] dls = new DocLine[list.size ()];
list.toArray (dls);
return dls;
} // loadLines
/***************************************************************************
* Get Source Currency Balance - subtracts line and tax amounts from total -
* no rounding
*
* @return positive amount, if total invoice is bigger than lines
*/
public BigDecimal getBalance ()
{
BigDecimal retValue = new BigDecimal (0.0);
return retValue;
} // getBalance
/***************************************************************************
* Create Facts (the accounting logic) for POR.
* <pre>
* Reservation
* Expense CR
* Offset DR
* </pre>
* @param as accounting schema
* @return Fact
*/
public ArrayList<Fact> createFacts (MAcctSchema as)
{
ArrayList<Fact> facts = new ArrayList<Fact>();
Fact fact = new Fact (this, as, Fact.POST_Reservation);
setC_Currency_ID(as.getC_Currency_ID());
//
BigDecimal grossAmt = getAmount (Doc.AMTTYPE_Gross);
// Commitment
if (as.isCreateReservation ())
{
BigDecimal total = Env.ZERO;
for (int i = 0; i < p_lines.length; i++)
{
DocLine line = p_lines[i];
BigDecimal cost = line.getAmtSource();
total = total.add (cost);
// Account
MAccount expense = line.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
//
fact.createLine (line, expense, as.getC_Currency_ID(), cost, null);
}
// Offset
MAccount offset = getAccount (ACCTTYPE_CommitmentOffset, as);
if (offset == null)
{
p_Error = "@NotFound@ @CommitmentOffset_Acct@";
log.log (Level.SEVERE, p_Error);
return null;
}
fact.createLine (null, offset, getC_Currency_ID(), null, total);
facts.add(fact);
}
return facts;
} // createFact
} // Doc_Requisition

View File

@ -0,0 +1,860 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.acct;
import java.math.*;
import java.util.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Accounting Fact
*
* @author Jorg Janke
* @version $Id: Fact.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $
*/
public final class Fact
{
/**
* Constructor
* @param document pointer to document
* @param acctSchema Account Schema to create accounts
* @param defaultPostingType the default Posting type (actual,..) for this posting
*/
public Fact (Doc document, MAcctSchema acctSchema, String defaultPostingType)
{
m_doc = document;
m_acctSchema = acctSchema;
m_postingType = defaultPostingType;
//
log.config(toString());
} // Fact
/** Log */
private CLogger log = CLogger.getCLogger(getClass());
/** Document */
private Doc m_doc = null;
/** Accounting Schema */
private MAcctSchema m_acctSchema = null;
/** Transaction */
private String m_trxName;
/** Posting Type */
private String m_postingType = null;
/** Actual Balance Type */
public static final String POST_Actual = MFactAcct.POSTINGTYPE_Actual;
/** Budget Balance Type */
public static final String POST_Budget = MFactAcct.POSTINGTYPE_Budget;;
/** Encumbrance Posting */
public static final String POST_Commitment = MFactAcct.POSTINGTYPE_Commitment;
/** Encumbrance Posting */
public static final String POST_Reservation = MFactAcct.POSTINGTYPE_Reservation;
/** Is Converted */
private boolean m_converted = false;
/** Lines */
private ArrayList<FactLine> m_lines = new ArrayList<FactLine>();
/**
* Dispose
*/
public void dispose()
{
m_lines.clear();
m_lines = null;
} // dispose
/**
* Create and convert Fact Line.
* Used to create a DR and/or CR entry
*
* @param docLine the document line or null
* @param account if null, line is not created
* @param C_Currency_ID the currency
* @param debitAmt debit amount, can be null
* @param creditAmt credit amount, can be null
* @return Fact Line
*/
public FactLine createLine (DocLine docLine, MAccount account,
int C_Currency_ID, BigDecimal debitAmt, BigDecimal creditAmt)
{
// log.fine("createLine - " + account + " - Dr=" + debitAmt + ", Cr=" + creditAmt);
// Data Check
if (account == null)
{
log.info("No account for " + docLine
+ ": Amt=" + debitAmt + "/" + creditAmt
+ " - " + toString());
return null;
}
//
FactLine line = new FactLine (m_doc.getCtx(), m_doc.get_Table_ID(),
m_doc.get_ID(),
docLine == null ? 0 : docLine.get_ID(), m_trxName);
// Set Info & Account
line.setDocumentInfo(m_doc, docLine);
line.setPostingType(m_postingType);
line.setAccount(m_acctSchema, account);
// Amounts - one needs to not zero
if (!line.setAmtSource(C_Currency_ID, debitAmt, creditAmt))
{
if (docLine == null || docLine.getQty() == null || docLine.getQty().signum() == 0)
{
log.fine("Both amounts & qty = 0/Null - " + docLine
+ " - " + toString());
return null;
}
log.fine("Both amounts = 0/Null, Qty=" + docLine.getQty() + " - " + docLine
+ " - " + toString());
}
// Convert
line.convert();
// Optionally overwrite Acct Amount
if (docLine != null
&& (docLine.getAmtAcctDr() != null || docLine.getAmtAcctCr() != null))
line.setAmtAcct(docLine.getAmtAcctDr(), docLine.getAmtAcctCr());
//
log.fine(line.toString());
add(line);
return line;
} // createLine
/**
* Add Fact Line
* @param line fact line
*/
void add (FactLine line)
{
m_lines.add(line);
} // add
/**
* Create and convert Fact Line.
* Used to create either a DR or CR entry
*
* @param docLine Document Line or null
* @param accountDr Account to be used if Amt is DR balance
* @param accountCr Account to be used if Amt is CR balance
* @param C_Currency_ID Currency
* @param Amt if negative Cr else Dr
* @return FactLine
*/
public FactLine createLine (DocLine docLine, MAccount accountDr, MAccount accountCr,
int C_Currency_ID, BigDecimal Amt)
{
if (Amt.signum() < 0)
return createLine (docLine, accountCr, C_Currency_ID, null, Amt.abs());
else
return createLine (docLine, accountDr, C_Currency_ID, Amt, null);
} // createLine
/**
* Create and convert Fact Line.
* Used to create either a DR or CR entry
*
* @param docLine Document line or null
* @param account Account to be used
* @param C_Currency_ID Currency
* @param Amt if negative Cr else Dr
* @return FactLine
*/
public FactLine createLine (DocLine docLine, MAccount account,
int C_Currency_ID, BigDecimal Amt)
{
if (Amt.signum() < 0)
return createLine (docLine, account, C_Currency_ID, null, Amt.abs());
else
return createLine (docLine, account, C_Currency_ID, Amt, null);
} // createLine
/**
* Is Posting Type
* @param PostingType - see POST_*
* @return true if document is posting type
*/
public boolean isPostingType (String PostingType)
{
return m_postingType.equals(PostingType);
} // isPostingType
/**
* Is converted
* @return true if converted
*/
public boolean isConverted()
{
return m_converted;
} // isConverted
/**
* Get AcctSchema
* @return AcctSchema
*/
public MAcctSchema getAcctSchema()
{
return m_acctSchema;
} // getAcctSchema
/**************************************************************************
* Are the lines Source Balanced
* @return true if source lines balanced
*/
public boolean isSourceBalanced()
{
// No lines -> balanded
if (m_lines.size() == 0)
return true;
BigDecimal balance = getSourceBalance();
boolean retValue = balance.signum() == 0;
if (retValue)
log.finer(toString());
else
log.warning ("NO - Diff=" + balance + " - " + toString());
return retValue;
} // isSourceBalanced
/**
* Return Source Balance
* @return source balance
*/
protected BigDecimal getSourceBalance()
{
BigDecimal result = Env.ZERO;
for (int i = 0; i < m_lines.size(); i++)
{
FactLine line = (FactLine)m_lines.get(i);
result = result.add (line.getSourceBalance());
}
// log.fine("getSourceBalance - " + result.toString());
return result;
} // getSourceBalance
/**
* Create Source Line for Suspense Balancing.
* Only if Suspense Balancing is enabled and not a multi-currency document
* (double check as otherwise the rule should not have fired)
* If not balanced create balancing entry in currency of the document
* @return FactLine
*/
public FactLine balanceSource()
{
if (!m_acctSchema.isSuspenseBalancing() || m_doc.isMultiCurrency())
return null;
BigDecimal diff = getSourceBalance();
log.finer("Diff=" + diff);
// new line
FactLine line = new FactLine (m_doc.getCtx(), m_doc.get_Table_ID(),
m_doc.get_ID(), 0, m_trxName);
line.setDocumentInfo(m_doc, null);
line.setPostingType(m_postingType);
// Amount
if (diff.signum() < 0) // negative balance => DR
line.setAmtSource(m_doc.getC_Currency_ID(), diff.abs(), Env.ZERO);
else // positive balance => CR
line.setAmtSource(m_doc.getC_Currency_ID(), Env.ZERO, diff);
// Account
line.setAccount(m_acctSchema, m_acctSchema.getSuspenseBalancing_Acct());
// Convert
line.convert();
//
log.fine(line.toString());
m_lines.add(line);
return line;
} // balancingSource
/**************************************************************************
* Are all segments balanced
* @return true if segments are balanced
*/
public boolean isSegmentBalanced()
{
if (m_lines.size() == 0)
return true;
MAcctSchemaElement[] elements = m_acctSchema.getAcctSchemaElements();
// check all balancing segments
for (int i = 0; i < elements.length; i++)
{
MAcctSchemaElement ase = elements[i];
if (ase.isBalanced() && !isSegmentBalanced (ase.getElementType()))
return false;
}
return true;
} // isSegmentBalanced
/**
* Is Source Segment balanced.
* @param segmentType - see AcctSchemaElement.SEGMENT_*
* Implemented only for Org
* Other sensible candidates are Project, User1/2
* @return true if segments are balanced
*/
public boolean isSegmentBalanced (String segmentType)
{
if (segmentType.equals(MAcctSchemaElement.ELEMENTTYPE_Organization))
{
HashMap<Integer,BigDecimal> map = new HashMap<Integer,BigDecimal>();
// Add up values by key
for (int i = 0; i < m_lines.size(); i++)
{
FactLine line = (FactLine)m_lines.get(i);
Integer key = new Integer(line.getAD_Org_ID());
BigDecimal bal = line.getSourceBalance();
BigDecimal oldBal = (BigDecimal)map.get(key);
if (oldBal != null)
bal = bal.add(oldBal);
map.put(key, bal);
// System.out.println("Add Key=" + key + ", Bal=" + bal + " <- " + line);
}
// check if all keys are zero
Iterator values = map.values().iterator();
while (values.hasNext())
{
BigDecimal bal = (BigDecimal)values.next();
if (bal.signum() != 0)
{
map.clear();
log.warning ("(" + segmentType + ") NO - " + toString() + ", Balance=" + bal);
return false;
}
}
map.clear();
log.finer("(" + segmentType + ") - " + toString());
return true;
}
log.finer("(" + segmentType + ") (not checked) - " + toString());
return true;
} // isSegmentBalanced
/**
* Balance all segments.
* - For all balancing segments
* - For all segment values
* - If balance <> 0 create dueTo/dueFrom line
* overwriting the segment value
*/
public void balanceSegments()
{
MAcctSchemaElement[] elements = m_acctSchema.getAcctSchemaElements();
// check all balancing segments
for (int i = 0; i < elements.length; i++)
{
MAcctSchemaElement ase = elements[i];
if (ase.isBalanced())
balanceSegment (ase.getElementType());
}
} // balanceSegments
/**
* Balance Source Segment
* @param elementType segment element type
*/
private void balanceSegment (String elementType)
{
// no lines -> balanced
if (m_lines.size() == 0)
return;
log.fine ("(" + elementType + ") - " + toString());
// Org
if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_Organization))
{
HashMap<Integer,Balance> map = new HashMap<Integer,Balance>();
// Add up values by key
for (int i = 0; i < m_lines.size(); i++)
{
FactLine line = (FactLine)m_lines.get(i);
Integer key = new Integer(line.getAD_Org_ID());
// BigDecimal balance = line.getSourceBalance();
Balance oldBalance = (Balance)map.get(key);
if (oldBalance == null)
{
oldBalance = new Balance (line.getAmtSourceDr(), line.getAmtSourceCr());
map.put(key, oldBalance);
}
else
oldBalance.add(line.getAmtSourceDr(), line.getAmtSourceCr());
// log.info ("Key=" + key + ", Balance=" + balance + " - " + line);
}
// Create entry for non-zero element
Iterator keys = map.keySet().iterator();
while (keys.hasNext())
{
Integer key = (Integer)keys.next();
Balance difference = (Balance)map.get(key);
log.info (elementType + "=" + key + ", " + difference);
//
if (!difference.isZeroBalance())
{
// Create Balancing Entry
FactLine line = new FactLine (m_doc.getCtx(), m_doc.get_Table_ID(),
m_doc.get_ID(), 0, m_trxName);
line.setDocumentInfo(m_doc, null);
line.setPostingType(m_postingType);
// Amount & Account
if (difference.getBalance().signum() < 0)
{
if (difference.isReversal())
{
line.setAmtSource(m_doc.getC_Currency_ID(), Env.ZERO, difference.getPostBalance());
line.setAccount(m_acctSchema, m_acctSchema.getDueTo_Acct(elementType));
}
else
{
line.setAmtSource(m_doc.getC_Currency_ID(), difference.getPostBalance(), Env.ZERO);
line.setAccount(m_acctSchema, m_acctSchema.getDueFrom_Acct(elementType));
}
}
else
{
if (difference.isReversal())
{
line.setAmtSource(m_doc.getC_Currency_ID(), difference.getPostBalance(), Env.ZERO);
line.setAccount(m_acctSchema, m_acctSchema.getDueFrom_Acct(elementType));
}
else
{
line.setAmtSource(m_doc.getC_Currency_ID(), Env.ZERO, difference.getPostBalance());
line.setAccount(m_acctSchema, m_acctSchema.getDueTo_Acct(elementType));
}
}
line.convert();
line.setAD_Org_ID(key.intValue());
//
m_lines.add(line);
log.fine("(" + elementType + ") - " + line);
}
}
map.clear();
}
} // balanceSegment
/**************************************************************************
* Are the lines Accounting Balanced
* @return true if accounting lines are balanced
*/
public boolean isAcctBalanced()
{
// no lines -> balanced
if (m_lines.size() == 0)
return true;
BigDecimal balance = getAcctBalance();
boolean retValue = balance.signum() == 0;
if (retValue)
log.finer(toString());
else
log.warning("NO - Diff=" + balance + " - " + toString());
return retValue;
} // isAcctBalanced
/**
* Return Accounting Balance
* @return true if accounting lines are balanced
*/
protected BigDecimal getAcctBalance()
{
BigDecimal result = Env.ZERO;
for (int i = 0; i < m_lines.size(); i++)
{
FactLine line = (FactLine)m_lines.get(i);
result = result.add(line.getAcctBalance());
}
// log.fine(result.toString());
return result;
} // getAcctBalance
/**
* Balance Accounting Currency.
* If the accounting currency is not balanced,
* if Currency balancing is enabled
* create a new line using the currency balancing account with zero source balance
* or
* adjust the line with the largest balance sheet account
* or if no balance sheet account exist, the line with the largest amount
* @return FactLine
*/
public FactLine balanceAccounting()
{
BigDecimal diff = getAcctBalance(); // DR-CR
log.fine("Balance=" + diff
+ ", CurrBal=" + m_acctSchema.isCurrencyBalancing()
+ " - " + toString());
FactLine line = null;
BigDecimal BSamount = Env.ZERO;
FactLine BSline = null;
BigDecimal PLamount = Env.ZERO;
FactLine PLline = null;
// Find line biggest BalanceSheet or P&L line
for (int i = 0; i < m_lines.size(); i++)
{
FactLine l = (FactLine)m_lines.get(i);
BigDecimal amt = l.getAcctBalance().abs();
if (l.isBalanceSheet() && amt.compareTo(BSamount) > 0)
{
BSamount = amt;
BSline = l;
}
else if (!l.isBalanceSheet() && amt.compareTo(PLamount) > 0)
{
PLamount = amt;
PLline = l;
}
}
// Create Currency Balancing Entry
if (m_acctSchema.isCurrencyBalancing())
{
line = new FactLine (m_doc.getCtx(), m_doc.get_Table_ID(),
m_doc.get_ID(), 0, m_trxName);
line.setDocumentInfo (m_doc, null);
line.setPostingType (m_postingType);
line.setAccount (m_acctSchema, m_acctSchema.getCurrencyBalancing_Acct());
// Amount
line.setAmtSource(m_doc.getC_Currency_ID(), Env.ZERO, Env.ZERO);
line.convert();
// Accounted
BigDecimal drAmt = Env.ZERO;
BigDecimal crAmt = Env.ZERO;
boolean isDR = diff.signum() < 0;
BigDecimal difference = diff.abs();
if (isDR)
drAmt = difference;
else
crAmt = difference;
// Switch sides
boolean switchIt = BSline != null
&& ((BSline.isDrSourceBalance() && isDR)
|| (!BSline.isDrSourceBalance() && !isDR));
if (switchIt)
{
drAmt = Env.ZERO;
crAmt = Env.ZERO;
if (isDR)
crAmt = difference.negate();
else
drAmt = difference.negate();
}
line.setAmtAcct(drAmt, crAmt);
log.fine(line.toString());
m_lines.add(line);
}
else // Adjust biggest (Balance Sheet) line amount
{
if (BSline != null)
line = BSline;
else
line = PLline;
if (line == null)
log.severe ("No Line found");
else
{
log.fine("Adjusting Amt=" + diff + "; Line=" + line);
line.currencyCorrect(diff);
log.fine(line.toString());
}
} // correct biggest amount
return line;
} // balanceAccounting
/**
* Check Accounts of Fact Lines
* @return true if success
*/
public boolean checkAccounts()
{
// no lines -> nothing to distribute
if (m_lines.size() == 0)
return true;
// For all fact lines
for (int i = 0; i < m_lines.size(); i++)
{
FactLine line = (FactLine)m_lines.get(i);
MAccount account = line.getAccount();
if (account == null)
{
log.warning("No Account for " + line);
return false;
}
MElementValue ev = account.getAccount();
if (ev == null)
{
log.warning("No Element Value for " + account
+ ": " + line);
return false;
}
if (ev.isSummary())
{
log.warning("Cannot post to Summary Account " + ev
+ ": " + line);
return false;
}
if (!ev.isActive())
{
log.warning("Cannot post to Inactive Account " + ev
+ ": " + line);
return false;
}
} // for all lines
return true;
} // checkAccounts
/**
* GL Distribution of Fact Lines
* @return true if success
*/
public boolean distribute()
{
// no lines -> nothing to distribute
if (m_lines.size() == 0)
return true;
ArrayList<FactLine> newLines = new ArrayList<FactLine>();
// For all fact lines
for (int i = 0; i < m_lines.size(); i++)
{
FactLine dLine = (FactLine)m_lines.get(i);
MDistribution[] distributions = MDistribution.get (dLine.getAccount(),
m_postingType, m_doc.getC_DocType_ID());
// No Distribution for this line
if (distributions == null || distributions.length == 0)
continue;
// Just the first
if (distributions.length > 1)
log.warning("More then one Distributiion for " + dLine.getAccount());
MDistribution distribution = distributions[0];
// Add Reversal
FactLine reversal = dLine.reverse(distribution.getName());
log.info("Reversal=" + reversal);
newLines.add(reversal); // saved in postCommit
// Prepare
distribution.distribute(dLine.getAccount(), dLine.getSourceBalance(), dLine.getC_Currency_ID());
MDistributionLine[] lines = distribution.getLines(false);
for (int j = 0; j < lines.length; j++)
{
MDistributionLine dl = lines[j];
if (!dl.isActive() || dl.getAmt().signum() == 0)
continue;
FactLine factLine = new FactLine (m_doc.getCtx(), m_doc.get_Table_ID(),
m_doc.get_ID(), 0, m_trxName);
// Set Info & Account
factLine.setDocumentInfo(m_doc, dLine.getDocLine());
factLine.setAccount(m_acctSchema, dl.getAccount());
factLine.setPostingType(m_postingType);
if (dl.isOverwriteOrg()) // set Org explicitly
factLine.setAD_Org_ID(dl.getOrg_ID());
//
if (dl.getAmt().signum() < 0)
factLine.setAmtSource(dLine.getC_Currency_ID(), null, dl.getAmt().abs());
else
factLine.setAmtSource(dLine.getC_Currency_ID(), dl.getAmt(), null);
// Convert
factLine.convert();
//
String description = distribution.getName() + " #" + dl.getLine();
if (dl.getDescription() != null)
description += " - " + dl.getDescription();
factLine.addDescription(description);
//
log.info(factLine.toString());
newLines.add(factLine);
}
} // for all lines
// Add Lines
for (int i = 0; i < newLines.size(); i++)
m_lines.add(newLines.get(i));
return true;
} // distribute
/**************************************************************************
* String representation
* @return String
*/
public String toString()
{
StringBuffer sb = new StringBuffer("Fact[");
sb.append(m_doc.toString());
sb.append(",").append(m_acctSchema.toString());
sb.append(",PostType=").append(m_postingType);
sb.append("]");
return sb.toString();
} // toString
/**
* Get Lines
* @return FactLine Array
*/
public FactLine[] getLines()
{
FactLine[] temp = new FactLine[m_lines.size()];
m_lines.toArray(temp);
return temp;
} // getLines
/**
* Save Fact
* @param trxName transaction
* @return true if all lines were saved
*/
public boolean save (String trxName)
{
// save Lines
for (int i = 0; i < m_lines.size(); i++)
{
FactLine fl = (FactLine)m_lines.get(i);
// log.fine("save - " + fl);
if (!fl.save(trxName)) // abort on first error
return false;
}
return true;
} // commit
/**
* Get Transaction
* @return trx
*/
public String get_TrxName()
{
return m_trxName;
} // getTrxName
/**
* Set Transaction name
* @param trxName
*/
private void set_TrxName(String trxName)
{
m_trxName = trxName;
} // set_TrxName
/**
* Fact Balance Utility
*
* @author Jorg Janke
* @version $Id: Fact.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $
*/
public class Balance
{
/**
* New Balance
* @param dr DR
* @param cr CR
*/
public Balance (BigDecimal dr, BigDecimal cr)
{
DR = dr;
CR = cr;
}
/** DR Amount */
public BigDecimal DR = Env.ZERO;
/** CR Amount */
public BigDecimal CR = Env.ZERO;
/**
* Add
* @param dr DR
* @param cr CR
*/
public void add (BigDecimal dr, BigDecimal cr)
{
DR = DR.add(dr);
CR = CR.add(cr);
}
/**
* Get Balance
* @return balance
*/
public BigDecimal getBalance()
{
return DR.subtract(CR);
} // getBalance
/**
* Get Post Balance
* @return absolute balance - negative if reversal
*/
public BigDecimal getPostBalance()
{
BigDecimal bd = getBalance().abs();
if (isReversal())
return bd.negate();
return bd;
} // getPostBalance
/**
* Zero Balance
* @return true if 0
*/
public boolean isZeroBalance()
{
return getBalance().signum() == 0;
} // isZeroBalance
/**
* Reversal
* @return true if both DR/CR are negative or zero
*/
public boolean isReversal()
{
return DR.signum() <= 0 && CR.signum() <= 0;
} // isReversal
/**
* String Representation
* @return info
*/
public String toString ()
{
StringBuffer sb = new StringBuffer ("Balance[");
sb.append ("DR=").append(DR)
.append ("-CR=").append(CR)
.append(" = ").append(getBalance())
.append ("]");
return sb.toString ();
} // toString
} // Balance
} // Fact

View File

@ -0,0 +1,949 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.acct;
import java.math.*;
import java.sql.*;
import java.util.*;
import java.util.logging.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Accounting Fact Entry.
*
* @author Jorg Janke
* @version $Id: FactLine.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public final class FactLine extends X_Fact_Acct
{
/**
* Constructor
* @param ctx context
* @param AD_Table_ID - Table of Document Source
* @param Record_ID - Record of document
* @param Line_ID - Optional line id
* @param trxName transaction
*/
public FactLine (Properties ctx, int AD_Table_ID, int Record_ID, int Line_ID, String trxName)
{
super(ctx, 0, trxName);
setAD_Client_ID(0); // do not derive
setAD_Org_ID(0); // do not derive
//
setAmtAcctCr (Env.ZERO);
setAmtAcctDr (Env.ZERO);
setAmtSourceCr (Env.ZERO);
setAmtSourceDr (Env.ZERO);
// Log.trace(this,Log.l1_User, "FactLine " + AD_Table_ID + ":" + Record_ID);
setAD_Table_ID (AD_Table_ID);
setRecord_ID (Record_ID);
setLine_ID (Line_ID);
} // FactLine
/** Account */
private MAccount m_acct = null;
/** Accounting Schema */
private MAcctSchema m_acctSchema = null;
/** Document Header */
private Doc m_doc = null;
/** Document Line */
private DocLine m_docLine = null;
/**
* Create Reversal (negate DR/CR) of the line
* @param description new description
* @return reversal line
*/
public FactLine reverse (String description)
{
FactLine reversal = new FactLine (getCtx(), getAD_Table_ID(), getRecord_ID(), getLine_ID(), get_TrxName());
reversal.setClientOrg(this); // needs to be set explicitly
reversal.setDocumentInfo(m_doc, m_docLine);
reversal.setAccount(m_acctSchema, m_acct);
reversal.setPostingType(getPostingType());
//
reversal.setAmtSource(getC_Currency_ID(), getAmtSourceDr().negate(), getAmtSourceCr().negate());
reversal.convert();
reversal.setDescription(description);
return reversal;
} // reverse
/**
* Create Accrual (flip CR/DR) of the line
* @param description new description
* @return accrual line
*/
public FactLine accrue (String description)
{
FactLine accrual = new FactLine (getCtx(), getAD_Table_ID(), getRecord_ID(), getLine_ID(), get_TrxName());
accrual.setClientOrg(this); // needs to be set explicitly
accrual.setDocumentInfo(m_doc, m_docLine);
accrual.setAccount(m_acctSchema, m_acct);
accrual.setPostingType(getPostingType());
//
accrual.setAmtSource(getC_Currency_ID(), getAmtSourceCr(), getAmtSourceDr());
accrual.convert();
accrual.setDescription(description);
return accrual;
} // reverse
/**
* Set Account Info
* @param acctSchema account schema
* @param acct account
*/
public void setAccount (MAcctSchema acctSchema, MAccount acct)
{
m_acctSchema = acctSchema;
setC_AcctSchema_ID (acctSchema.getC_AcctSchema_ID());
//
m_acct = acct;
if (getAD_Client_ID() == 0)
setAD_Client_ID(m_acct.getAD_Client_ID());
setAccount_ID (m_acct.getAccount_ID());
setC_SubAcct_ID(m_acct.getC_SubAcct_ID());
} // setAccount
/**
* Set Source Amounts
* @param C_Currency_ID currency
* @param AmtSourceDr source amount dr
* @param AmtSourceCr source amount cr
* @return true, if any if the amount is not zero
*/
public boolean setAmtSource (int C_Currency_ID, BigDecimal AmtSourceDr, BigDecimal AmtSourceCr)
{
setC_Currency_ID (C_Currency_ID);
if (AmtSourceDr != null)
setAmtSourceDr (AmtSourceDr);
if (AmtSourceCr != null)
setAmtSourceCr (AmtSourceCr);
// one needs to be non zero
if (getAmtSourceDr().equals(Env.ZERO) && getAmtSourceCr().equals(Env.ZERO))
return false;
// Currency Precision
int precision = MCurrency.getStdPrecision(getCtx(), C_Currency_ID);
if (AmtSourceDr != null && AmtSourceDr.scale() > precision)
{
BigDecimal AmtSourceDr1 = AmtSourceDr.setScale(precision, BigDecimal.ROUND_HALF_UP);
log.warning("Source DR Precision " + AmtSourceDr + " -> " + AmtSourceDr1);
setAmtSourceDr(AmtSourceDr1);
}
if (AmtSourceCr != null && AmtSourceCr.scale() > precision)
{
BigDecimal AmtSourceCr1 = AmtSourceCr.setScale(precision, BigDecimal.ROUND_HALF_UP);
log.warning("Source CR Precision " + AmtSourceCr + " -> " + AmtSourceCr1);
setAmtSourceCr(AmtSourceCr1);
}
return true;
} // setAmtSource
/**
* Set Accounted Amounts (alternative: call convert)
* @param AmtAcctDr acct amount dr
* @param AmtAcctCr acct amount cr
*/
public void setAmtAcct(BigDecimal AmtAcctDr, BigDecimal AmtAcctCr)
{
setAmtAcctDr (AmtAcctDr);
setAmtAcctCr (AmtAcctCr);
} // setAmtAcct
/**
* Set Document Info
* @param doc document
* @param docLine doc line
*/
public void setDocumentInfo(Doc doc, DocLine docLine)
{
m_doc = doc;
m_docLine = docLine;
// reset
setAD_Org_ID(0);
setC_SalesRegion_ID(0);
// Client
if (getAD_Client_ID() == 0)
setAD_Client_ID (m_doc.getAD_Client_ID());
// Date Trx
setDateTrx (m_doc.getDateDoc());
if (m_docLine != null && m_docLine.getDateDoc() != null)
setDateTrx (m_docLine.getDateDoc());
// Date Acct
setDateAcct (m_doc.getDateAcct());
if (m_docLine != null && m_docLine.getDateAcct() != null)
setDateAcct (m_docLine.getDateAcct());
// Period, Tax
if (m_docLine != null && m_docLine.getC_Period_ID() != 0)
setC_Period_ID(m_docLine.getC_Period_ID());
else
setC_Period_ID (m_doc.getC_Period_ID());
if (m_docLine != null)
setC_Tax_ID (m_docLine.getC_Tax_ID());
// Description
StringBuffer description = new StringBuffer(m_doc.getDocumentNo());
if (m_docLine != null)
{
description.append(" #").append(m_docLine.getLine());
if (m_docLine.getDescription() != null)
description.append(" (").append(m_docLine.getDescription()).append(")");
else if (m_doc.getDescription() != null && m_doc.getDescription().length() > 0)
description.append(" (").append(m_doc.getDescription()).append(")");
}
else if (m_doc.getDescription() != null && m_doc.getDescription().length() > 0)
description.append(" (").append(m_doc.getDescription()).append(")");
setDescription(description.toString());
// Journal Info
setGL_Budget_ID (m_doc.getGL_Budget_ID());
setGL_Category_ID (m_doc.getGL_Category_ID());
// Product
if (m_docLine != null)
setM_Product_ID (m_docLine.getM_Product_ID());
if (getM_Product_ID() == 0)
setM_Product_ID (m_doc.getM_Product_ID());
// UOM
if (m_docLine != null)
setC_UOM_ID (m_docLine.getC_UOM_ID());
// Qty
if (get_Value("Qty") == null) // not previously set
{
setQty (m_doc.getQty()); // neg = outgoing
if (m_docLine != null)
setQty (m_docLine.getQty());
}
// Loc From (maybe set earlier)
if (getC_LocFrom_ID() == 0 && m_docLine != null)
setC_LocFrom_ID (m_docLine.getC_LocFrom_ID());
if (getC_LocFrom_ID() == 0)
setC_LocFrom_ID (m_doc.getC_LocFrom_ID());
// Loc To (maybe set earlier)
if (getC_LocTo_ID() == 0 && m_docLine != null)
setC_LocTo_ID (m_docLine.getC_LocTo_ID());
if (getC_LocTo_ID() == 0)
setC_LocTo_ID (m_doc.getC_LocTo_ID());
// BPartner
if (m_docLine != null)
setC_BPartner_ID (m_docLine.getC_BPartner_ID());
if (getC_BPartner_ID() == 0)
setC_BPartner_ID (m_doc.getC_BPartner_ID());
// Sales Region from BPLocation/Sales Rep
// Trx Org
if (m_docLine != null)
setAD_OrgTrx_ID (m_docLine.getAD_OrgTrx_ID());
if (getAD_OrgTrx_ID() == 0)
setAD_OrgTrx_ID (m_doc.getAD_OrgTrx_ID());
// Project
if (m_docLine != null)
setC_Project_ID (m_docLine.getC_Project_ID());
if (getC_Project_ID() == 0)
setC_Project_ID (m_doc.getC_Project_ID());
// Campaign
if (m_docLine != null)
setC_Campaign_ID (m_docLine.getC_Campaign_ID());
if (getC_Campaign_ID() == 0)
setC_Campaign_ID (m_doc.getC_Campaign_ID());
// Activity
if (m_docLine != null)
setC_Activity_ID (m_docLine.getC_Activity_ID());
if (getC_Activity_ID() == 0)
setC_Activity_ID (m_doc.getC_Activity_ID());
// User List 1
if (m_docLine != null)
setUser1_ID (m_docLine.getUser1_ID());
if (getUser1_ID() == 0)
setUser1_ID (m_doc.getUser1_ID());
// User List 2
if (m_docLine != null)
setUser2_ID (m_docLine.getUser2_ID());
if (getUser2_ID() == 0)
setUser2_ID (m_doc.getUser2_ID());
// User Defined
} // setDocumentInfo
/**
* Get Document Line
* @return doc line
*/
protected DocLine getDocLine()
{
return m_docLine;
} // getDocLine
/**
* Set Description
* @param description description
*/
public void addDescription (String description)
{
String original = getDescription();
if (original == null || original.trim().length() == 0)
super.setDescription(description);
else
super.setDescription(original + " - " + description);
} // addDescription
/**
* Set Warehouse Locator.
* - will overwrite Organization -
* @param M_Locator_ID locator
*/
public void setM_Locator_ID (int M_Locator_ID)
{
super.setM_Locator_ID (M_Locator_ID);
setAD_Org_ID(0); // reset
} // setM_Locator_ID
/**************************************************************************
* Set Location
* @param C_Location_ID location
* @param isFrom from
*/
public void setLocation (int C_Location_ID, boolean isFrom)
{
if (isFrom)
setC_LocFrom_ID (C_Location_ID);
else
setC_LocTo_ID (C_Location_ID);
} // setLocator
/**
* Set Location from Locator
* @param M_Locator_ID locator
* @param isFrom from
*/
public void setLocationFromLocator (int M_Locator_ID, boolean isFrom)
{
if (M_Locator_ID == 0)
return;
int C_Location_ID = 0;
String sql = "SELECT w.C_Location_ID FROM M_Warehouse w, M_Locator l "
+ "WHERE w.M_Warehouse_ID=l.M_Warehouse_ID AND l.M_Locator_ID=?";
try
{
PreparedStatement pstmt = DB.prepareStatement(sql, get_TrxName());
pstmt.setInt(1, M_Locator_ID);
ResultSet rs = pstmt.executeQuery();
if (rs.next())
C_Location_ID = rs.getInt(1);
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, sql, e);
return;
}
if (C_Location_ID != 0)
setLocation (C_Location_ID, isFrom);
} // setLocationFromLocator
/**
* Set Location from Busoness Partner Location
* @param C_BPartner_Location_ID bp location
* @param isFrom from
*/
public void setLocationFromBPartner (int C_BPartner_Location_ID, boolean isFrom)
{
if (C_BPartner_Location_ID == 0)
return;
int C_Location_ID = 0;
String sql = "SELECT C_Location_ID FROM C_BPartner_Location WHERE C_BPartner_Location_ID=?";
try
{
PreparedStatement pstmt = DB.prepareStatement(sql, get_TrxName());
pstmt.setInt(1, C_BPartner_Location_ID);
ResultSet rs = pstmt.executeQuery();
if (rs.next())
C_Location_ID = rs.getInt(1);
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, sql, e);
return;
}
if (C_Location_ID != 0)
setLocation (C_Location_ID, isFrom);
} // setLocationFromBPartner
/**
* Set Location from Organization
* @param AD_Org_ID org
* @param isFrom from
*/
public void setLocationFromOrg (int AD_Org_ID, boolean isFrom)
{
if (AD_Org_ID == 0)
return;
int C_Location_ID = 0;
String sql = "SELECT C_Location_ID FROM AD_OrgInfo WHERE AD_Org_ID=?";
try
{
PreparedStatement pstmt = DB.prepareStatement(sql, get_TrxName());
pstmt.setInt(1, AD_Org_ID);
ResultSet rs = pstmt.executeQuery();
if (rs.next())
C_Location_ID = rs.getInt(1);
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, sql, e);
return;
}
if (C_Location_ID != 0)
setLocation (C_Location_ID, isFrom);
} // setLocationFromOrg
/**************************************************************************
* Returns Source Balance of line
* @return source balance
*/
public BigDecimal getSourceBalance()
{
if (getAmtSourceDr() == null)
setAmtSourceDr (Env.ZERO);
if (getAmtSourceCr() == null)
setAmtSourceCr (Env.ZERO);
//
return getAmtSourceDr().subtract(getAmtSourceCr());
} // getSourceBalance
/**
* Is Debit Source Balance
* @return true if DR source balance
*/
public boolean isDrSourceBalance()
{
return getSourceBalance().signum() != -1;
} // isDrSourceBalance
/**
* Get Accounted Balance
* @return accounting balance
*/
public BigDecimal getAcctBalance()
{
if (getAmtAcctDr() == null)
setAmtAcctDr (Env.ZERO);
if (getAmtAcctCr() == null)
setAmtAcctCr (Env.ZERO);
return getAmtAcctDr().subtract(getAmtAcctCr());
} // getAcctBalance
/**
* Is Account on Balance Sheet
* @return true if account is a balance sheet account
*/
public boolean isBalanceSheet()
{
return m_acct.isBalanceSheet();
} // isBalanceSheet
/**
* Currect Accounting Amount.
* <pre>
* Example: 1 -1 1 -1
* Old 100/0 100/0 0/100 0/100
* New 99/0 101/0 0/99 0/101
* </pre>
* @param deltaAmount delta amount
*/
public void currencyCorrect (BigDecimal deltaAmount)
{
boolean negative = deltaAmount.compareTo(Env.ZERO) < 0;
boolean adjustDr = getAmtAcctDr().abs().compareTo(getAmtAcctCr().abs()) > 0;
log.fine(deltaAmount.toString()
+ "; Old-AcctDr=" + getAmtAcctDr() + ",AcctCr=" + getAmtAcctCr()
+ "; Negative=" + negative + "; AdjustDr=" + adjustDr);
if (adjustDr)
if (negative)
setAmtAcctDr (getAmtAcctDr().subtract(deltaAmount));
else
setAmtAcctDr (getAmtAcctDr().subtract(deltaAmount));
else
if (negative)
setAmtAcctCr (getAmtAcctCr().add(deltaAmount));
else
setAmtAcctCr (getAmtAcctCr().add(deltaAmount));
log.fine("New-AcctDr=" + getAmtAcctDr() + ",AcctCr=" + getAmtAcctCr());
} // currencyCorrect
/**
* Convert to Accounted Currency
* @return true if converted
*/
public boolean convert ()
{
// Document has no currency
if (getC_Currency_ID() == Doc.NO_CURRENCY)
setC_Currency_ID (m_acctSchema.getC_Currency_ID());
if (m_acctSchema.getC_Currency_ID() == getC_Currency_ID())
{
setAmtAcctDr (getAmtSourceDr());
setAmtAcctCr (getAmtSourceCr());
return true;
}
// Get Conversion Type from Line or Header
int C_ConversionType_ID = 0;
int AD_Org_ID = 0;
if (m_docLine != null) // get from line
{
C_ConversionType_ID = m_docLine.getC_ConversionType_ID();
AD_Org_ID = m_docLine.getAD_Org_ID();
}
if (C_ConversionType_ID == 0) // get from header
{
if (m_doc == null)
{
log.severe ("No Document VO");
return false;
}
C_ConversionType_ID = m_doc.getC_ConversionType_ID();
if (AD_Org_ID == 0)
AD_Org_ID = m_doc.getAD_Org_ID();
}
setAmtAcctDr (MConversionRate.convert (getCtx(),
getAmtSourceDr(), getC_Currency_ID(), m_acctSchema.getC_Currency_ID(),
getDateAcct(), C_ConversionType_ID, m_doc.getAD_Client_ID(), AD_Org_ID));
if (getAmtAcctDr() == null)
return false;
setAmtAcctCr (MConversionRate.convert (getCtx(),
getAmtSourceCr(), getC_Currency_ID(), m_acctSchema.getC_Currency_ID(),
getDateAcct(), C_ConversionType_ID, m_doc.getAD_Client_ID(), AD_Org_ID));
return true;
} // convert
/**
* Get Account
* @return account
*/
public MAccount getAccount()
{
return m_acct;
} // getAccount
/**
* To String
* @return String
*/
public String toString()
{
StringBuffer sb = new StringBuffer("FactLine=[");
sb.append(getAD_Table_ID()).append(":").append(getRecord_ID())
.append(",").append(m_acct)
.append(",Cur=").append(getC_Currency_ID())
.append(", DR=").append(getAmtSourceDr()).append("|").append(getAmtAcctDr())
.append(", CR=").append(getAmtSourceCr()).append("|").append(getAmtAcctCr())
.append("]");
return sb.toString();
} // toString
/**
* Get AD_Org_ID (balancing segment).
* (if not set directly - from document line, document, account, locator)
* <p>
* Note that Locator needs to be set before - otherwise
* segment balancing might produce the wrong results
* @return AD_Org_ID
*/
public int getAD_Org_ID()
{
if (super.getAD_Org_ID() != 0) // set earlier
return super.getAD_Org_ID();
// Prio 1 - get from locator - if exist
if (getM_Locator_ID() != 0)
{
String sql = "SELECT AD_Org_ID FROM M_Locator WHERE M_Locator_ID=? AND AD_Client_ID=?";
try
{
PreparedStatement pstmt = DB.prepareStatement(sql, get_TrxName());
pstmt.setInt(1, getM_Locator_ID());
pstmt.setInt(2, getAD_Client_ID());
ResultSet rs = pstmt.executeQuery();
if (rs.next())
{
setAD_Org_ID (rs.getInt(1));
log.finer("AD_Org_ID=" + super.getAD_Org_ID() + " (1 from M_Locator_ID=" + getM_Locator_ID() + ")");
}
else
log.log(Level.SEVERE, "AD_Org_ID - Did not find M_Locator_ID=" + getM_Locator_ID());
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, sql, e);
}
} // M_Locator_ID != 0
// Prio 2 - get from doc line - if exists (document context overwrites)
if (m_docLine != null && super.getAD_Org_ID() == 0)
{
setAD_Org_ID (m_docLine.getAD_Org_ID());
log.finer("AD_Org_ID=" + super.getAD_Org_ID() + " (2 from DocumentLine)");
}
// Prio 3 - get from doc - if not GL
if (m_doc != null && super.getAD_Org_ID() == 0)
{
if (Doc.DOCTYPE_GLJournal.equals (m_doc.getDocumentType()))
{
setAD_Org_ID (m_acct.getAD_Org_ID()); // inter-company GL
log.finer("AD_Org_ID=" + super.getAD_Org_ID() + " (3 from Acct)");
}
else
{
setAD_Org_ID (m_doc.getAD_Org_ID());
log.finer("AD_Org_ID=" + super.getAD_Org_ID() + " (3 from Document)");
}
}
// Prio 4 - get from account - if not GL
if (m_doc != null && super.getAD_Org_ID() == 0)
{
if (Doc.DOCTYPE_GLJournal.equals (m_doc.getDocumentType()))
{
setAD_Org_ID (m_doc.getAD_Org_ID());
log.finer("AD_Org_ID=" + super.getAD_Org_ID() + " (4 from Document)");
}
else
{
setAD_Org_ID (m_acct.getAD_Org_ID());
log.finer("AD_Org_ID=" + super.getAD_Org_ID() + " (4 from Acct)");
}
}
return super.getAD_Org_ID();
} // setAD_Org_ID
/**
* Get/derive Sales Region
* @return Sales Region
*/
public int getC_SalesRegion_ID ()
{
if (super.getC_SalesRegion_ID() != 0)
return super.getC_SalesRegion_ID();
//
if (m_docLine != null)
setC_SalesRegion_ID (m_docLine.getC_SalesRegion_ID());
if (m_doc != null)
{
if (super.getC_SalesRegion_ID() == 0)
setC_SalesRegion_ID (m_doc.getC_SalesRegion_ID());
if (super.getC_SalesRegion_ID() == 0 && m_doc.getBP_C_SalesRegion_ID() > 0)
setC_SalesRegion_ID (m_doc.getBP_C_SalesRegion_ID());
// derive SalesRegion if AcctSegment
if (super.getC_SalesRegion_ID() == 0
&& m_doc.getC_BPartner_Location_ID() != 0
&& m_doc.getBP_C_SalesRegion_ID() == -1) // never tried
// && m_acctSchema.isAcctSchemaElement(MAcctSchemaElement.ELEMENTTYPE_SalesRegion))
{
String sql = "SELECT COALESCE(C_SalesRegion_ID,0) FROM C_BPartner_Location WHERE C_BPartner_Location_ID=?";
setC_SalesRegion_ID (DB.getSQLValue(null,
sql, m_doc.getC_BPartner_Location_ID()));
if (super.getC_SalesRegion_ID() != 0) // save in VO
{
m_doc.setBP_C_SalesRegion_ID(super.getC_SalesRegion_ID());
log.fine("C_SalesRegion_ID=" + super.getC_SalesRegion_ID() + " (from BPL)" );
}
else // From Sales Rep of Document -> Sales Region
{
sql = "SELECT COALESCE(MAX(C_SalesRegion_ID),0) FROM C_SalesRegion WHERE SalesRep_ID=?";
setC_SalesRegion_ID (DB.getSQLValue(null,
sql, m_doc.getSalesRep_ID()));
if (super.getC_SalesRegion_ID() != 0) // save in VO
{
m_doc.setBP_C_SalesRegion_ID(super.getC_SalesRegion_ID());
log.fine("C_SalesRegion_ID=" + super.getC_SalesRegion_ID() + " (from SR)" );
}
else
m_doc.setBP_C_SalesRegion_ID(-2); // don't try again
}
}
if (m_acct != null && super.getC_SalesRegion_ID() == 0)
setC_SalesRegion_ID (m_acct.getC_SalesRegion_ID());
}
//
// log.fine("C_SalesRegion_ID=" + super.getC_SalesRegion_ID()
// + ", C_BPartner_Location_ID=" + m_docVO.C_BPartner_Location_ID
// + ", BP_C_SalesRegion_ID=" + m_docVO.BP_C_SalesRegion_ID
// + ", SR=" + m_acctSchema.isAcctSchemaElement(MAcctSchemaElement.ELEMENTTYPE_SalesRegion));
return super.getC_SalesRegion_ID();
} // getC_SalesRegion_ID
/**
* Before Save
* @param newRecord new
* @return true
*/
protected boolean beforeSave (boolean newRecord)
{
if (newRecord)
{
log.fine(toString());
//
getAD_Org_ID();
getC_SalesRegion_ID();
// Set Default Account Info
if (getM_Product_ID() == 0)
setM_Product_ID (m_acct.getM_Product_ID());
if (getC_LocFrom_ID() == 0)
setC_LocFrom_ID (m_acct.getC_LocFrom_ID());
if (getC_LocTo_ID() == 0)
setC_LocTo_ID (m_acct.getC_LocTo_ID());
if (getC_BPartner_ID() == 0)
setC_BPartner_ID (m_acct.getC_BPartner_ID());
if (getAD_OrgTrx_ID() == 0)
setAD_OrgTrx_ID (m_acct.getAD_OrgTrx_ID());
if (getC_Project_ID() == 0)
setC_Project_ID (m_acct.getC_Project_ID());
if (getC_Campaign_ID() == 0)
setC_Campaign_ID (m_acct.getC_Campaign_ID());
if (getC_Activity_ID() == 0)
setC_Activity_ID (m_acct.getC_Activity_ID());
if (getUser1_ID() == 0)
setUser1_ID (m_acct.getUser1_ID());
if (getUser2_ID() == 0)
setUser2_ID (m_acct.getUser2_ID());
// Revenue Recognition for AR Invoices
if (m_doc.getDocumentType().equals(Doc.DOCTYPE_ARInvoice)
&& m_docLine != null
&& m_docLine.getC_RevenueRecognition_ID() != 0)
{
int AD_User_ID = 0;
setAccount_ID (
createRevenueRecognition (
m_docLine.getC_RevenueRecognition_ID(), m_docLine.get_ID(),
getAD_Client_ID(), getAD_Org_ID(), AD_User_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())
);
}
}
return true;
} // beforeSave
/**************************************************************************
* Revenue Recognition.
* Called from FactLine.save
* <p>
* Create Revenue recognition plan and return Unearned Revenue account
* to be used instead of Revenue Account. If not found, it returns
* the revenue account.
*
* @param C_RevenueRecognition_ID revenue recognition
* @param C_InvoiceLine_ID invoice line
* @param AD_Client_ID client
* @param AD_Org_ID org
* @param AD_User_ID user
* @param Account_ID of Revenue Account
* @param C_SubAcct_ID sub account
* @param M_Product_ID product
* @param C_BPartner_ID bpartner
* @param AD_OrgTrx_ID trx org
* @param C_LocFrom_ID loc from
* @param C_LocTo_ID loc to
* @param C_SRegion_ID sales region
* @param C_Project_ID project
* @param C_Campaign_ID campaign
* @param C_Activity_ID activity
* @param User1_ID user1
* @param User2_ID user2
* @param UserElement1_ID user element 1
* @param UserElement2_ID user element 2
* @return Account_ID for Unearned Revenue or Revenue Account if not found
*/
private int createRevenueRecognition (
int C_RevenueRecognition_ID, int C_InvoiceLine_ID,
int AD_Client_ID, int AD_Org_ID, int AD_User_ID,
int Account_ID, int C_SubAcct_ID,
int M_Product_ID, int C_BPartner_ID, int AD_OrgTrx_ID,
int C_LocFrom_ID, int C_LocTo_ID, int C_SRegion_ID, int C_Project_ID,
int C_Campaign_ID, int C_Activity_ID,
int User1_ID, int User2_ID, int UserElement1_ID, int UserElement2_ID)
{
log.fine("From Accout_ID=" + Account_ID);
// get VC for P_Revenue (from Product)
MAccount revenue = MAccount.get(getCtx(),
AD_Client_ID, AD_Org_ID, getC_AcctSchema_ID(), Account_ID, C_SubAcct_ID,
M_Product_ID, C_BPartner_ID, AD_OrgTrx_ID, C_LocFrom_ID, C_LocTo_ID, C_SRegion_ID,
C_Project_ID, C_Campaign_ID, C_Activity_ID,
User1_ID, User2_ID, UserElement1_ID, UserElement2_ID);
if (revenue != null && revenue.get_ID() == 0)
revenue.save();
if (revenue == null || revenue.get_ID() == 0)
{
log.severe ("Revenue_Acct not found");
return Account_ID;
}
int P_Revenue_Acct = revenue.get_ID();
// get Unearned Revenue Acct from BPartner Group
int UnearnedRevenue_Acct = 0;
int new_Account_ID = 0;
String sql = "SELECT ga.UnearnedRevenue_Acct, vc.Account_ID "
+ "FROM C_BP_Group_Acct ga, C_BPartner p, C_ValidCombination vc "
+ "WHERE ga.C_BP_Group_ID=p.C_BP_Group_ID"
+ " AND ga.UnearnedRevenue_Acct=vc.C_ValidCombination_ID"
+ " AND ga.C_AcctSchema_ID=? AND p.C_BPartner_ID=?";
try
{
PreparedStatement pstmt = DB.prepareStatement(sql, get_TrxName());
pstmt.setInt(1, getC_AcctSchema_ID());
pstmt.setInt(2, C_BPartner_ID);
ResultSet rs = pstmt.executeQuery();
if (rs.next())
{
UnearnedRevenue_Acct = rs.getInt(1);
new_Account_ID = rs.getInt(2);
}
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, sql, e);
}
if (new_Account_ID == 0)
{
log.severe ("UnearnedRevenue_Acct not found");
return Account_ID;
}
MRevenueRecognitionPlan plan = new MRevenueRecognitionPlan(getCtx(), 0, null);
plan.setC_RevenueRecognition_ID (C_RevenueRecognition_ID);
plan.setC_AcctSchema_ID (getC_AcctSchema_ID());
plan.setC_InvoiceLine_ID (C_InvoiceLine_ID);
plan.setUnEarnedRevenue_Acct (UnearnedRevenue_Acct);
plan.setP_Revenue_Acct (P_Revenue_Acct);
plan.setC_Currency_ID (getC_Currency_ID());
plan.setTotalAmt (getAcctBalance());
if (!plan.save(get_TrxName()))
{
log.severe ("Plan NOT created");
return Account_ID;
}
log.fine("From Acctount_ID=" + Account_ID + " to " + new_Account_ID
+ " - Plan from UnearnedRevenue_Acct=" + UnearnedRevenue_Acct + " to Revenue_Acct=" + P_Revenue_Acct);
return new_Account_ID;
} // createRevenueRecognition
/**************************************************************************
* Update Line with reversed Original Amount in Accounting Currency.
* Also copies original dimensions like Project, etc.
* Called from Doc_MatchInv
* @param AD_Table_ID table
* @param Record_ID record
* @param Line_ID line
* @param multiplier targetQty/documentQty
* @return true if success
*/
public boolean updateReverseLine (int AD_Table_ID, int Record_ID, int Line_ID,
BigDecimal multiplier)
{
boolean success = false;
String sql = "SELECT * "
+ "FROM Fact_Acct "
+ "WHERE C_AcctSchema_ID=? AND AD_Table_ID=? AND Record_ID=?"
+ " AND Line_ID=? AND Account_ID=?";
try
{
PreparedStatement pstmt = DB.prepareStatement(sql, get_TrxName());
pstmt.setInt(1, getC_AcctSchema_ID());
pstmt.setInt(2, AD_Table_ID);
pstmt.setInt(3, Record_ID);
pstmt.setInt(4, Line_ID);
pstmt.setInt(5, m_acct.getAccount_ID());
ResultSet rs = pstmt.executeQuery();
if (rs.next())
{
MFactAcct fact = new MFactAcct(getCtx(), rs, get_TrxName());
// Accounted Amounts - reverse
BigDecimal dr = fact.getAmtAcctDr();
BigDecimal cr = fact.getAmtAcctCr();
setAmtAcctDr (cr.multiply(multiplier));
setAmtAcctCr (dr.multiply(multiplier));
// Source Amounts
setAmtSourceDr (getAmtAcctDr());
setAmtSourceCr (getAmtAcctCr());
//
success = true;
log.fine(new StringBuffer("(Table=").append(AD_Table_ID)
.append(",Record_ID=").append(Record_ID)
.append(",Line=").append(Record_ID)
.append(", Account=").append(m_acct)
.append(",dr=").append(dr).append(",cr=").append(cr)
.append(") - DR=").append(getAmtSourceDr()).append("|").append(getAmtAcctDr())
.append(", CR=").append(getAmtSourceCr()).append("|").append(getAmtAcctCr())
.toString());
// Dimensions
setAD_OrgTrx_ID(fact.getAD_OrgTrx_ID());
setC_Project_ID (fact.getC_Project_ID());
setC_Activity_ID(fact.getC_Activity_ID());
setC_Campaign_ID(fact.getC_Campaign_ID());
setC_SalesRegion_ID(fact.getC_SalesRegion_ID());
setC_LocFrom_ID(fact.getC_LocFrom_ID());
setC_LocTo_ID(fact.getC_LocTo_ID());
setM_Product_ID(fact.getM_Product_ID());
setM_Locator_ID(fact.getM_Locator_ID());
setUser1_ID(fact.getUser1_ID());
setUser2_ID(fact.getUser2_ID());
setC_UOM_ID(fact.getC_UOM_ID());
setC_Tax_ID(fact.getC_Tax_ID());
// Org for cross charge
setAD_Org_ID (fact.getAD_Org_ID());
}
else
log.warning(new StringBuffer("Not Found (try later) ")
.append(",C_AcctSchema_ID=").append(getC_AcctSchema_ID())
.append(", AD_Table_ID=").append(AD_Table_ID)
.append(",Record_ID=").append(Record_ID)
.append(",Line_ID=").append(Line_ID)
.append(", Account_ID=").append(m_acct.getAccount_ID()).toString());
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, sql, e);
}
return success;
} // updateReverseLine
} // FactLine

View File

@ -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.acct;
import java.math.*;
import java.sql.*;
import java.util.logging.*;
import org.compiere.util.*;
/**
* Automatic Matching.
* Inv
*
* @author Jorg Janke
* @version $Id: Matcher.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $
*/
public class Matcher
{
/**
* Constructor
* @param AD_Client_ID Client
* @param trxName transaction
*/
public Matcher (int AD_Client_ID, String trxName)
{
m_AD_Client_ID = AD_Client_ID;
m_trxName = trxName;
} // Matcher
/** Client */
private int m_AD_Client_ID;
/** Transaction */
private String m_trxName = null;
/** Logger */
protected CLogger log = CLogger.getCLogger (getClass());
/**
* Matching
* <pre>
* Derive Invoice-Receipt Match from PO-Invoice and PO-Receipt
* Purchase Order (20)
* - Invoice1 (10)
* - Invoice2 (10)
* - Receipt1 (5)
* - Receipt2 (15)
*
* (a) Creates Directs
* - Invoice1 - Receipt1 (5)
* - Invoice2 - Receipt2 (10)
*
* (b) Creates Indirects
* - Invoice1 - Receipt2 (5)
* (Not imlemented)
*
*
* </pre>
* @return number of records created
*/
public int match()
{
int counter = 0;
// (a) Direct Matches
String sql = "SELECT m1.AD_Client_ID,m2.AD_Org_ID, " // 1..2
+ "m1.C_InvoiceLine_ID,m2.M_InOutLine_ID,m1.M_Product_ID, " // 3..5
+ "m1.DateTrx,m2.DateTrx, m1.Qty, m2.Qty " // 6..9
+ "FROM M_MatchPO m1, M_MatchPO m2 "
+ "WHERE m1.C_OrderLine_ID=m2.C_OrderLine_ID"
+ " AND m1.M_InOutLine_ID IS NULL"
+ " AND m2.C_InvoiceLine_ID IS NULL"
+ " AND m1.M_Product_ID=m2.M_Product_ID"
+ " AND m1.AD_Client_ID=?" // #1
// Not existing Inv Matches
+ " AND NOT EXISTS (SELECT * FROM M_MatchInv mi "
+ "WHERE mi.C_InvoiceLine_ID=m1.C_InvoiceLine_ID AND mi.M_InOutLine_ID=m2.M_InOutLine_ID)";
try
{
PreparedStatement pstmt = DB.prepareStatement(sql, null);
pstmt.setInt(1, m_AD_Client_ID);
ResultSet rs = pstmt.executeQuery();
while (rs.next())
{
BigDecimal qty1 = rs.getBigDecimal(8);
BigDecimal qty2 = rs.getBigDecimal(9);
BigDecimal Qty = qty1.min(qty2);
if (Qty.equals(Env.ZERO))
continue;
Timestamp dateTrx1 = rs.getTimestamp(6);
Timestamp dateTrx2 = rs.getTimestamp(7);
Timestamp DateTrx = dateTrx1;
if (dateTrx1.before(dateTrx2))
DateTrx = dateTrx2;
//
int AD_Client_ID = rs.getInt(1);
int AD_Org_ID = rs.getInt(2);
int C_InvoiceLine_ID = rs.getInt(3);
int M_InOutLine_ID = rs.getInt(4);
int M_Product_ID = rs.getInt(5);
//
if (createMatchInv(AD_Client_ID, AD_Org_ID,
M_InOutLine_ID, C_InvoiceLine_ID,
M_Product_ID, DateTrx, Qty))
counter++;
}
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, "match", e);
}
log.fine("Matcher.match - Client_ID=" + m_AD_Client_ID
+ ", Records created=" + counter);
return counter;
} // match
/**
* Create MatchInv record
* @param AD_Client_ID Client
* @param AD_Org_ID Org
* @param M_InOutLine_ID Receipt
* @param C_InvoiceLine_ID Invoice
* @param M_Product_ID Product
* @param DateTrx Date
* @param Qty Qty
* @return true if record created
*/
private boolean createMatchInv (int AD_Client_ID, int AD_Org_ID,
int M_InOutLine_ID, int C_InvoiceLine_ID,
int M_Product_ID, Timestamp DateTrx, BigDecimal Qty)
{
log.fine("InvLine=" + C_InvoiceLine_ID + ",Rec=" + M_InOutLine_ID + ", Qty=" + Qty + ", " + DateTrx);
// MMatchInv inv = new MMatchInv ();
int M_MatchInv_ID = DB.getNextID (AD_Client_ID, "M_MatchInv", m_trxName);
//
StringBuffer sql = new StringBuffer("INSERT INTO M_MatchInv ("
+ "M_MatchInv_ID, "
+ "AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy, "
+ "M_InOutLine_ID,C_InvoiceLine_ID, "
+ "M_Product_ID,DateTrx,Qty, "
+ "Processing,Processed,Posted) VALUES (")
.append(M_MatchInv_ID).append(", ")
.append(AD_Client_ID).append(",").append(AD_Org_ID).append(",'Y',SysDate,0,SysDate,0, ")
.append(M_InOutLine_ID).append(",").append(C_InvoiceLine_ID).append(", ")
.append(M_Product_ID).append(",").append(DB.TO_DATE(DateTrx,true)).append(",").append(Qty)
.append(", 'N','Y','N')");
int no = DB.executeUpdate(sql.toString(), m_trxName);
return no == 1;
} // createMatchInv
} // Matcher

View File

@ -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.acct;
import java.math.*;
import java.sql.*;
import java.util.logging.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Product Costing Information.
*
* @author Jorg Janke
* @version $Id: ProductInfo.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $
*/
public class ProductInfo
{
/**
* Constructor
* @param M_Product_ID Product
* @param trxName transcation
*/
public ProductInfo (int M_Product_ID, String trxName)
{
m_trxName = trxName;
init (M_Product_ID);
} // ProductInfo
/** The Product Key */
private int m_M_Product_ID = 0;
/** Transaction */
private String m_trxName = null;
// Product Info
private int m_AD_Client_ID = 0;
private int m_AD_Org_ID = 0;
private String m_productType = null;
private String m_ProductCategory = null;
private boolean m_isBOM = false;
private boolean m_isStocked = true;
private int m_C_RevenueRecognition_ID = 0;
private int m_C_UOM_ID = 0;
private BigDecimal m_qty = Env.ZERO;
/** Logger */
protected CLogger log = CLogger.getCLogger (getClass());
/**
* Get Product Info (Service, Revenue Recognition).
* automatically called by constructor
* @param M_Product_ID Product
*/
private void init (int M_Product_ID)
{
m_M_Product_ID = M_Product_ID;
if (m_M_Product_ID == 0)
return;
String sql = "SELECT p.ProductType, pc.Value, " // 1..2
+ "p.C_RevenueRecognition_ID,p.C_UOM_ID, " // 3..4
+ "p.AD_Client_ID,p.AD_Org_ID, " // 5..6
+ "p.IsBOM, p.IsStocked " // 7..8
+ "FROM M_Product_Category pc"
+ " INNER JOIN M_Product p ON (pc.M_Product_Category_ID=p.M_Product_Category_ID) "
+ "WHERE p.M_Product_ID=?"; // #1
try
{
PreparedStatement pstmt = DB.prepareStatement(sql, null);
pstmt.setInt(1, m_M_Product_ID);
ResultSet rs = pstmt.executeQuery();
if (rs.next())
{
m_productType = rs.getString(1);
m_ProductCategory = rs.getString(2);
m_C_RevenueRecognition_ID = rs.getInt(3);
m_C_UOM_ID = rs.getInt(4);
// reference
m_AD_Client_ID = rs.getInt(5);
m_AD_Org_ID = rs.getInt(6);
//
m_isBOM = "Y".equals(rs.getString(7));
m_isStocked = "Y".equals(rs.getString(8));
}
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, sql, e);
}
} // init
/**
* Is Product/Item
* @return true if product
*/
public boolean isProduct()
{
return MProduct.PRODUCTTYPE_Item.equals(m_productType);
} // isProduct
/**
* Is it a BOM
* @return true if BOM
*/
public boolean isBOM()
{
return m_isBOM;
} // isBOM
/**
* Is it stocked
* @return true if stocked
*/
public boolean isStocked()
{
return m_isStocked;
} // isStocked
/**
* Is Service
* @return true if service
*/
public boolean isService()
{
return MProduct.PRODUCTTYPE_Service.equals(m_productType);
} // isService
/**
* Get Product Category (Value)
* @return M_Product_Category_ID
*/
public String getProductCategory()
{
return m_ProductCategory;
} // getProductCategory
/**
* Has Revenue Recognition
* @return true if product/service has revenue recognition
*/
public boolean isRevenueRecognition()
{
return m_C_RevenueRecognition_ID != 0;
} // isRevenueRecognition
/**
* Get Revenue Recognition
* @return C_RevenueRecognition_ID
*/
public int getC_RevenueRecognition_ID()
{
return m_C_RevenueRecognition_ID;
} // getC_RevenueRecognition_ID
/**
* Quantity UOM
* @return C_UOM_ID
*/
public int getC_UOM_ID()
{
return m_C_UOM_ID;
} // getC_UOM_ID
/*************************************************************************/
/**
* 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;
}
} // setQty
/**
* Get Qty in Storage UOM
* @return qty
*/
public BigDecimal getQty()
{
return m_qty;
} // getQty
/**
* 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 updateCosts (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(m_AD_Client_ID).append(",").append(m_AD_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(), m_AD_Client_ID, m_AD_Org_ID);
return cost;
} // getPOCost
} // ProductInfo

View File

@ -0,0 +1,118 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or modify it
* under the terms version 2 of the GNU General Public License as published
* by the Free Software Foundation. This program is distributed in the hope
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public 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.ldap;
import java.io.*;
import java.net.*;
import java.util.logging.*;
import org.compiere.ldap.*;
import org.compiere.util.*;
import com.sun.jndi.ldap.*;
/**
* LDAP Connection Handler
*
* @author Jorg Janke
* @version $Id: LdapConnectionHandler.java,v 1.1 2006/10/09 00:23:16 jjanke Exp $
*/
public class LdapConnectionHandler extends Thread
{
/**
* Ldap Connection Handler
* @param socket server socket
*/
public LdapConnectionHandler(Socket socket)
{
try
{
m_socket = socket;
m_socket.setTcpNoDelay(true); // should not be required
}
catch (Exception e)
{
log.log(Level.SEVERE, "", e);
} // no timeout
} // LdapConnectionHandler
/** Socket */
private Socket m_socket = null;
/** Logger */
private static CLogger log = CLogger.getCLogger (LdapConnectionHandler.class);
/**
* Do Work
*/
public void run()
{
try
{
if (m_socket == null || m_socket.isClosed())
return;
boolean activeSession = true;
while (activeSession)
{
InputStream in = m_socket.getInputStream();
BufferedOutputStream out = new BufferedOutputStream(m_socket.getOutputStream());
// Read
byte[] buffer = new byte[512];
int length = in.read(buffer, 0, 512);
LdapMessage msg = new LdapMessage (buffer, length);
if (msg.getOperation() == LdapMessage.UNBIND_REQUEST)
{
activeSession = false;
out.close();
}
else
{
LdapResult result = new LdapResult ();
byte[] bytes = result.bindResponse();
//
out.write(bytes);
out.flush();
}
}
}
catch (IOException e)
{
log.log(Level.SEVERE, "", e);
}
try
{
m_socket.close();
}
catch (Exception e)
{
log.log(Level.WARNING, "Socket", e);
}
m_socket = null;
} // run
/**
* String Representation
* @return info
*/
public String toString()
{
StringBuffer sb = new StringBuffer ("LdapConnectionHandler[");
sb.append (hashCode()).append ("]");
return sb.toString ();
} // toString
} // LdapConnectionHandler

View File

@ -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.
* 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.ldap;
import java.util.logging.*;
import org.compiere.util.*;
import com.sun.jndi.ldap.*;
/**
* Ldap Message
*
* @author Jorg Janke
* @version $Id: LdapMessage.java,v 1.1 2006/10/09 00:23:16 jjanke Exp $
*/
public class LdapMessage
{
/**
* Ldap Message
* @param data BER data
* @param length Ber data length
*/
public LdapMessage (byte[] data, int length)
{
try
{
decode(data, length);
}
catch (Exception e)
{
log.log(Level.SEVERE, data.toString(), e);
}
} // LdapMessage
/**
LDAPMessage ::= SEQUENCE {
messageID MessageID,
protocolOp CHOICE {
bindRequest BindRequest,
bindResponse BindResponse,
unbindRequest UnbindRequest,
searchRequest SearchRequest,
searchResEntry SearchResultEntry,
searchResDone SearchResultDone,
searchResRef SearchResultReference,
modifyRequest ModifyRequest,
modifyResponse ModifyResponse,
addRequest AddRequest,
addResponse AddResponse,
delRequest DelRequest,
delResponse DelResponse,
modDNRequest ModifyDNRequest,
modDNResponse ModifyDNResponse,
compareRequest CompareRequest,
compareResponse CompareResponse,
abandonRequest AbandonRequest,
extendedReq ExtendedRequest,
extendedResp ExtendedResponse },
controls [0] Controls OPTIONAL }
**/
static public final int BIND_REQUEST = 0;
static public final int BIND_RESPONSE = 1;
static public final int UNBIND_REQUEST = 2;
static public final int SEARCH_REQUEST = 3;
static public final int SEARCH_RESENTRY = 4;
static public final int SEARCH_RESDONE = 5;
static public final int MODIFY_REQUEST = 6;
static public final int MODIFY_RESPONSE = 7;
static public final int ADD_REQUEST = 8;
static public final int ADD_RESPONSE = 9;
static public final int DEL_REQUEST = 10;
static public final int DEL_RESPONSE = 11;
static public final int MODDN_REQUEST = 12;
static public final int MODDN_RESPONSE = 13;
static public final int COMPARE_REQUEST = 14;
static public final int COMPARE_RESPONSE = 15;
static public final int ABANDON_REQUEST = 16;
static public final int EXTENDED_REQUEST = 17;
static public final int EXTENDED_RESPONSE = 18;
static public final int[] PROTOCOL_OP = {
BIND_REQUEST, BIND_RESPONSE, UNBIND_REQUEST,
SEARCH_REQUEST, SEARCH_RESENTRY, SEARCH_RESDONE,
MODIFY_REQUEST, MODIFY_RESPONSE, ADD_REQUEST, ADD_RESPONSE,
DEL_REQUEST, DEL_RESPONSE, MODDN_REQUEST, MODDN_RESPONSE,
COMPARE_REQUEST, COMPARE_RESPONSE, ABANDON_REQUEST,
EXTENDED_REQUEST, EXTENDED_RESPONSE};
/** Logger */
private static CLogger log = CLogger.getCLogger (LdapMessage.class);
/** Protocol Operation */
private int m_protocolOp = -1;
/**
* Decode Message
* @param data data
* @param length length
* @throws Exception
*/
private void decode (byte[] data, int length) throws Exception
{
BerDecoder decoder = new BerDecoder(data, 0, length);
int left = decoder.bytesLeft();
int pos = decoder.getParsePosition();
//
int seq = decoder.parseSeq(null);
left = decoder.bytesLeft();
pos = decoder.getParsePosition();
//
int messageID = decoder.parseInt();
left = decoder.bytesLeft();
pos = decoder.getParsePosition();
//
int peek = decoder.peekByte();
m_protocolOp = decoder.parseSeq(PROTOCOL_OP);
m_protocolOp -= Ber.ASN_APPLICATION;
if (m_protocolOp - Ber.ASN_CONSTRUCTOR >= 0)
m_protocolOp -= Ber.ASN_CONSTRUCTOR;
left = decoder.bytesLeft();
pos = decoder.getParsePosition();
//
// Payload
if (m_protocolOp == BIND_REQUEST)
{
int version = decoder.parseInt();
left = decoder.bytesLeft();
pos = decoder.getParsePosition();
//
byte[] dn = decoder.parseOctetString(Ber.ASN_OCTET_STR, null);
left = decoder.bytesLeft();
pos = decoder.getParsePosition();
//
byte[] authentification = decoder.parseOctetString(Ber.ASN_CONTEXT, null);
left = decoder.bytesLeft();
pos = decoder.getParsePosition();
//
log.info("#" + messageID + ": bind - version=" + version + ", dn=" + new String(dn)
+ ", auth=" + new String (authentification));
}
else if (m_protocolOp == UNBIND_REQUEST)
log.info("#" + messageID + ": unbind");
else
{
log.warning("#" + messageID + ": Unknown Op + " + m_protocolOp);
}
} // decode
/**
* Get Operation Code
* @return protocolOp
*/
public int getOperation()
{
return m_protocolOp;
} // getOperation
} // LdapMessage

View File

@ -0,0 +1,141 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or modify it
* under the terms version 2 of the GNU General Public License as published
* by the Free Software Foundation. This program is distributed in the hope
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public 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.ldap;
import java.net.*;
import java.sql.*;
import java.util.*;
import java.util.logging.*;
import javax.naming.ldap.*;
import org.compiere.*;
import org.compiere.ldap.*;
import org.compiere.model.*;
import org.compiere.server.*;
import org.compiere.util.*;
/**
* LDAP Server
*
* @author Jorg Janke
* @version $Id: LdapProcessor.java,v 1.1 2006/10/09 00:23:16 jjanke Exp $
*/
public class LdapProcessor extends AdempiereServer
{
/**
* Ldap Processor (Server)
* @param model Ldap Model
*/
public LdapProcessor (LdapProcessorModel model)
{
super (model, 300);
m_model = model;
init();
} // LdapProcessor
/** The Concrete Model */
private LdapProcessorModel m_model = null;
/** Last Summary */
private StringBuffer m_summary = new StringBuffer();
/** Client info */
private MClient m_client = null;
/** Server Socket */
private ServerSocket m_serverSocket = null;
/** Counter */
private int m_counter = 0;
/**
* Do Work
*/
protected void doWork()
{
// Close Socket
if (m_serverSocket != null)
{
try
{
m_serverSocket.close();
}
catch (Exception e)
{
}
}
m_counter = 0;
//
m_summary = new StringBuffer(m_model.toString())
.append(" - ");
//
try
{
m_serverSocket = new ServerSocket(m_model.getLdapPort());
log.log(Level.INFO, "Opened Port=" + m_model.getLdapPort());
while (!isInterrupted())
{
Socket socket = m_serverSocket.accept(); // waits for connection
log.log(Level.FINE, "Connection on Port=" + m_model.getLdapPort());
LdapConnectionHandler handler = new LdapConnectionHandler (socket);
handler.start();
m_counter++;
}
}
catch (Exception e)
{
log.log(Level.WARNING, "Port=" + m_model.getLdapPort(), e);
m_summary.append(e.toString());
}
} // doWork
/**
* Initialize
*/
private void init()
{
try
{
InitialLdapContext lctx = new InitialLdapContext();
// lctx.setRequestControls(critModCtls);
// lctx.modifyAttributes(name, mods);
Control[] respCtls = lctx.getResponseControls();
}
catch (Exception e)
{
}
} //
/**
* Get Server Info
* @return info
*/
public String getServerInfo()
{
return "#" + p_runCount + " - Last=" + m_summary.toString()
+ "; Counter=" + m_counter;
} // getServerInfo
/**
* Test
* @param args
*/
public static void main(String[] args)
{
Adempiere.startup(true);
new LdapProcessor(new LdapProcessorModel(new Properties())).doWork();
} // main
} // LdapProcessor

View File

@ -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.
* 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.ldap;
import java.sql.*;
import java.util.*;
import org.compiere.model.*;
/**
* Interim LDAP Server Model
*
* @author Jorg Janke
* @version $Id: LdapProcessorModel.java,v 1.1 2006/10/09 00:23:16 jjanke Exp $
*/
public class LdapProcessorModel implements AdempiereProcessor
{
/**
* Ldap Processor Model
* @param ctx context
*/
public LdapProcessorModel (Properties ctx)
{
m_ctx = ctx;
}
// Properties
private Properties m_ctx = null;
private Timestamp m_dateNextRun;
private Timestamp m_dateLastRun;
public int getLdapPort()
{
return 389;
}
/**
* String Representation
* @return info
*/
public String toString()
{
StringBuffer sb = new StringBuffer (getName());
sb.append (";Port=").append (getLdapPort());
return sb.toString ();
} // toString
/**************************************************************************
* getAD_Client_ID
* @see org.compiere.model.AdempiereProcessor#getAD_Client_ID()
* @return 0
*/
public int getAD_Client_ID()
{
return 0;
}
/**
* getName
* @see org.compiere.model.AdempiereProcessor#getName()
* @return name
*/
public String getName()
{
return "Adempiere LDAP Server";
}
/**
* getDescription
* @see org.compiere.model.AdempiereProcessor#getDescription()
* @return -
*/
public String getDescription()
{
return "-";
}
/**
* Get Ctx
* @return context
*/
public Properties getCtx()
{
return m_ctx;
}
/**
* GetFrequencyType
* @see org.compiere.model.AdempiereProcessor#getFrequencyType()
* @return min
*/
public String getFrequencyType()
{
return MRequestProcessor.FREQUENCYTYPE_Minute;
}
/**
* getFrequency
* @see org.compiere.model.AdempiereProcessor#getFrequency()
* @return 1
*/
public int getFrequency()
{
return 1;
}
/**
* Get Unique Server ID
* @return id
*/
public String getServerID()
{
return "Ldap";
}
public Timestamp getDateNextRun(boolean requery)
{
return m_dateNextRun;
}
public void setDateNextRun(Timestamp dateNextWork)
{
m_dateNextRun = dateNextWork;
}
public Timestamp getDateLastRun()
{
return m_dateLastRun;
}
public void setDateLastRun(Timestamp dateLastRun)
{
m_dateLastRun = dateLastRun;
}
public boolean save()
{
return true;
}
public AdempiereProcessorLog[] getLogs()
{
return new AdempiereProcessorLog[0];
}
}

View File

@ -0,0 +1,147 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or modify it
* under the terms version 2 of the GNU General Public License as published
* by the Free Software Foundation. This program is distributed in the hope
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public 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.ldap;
import java.io.*;
import java.util.logging.*;
import org.compiere.util.*;
import com.sun.jndi.ldap.*;
/**
* Ldap Wire Response
*
* @author Jorg Janke
* @version $Id: LdapResult.java,v 1.1 2006/10/09 00:23:16 jjanke Exp $
*/
public class LdapResult
{
public LdapResult()
{
super ();
} // LdapResult
/**
LDAPResult ::= SEQUENCE {
resultCode ENUMERATED {
success (0),
operationsError (1),
protocolError (2),
timeLimitExceeded (3),
sizeLimitExceeded (4),
compareFalse (5),
compareTrue (6),
authMethodNotSupported (7),
strongAuthRequired (8),
-- 9 reserved --
referral (10), -- new
adminLimitExceeded (11), -- new
unavailableCriticalExtension (12), -- new
confidentialityRequired (13), -- new
saslBindInProgress (14), -- new
noSuchAttribute (16),
undefinedAttributeType (17),
inappropriateMatching (18),
constraintViolation (19),
attributeOrValueExists (20),
invalidAttributeSyntax (21),
noSuchObject (32),
aliasProblem (33),
invalidDNSyntax (34),
-- 35 reserved for undefined isLeaf --
aliasDereferencingProblem (36),
-- 37-47 unused --
inappropriateAuthentication (48),
invalidCredentials (49),
insufficientAccessRights (50),
busy (51),
unavailable (52),
unwillingToPerform (53),
loopDetect (54),
-- 55-63 unused --
namingViolation (64),
objectClassViolation (65),
notAllowedOnNonLeaf (66),
notAllowedOnRDN (67),
entryAlreadyExists (68),
objectClassModsProhibited (69),
-- 70 reserved for CLDAP --
affectsMultipleDSAs (71), -- new
-- 72-79 unused --
other (80) },
-- 81-90 reserved for APIs --
matchedDN LDAPDN,
errorMessage LDAPString,
referral [3] Referral OPTIONAL }
**/
/** Encoder */
private BerEncoder m_encoder = new BerEncoder();
/** Logger */
private static CLogger log = CLogger.getCLogger (LdapResult.class);
/**
* Bind Response
* @return reponse
*/
public byte[] bindResponse()
{
try
{
/**
m_encoder.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
for (int i = 0; i < sortKeys.length; i++) {
ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
ber.encodeString(sortKeys[i].getAttributeID(), true); // v3
if ((matchingRule = sortKeys[i].getMatchingRuleID()) != null) {
ber.encodeString(matchingRule, (Ber.ASN_CONTEXT | 0), true);
}
if (! sortKeys[i].isAscending()) {
ber.encodeBoolean(true, (Ber.ASN_CONTEXT | 1));
}
ber.endSeq();
}
*/
// payload
m_encoder.beginSeq(Ber.ASN_APPLICATION | LdapMessage.BIND_RESPONSE);
// Response
m_encoder.encodeInt(0); // success
m_encoder.encodeOctetString("cn=testCN".getBytes(), 0); // matched DN
m_encoder.encodeOctetString("".getBytes(), 0); // error mag
// referral
// sasl
//
m_encoder.endSeq();
log.info("Success");
}
catch (Exception e)
{
log.log(Level.SEVERE, "", e);
}
return getResult();
} // bindResponse
/**
* Get BER Result as byte array
* @return byte array
*/
public byte[] getResult()
{
return m_encoder.getTrimmedBuf();
} // getResult
} // LdapResult

View File

@ -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.server;
import java.sql.*;
import java.util.logging.*;
import org.compiere.acct.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Accounting Processor
*
* @author Jorg Janke
* @version $Id: AcctProcessor.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class AcctProcessor extends AdempiereServer
{
/**
* Accounting Processor
* @param model model
*/
public AcctProcessor (MAcctProcessor model)
{
super (model, 30); // 30 seconds delay
m_model = model;
m_client = MClient.get(model.getCtx(), model.getAD_Client_ID());
} // AcctProcessor
/** The Concrete Model */
private MAcctProcessor m_model = null;
/** Last Summary */
private StringBuffer m_summary = new StringBuffer();
/** Client onfo */
private MClient m_client = null;
/** Accounting Schemata */
private MAcctSchema[] m_ass = null;
/**
* Work
*/
protected void doWork ()
{
m_summary = new StringBuffer();
// Get Schemata
if (m_model.getC_AcctSchema_ID() == 0)
m_ass = MAcctSchema.getClientAcctSchema(getCtx(), m_model.getAD_Client_ID());
else // only specific accounting schema
m_ass = new MAcctSchema[] {new MAcctSchema (getCtx(), m_model.getC_AcctSchema_ID(), null)};
//
postSession();
MCost.create(m_client);
//
int no = m_model.deleteLog();
m_summary.append("Logs deleted=").append(no);
//
MAcctProcessorLog pLog = new MAcctProcessorLog(m_model, m_summary.toString());
pLog.setReference("#" + String.valueOf(p_runCount)
+ " - " + TimeUtil.formatElapsed(new Timestamp(p_startWork)));
pLog.save();
} // doWork
/**
* Post Session
*/
private void postSession()
{
for (int i = 0; i < Doc.documentsTableID.length; i++)
{
int AD_Table_ID = Doc.documentsTableID[i];
String TableName = Doc.documentsTableName[i];
// Post only special documents
if (m_model.getAD_Table_ID() != 0
&& m_model.getAD_Table_ID() != AD_Table_ID)
continue;
// SELECT * FROM table
StringBuffer sql = new StringBuffer ("SELECT * FROM ").append(TableName)
.append(" WHERE AD_Client_ID=?")
.append(" AND Processed='Y' AND Posted='N' AND IsActive='Y'")
.append(" ORDER BY Created");
//
int count = 0;
int countError = 0;
PreparedStatement pstmt = null;
try
{
pstmt = DB.prepareStatement(sql.toString(), null);
pstmt.setInt(1, m_model.getAD_Client_ID());
ResultSet rs = pstmt.executeQuery();
while (!isInterrupted() && rs.next())
{
count++;
boolean ok = true;
try
{
Doc doc = Doc.get (m_ass, AD_Table_ID, rs, null);
if (doc == null)
{
log.severe(getName() + ": No Doc for " + TableName);
ok = false;
}
else
{
String error = doc.post(false, false); // post no force/repost
ok = error == null;
}
}
catch (Exception e)
{
log.log(Level.SEVERE, getName() + ": " + TableName, e);
ok = false;
}
if (!ok)
countError++;
}
rs.close();
pstmt.close();
pstmt = null;
}
catch (Exception e)
{
log.log(Level.SEVERE, sql.toString(), e);
}
if (pstmt != null)
{
try
{
pstmt.close();
}
catch (Exception e)
{
}
}
//
if (count > 0)
{
m_summary.append(TableName).append("=").append(count);
if (countError > 0)
m_summary.append("(Errors=").append(countError).append(")");
m_summary.append(" - ");
log.finer(getName() + ": " + m_summary.toString());
}
else
log.finer(getName() + ": " + TableName + " - no work");
}
} // postSession
/**
* Get Server Info
* @return info
*/
public String getServerInfo()
{
return "#" + p_runCount + " - Last=" + m_summary.toString();
} // getServerInfo
} // AcctProcessor

View File

@ -0,0 +1,388 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.server;
import java.sql.*;
import java.util.*;
import java.util.logging.*;
import org.compiere.ldap.*;
import org.compiere.model.*;
import org.compiere.util.*;
import org.compiere.wf.*;
/**
* Adempiere Server Base
*
* @author Jorg Janke
* @version $Id: AdempiereServer.java,v 1.3 2006/10/09 00:23:26 jjanke Exp $
*/
public abstract class AdempiereServer extends Thread
{
/**
* Create New Server Thead
* @param model model
* @return server tread or null
*/
public static AdempiereServer create (AdempiereProcessor model)
{
if (model instanceof MRequestProcessor)
return new RequestProcessor ((MRequestProcessor)model);
if (model instanceof MWorkflowProcessor)
return new WorkflowProcessor ((MWorkflowProcessor)model);
if (model instanceof MAcctProcessor)
return new AcctProcessor ((MAcctProcessor)model);
if (model instanceof MAlertProcessor)
return new AlertProcessor ((MAlertProcessor)model);
if (model instanceof MScheduler)
return new Scheduler ((MScheduler)model);
if (model instanceof LdapProcessorModel)
return new LdapProcessor((LdapProcessorModel)model);
//
throw new IllegalArgumentException("Unknown Processor");
} // create
/**************************************************************************
* Server Base Class
* @param model model
* @param initialNap delay time running in sec
*/
protected AdempiereServer (AdempiereProcessor model, int initialNap)
{
super (AdempiereServerGroup.get(), null, model.getName(), 0);
p_model = model;
m_ctx = new Properties(model.getCtx());
if (p_system == null)
p_system = MSystem.get(m_ctx);
p_client = MClient.get(m_ctx);
Env.setContext(m_ctx, "#AD_Client_ID", p_client.getAD_Client_ID());
m_initialNap = initialNap;
// log.info(model.getName() + " - " + getThreadGroup());
} // ServerBase
/** The Processor Model */
protected AdempiereProcessor p_model;
/** Initial nap is seconds */
private int m_initialNap = 0;
/** Miliseconds to sleep - 10 Min default */
private long m_sleepMS = 600000;
/** Sleeping */
private volatile boolean m_sleeping = false;
/** Server start time */
private long m_start = 0;
/** Number of Work executions */
protected int p_runCount = 0;
/** Tine start of work */
protected long p_startWork = 0;
/** Number MS of last Run */
private long m_runLastMS = 0;
/** Number of MS total */
private long m_runTotalMS = 0;
/** When to run next */
private long m_nextWork = 0;
/** Logger */
protected CLogger log = CLogger.getCLogger(getClass());
/** Context */
private Properties m_ctx = null;
/** System */
protected static MSystem p_system = null;
/** Client */
protected MClient p_client = null;
/**
* Get Server Context
* @return context
*/
public Properties getCtx()
{
return m_ctx;
} // getCtx
/**
* @return Returns the sleepMS.
*/
public long getSleepMS ()
{
return m_sleepMS;
} // getSleepMS
/**
* Sleep for set time
* @return true if not interrupted
*/
public boolean sleep()
{
if (isInterrupted())
{
log.info (getName() + ": interrupted");
return false;
}
log.fine(getName() + ": sleeping " + TimeUtil.formatElapsed(m_sleepMS));
m_sleeping = true;
try
{
sleep (m_sleepMS);
}
catch (InterruptedException e)
{
log.info (getName() + ": interrupted");
m_sleeping = false;
return false;
}
m_sleeping = false;
return true;
} // sleep
/**
* Run Now
*/
public void runNow()
{
log.info(getName());
p_startWork = System.currentTimeMillis();
doWork();
long now = System.currentTimeMillis();
// ---------------
p_runCount++;
m_runLastMS = now - p_startWork;
m_runTotalMS += m_runLastMS;
//
p_model.setDateLastRun(new Timestamp(now));
p_model.save();
//
log.fine(getName() + ": " + getStatistics());
} // runNow
/**************************************************************************
* Run async
*/
public void run ()
{
try
{
log.fine(getName() + ": pre-nap - " + m_initialNap);
sleep (m_initialNap * 1000);
}
catch (InterruptedException e)
{
log.log(Level.SEVERE, getName() + ": pre-nap interrupted", e);
return;
}
m_start = System.currentTimeMillis();
while (true)
{
if (m_nextWork == 0)
{
Timestamp dateNextRun = getDateNextRun(true);
if (dateNextRun != null)
m_nextWork = dateNextRun.getTime();
}
long now = System.currentTimeMillis();
if (m_nextWork > now)
{
m_sleepMS = m_nextWork - now;
if (!sleep ())
break;
}
if (isInterrupted())
{
log.info (getName() + ": interrupted");
break;
}
// ---------------
p_startWork = System.currentTimeMillis();
doWork();
now = System.currentTimeMillis();
// ---------------
p_runCount++;
m_runLastMS = now - p_startWork;
m_runTotalMS += m_runLastMS;
//
m_sleepMS = calculateSleep();
m_nextWork = now + m_sleepMS;
//
p_model.setDateLastRun(new Timestamp(now));
p_model.setDateNextRun(new Timestamp(m_nextWork));
p_model.save();
//
log.fine(getName() + ": " + getStatistics());
if (!sleep())
break;
}
m_start = 0;
} // run
/**
* Get Run Statistics
* @return Statistic info
*/
public String getStatistics()
{
return "Run #" + p_runCount
+ " - Last=" + TimeUtil.formatElapsed(m_runLastMS)
+ " - Total=" + TimeUtil.formatElapsed(m_runTotalMS)
+ " - Next " + TimeUtil.formatElapsed(m_nextWork - System.currentTimeMillis());
} // getStatistics
/**
* Do the actual Work
*/
protected abstract void doWork();
/**
* Get Server Info
* @return info
*/
public abstract String getServerInfo();
/**
* Get Unique ID
* @return Unique ID
*/
public String getServerID()
{
return p_model.getServerID();
} // getServerID
/**
* Get the date Next run
* @param requery requery database
* @return date next run
*/
public Timestamp getDateNextRun (boolean requery)
{
return p_model.getDateNextRun(requery);
} // getDateNextRun
/**
* Get the date Last run
* @return date lext run
*/
public Timestamp getDateLastRun ()
{
return p_model.getDateLastRun();
} // getDateLastRun
/**
* Get Description
* @return Description
*/
public String getDescription()
{
return p_model.getDescription();
} // getDescription
/**
* Get Model
* @return Model
*/
public AdempiereProcessor getModel()
{
return p_model;
} // getModel
/**
* Calculate Sleep ms
* @return miliseconds
*/
private long calculateSleep ()
{
String frequencyType = p_model.getFrequencyType();
int frequency = p_model.getFrequency();
if (frequency < 1)
frequency = 1;
//
long typeSec = 600; // 10 minutes
if (frequencyType == null)
typeSec = 300; // 5 minutes
else if (X_R_RequestProcessor.FREQUENCYTYPE_Minute.equals(frequencyType))
typeSec = 60;
else if (X_R_RequestProcessor.FREQUENCYTYPE_Hour.equals(frequencyType))
typeSec = 3600;
else if (X_R_RequestProcessor.FREQUENCYTYPE_Day.equals(frequencyType))
typeSec = 86400;
//
return typeSec * 1000 * frequency; // ms
} // calculateSleep
/**
* Is Sleeping
* @return sleeping
*/
public boolean isSleeping()
{
return m_sleeping;
} // isSleeping
/**
* String Representation
* @return info
*/
public String toString ()
{
StringBuffer sb = new StringBuffer (getName())
.append (",Prio=").append(getPriority())
.append (",").append (getThreadGroup())
.append (",Alive=").append(isAlive())
.append (",Sleeping=").append(m_sleeping)
.append (",Last=").append(getDateLastRun());
if (m_sleeping)
sb.append (",Next=").append(getDateNextRun(false));
return sb.toString ();
} // toString
/**
* Get Seconds Alive
* @return seconds alive
*/
public int getSecondsAlive()
{
if (m_start == 0)
return 0;
long now = System.currentTimeMillis();
long ms = (now-m_start) / 1000;
return (int)ms;
} // getSecondsAlive
/**
* Get Start Time
* @return start time
*/
public Timestamp getStartTime()
{
if (m_start == 0)
return null;
return new Timestamp (m_start);
} // getStartTime
/**
* Get Processor Logs
* @return logs
*/
public AdempiereProcessorLog[] getLogs()
{
return p_model.getLogs();
} // getLogs
} // AdempiereServer

View File

@ -0,0 +1,90 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.server;
import org.compiere.util.*;
/**
* Adempiere Server Group
*
* @author Jorg Janke
* @version $Id: AdempiereServerGroup.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $
*/
public class AdempiereServerGroup extends ThreadGroup
{
/**
* Get Adempiere Server Group
* @return Server Group
*/
public static AdempiereServerGroup get()
{
if (s_group == null || s_group.isDestroyed())
s_group = new AdempiereServerGroup();
return s_group;
} // get
/** Group */
private static AdempiereServerGroup s_group = null;
/**
* AdempiereServerGroup
*/
private AdempiereServerGroup ()
{
super ("AdempiereServers");
setDaemon(true);
setMaxPriority(Thread.MAX_PRIORITY);
log.info(getName() + " - Parent=" + getParent());
} // AdempiereServerGroup
/** Logger */
protected CLogger log = CLogger.getCLogger(getClass());
/**
* Uncaught Exception
* @param t thread
* @param e exception
*/
public void uncaughtException (Thread t, Throwable e)
{
log.info ("uncaughtException = " + e.toString());
super.uncaughtException (t, e);
} // uncaughtException
/**
* String Representation
* @return name
*/
public String toString ()
{
return getName();
} // toString
/**
* Dump Info
*/
public void dump ()
{
log.fine(getName() + (isDestroyed() ? " (destroyed)" : ""));
log.fine("- Parent=" + getParent());
Thread[] list = new Thread[activeCount()];
log.fine("- Count=" + enumerate(list, true));
for (int i = 0; i < list.length; i++)
log.fine("-- " + list[i]);
} // dump
} // AdempiereServerGroup

View File

@ -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.server;
import java.sql.*;
import java.util.*;
import java.util.logging.*;
import org.compiere.*;
import org.compiere.ldap.*;
import org.compiere.model.*;
import org.compiere.util.*;
import org.compiere.wf.*;
/**
* Adempiere Server Manager
*
* @author Jorg Janke
* @version $Id: AdempiereServerMgr.java,v 1.4 2006/10/09 00:23:26 jjanke Exp $
*/
public class AdempiereServerMgr
{
/**
* Get Adempiere Server Manager
* @return mgr
*/
public static AdempiereServerMgr get()
{
if (m_serverMgr == null)
{
// for faster subsequent calls
m_serverMgr = new AdempiereServerMgr();
m_serverMgr.startServers();
m_serverMgr.log.info(m_serverMgr.toString());
}
return m_serverMgr;
} // get
/** Singleton */
private static AdempiereServerMgr m_serverMgr = null;
/** Logger */
protected CLogger log = CLogger.getCLogger(getClass());
/**************************************************************************
* Adempiere Server Manager
*/
private AdempiereServerMgr ()
{
super();
startEnvironment();
// m_serverMgr.startServers();
} // AdempiereServerMgr
/** The Servers */
private ArrayList<AdempiereServer> m_servers = new ArrayList<AdempiereServer>();
/** Context */
private Properties m_ctx = Env.getCtx();
/** Start */
private Timestamp m_start = new Timestamp(System.currentTimeMillis());
/**
* Start Environment
* @return true if started
*/
private boolean startEnvironment()
{
Adempiere.startup(false);
log.info("");
// Set Session
MSession session = MSession.get(getCtx(), true);
session.setWebStoreSession(false);
session.setWebSession("Server");
session.save();
//
return true;
} // startEnvironment
/**
* Start Environment
* @return true if started
*/
private boolean startServers()
{
log.info("");
int noServers = 0;
// Accounting
MAcctProcessor[] acctModels = MAcctProcessor.getActive(m_ctx);
for (int i = 0; i < acctModels.length; i++)
{
MAcctProcessor pModel = acctModels[i];
AdempiereServer server = AdempiereServer.create(pModel);
server.start();
server.setPriority(Thread.NORM_PRIORITY-2);
m_servers.add(server);
}
// Request
MRequestProcessor[] requestModels = MRequestProcessor.getActive(m_ctx);
for (int i = 0; i < requestModels.length; i++)
{
MRequestProcessor pModel = requestModels[i];
AdempiereServer server = AdempiereServer.create(pModel);
server.start();
server.setPriority(Thread.NORM_PRIORITY-2);
m_servers.add(server);
}
// Workflow
MWorkflowProcessor[] workflowModels = MWorkflowProcessor.getActive(m_ctx);
for (int i = 0; i < workflowModels.length; i++)
{
MWorkflowProcessor pModel = workflowModels[i];
AdempiereServer server = AdempiereServer.create(pModel);
server.start();
server.setPriority(Thread.NORM_PRIORITY-2);
m_servers.add(server);
}
// Alert
MAlertProcessor[] alertModels = MAlertProcessor.getActive(m_ctx);
for (int i = 0; i < alertModels.length; i++)
{
MAlertProcessor pModel = alertModels[i];
AdempiereServer server = AdempiereServer.create(pModel);
server.start();
server.setPriority(Thread.NORM_PRIORITY-2);
m_servers.add(server);
}
// Scheduler
MScheduler[] schedulerModels = MScheduler.getActive(m_ctx);
for (int i = 0; i < schedulerModels.length; i++)
{
MScheduler pModel = schedulerModels[i];
AdempiereServer server = AdempiereServer.create(pModel);
server.start();
server.setPriority(Thread.NORM_PRIORITY-2);
m_servers.add(server);
}
// LDAP
LdapProcessorModel lp = new LdapProcessorModel(m_ctx);
AdempiereServer server = AdempiereServer.create(lp);
server.start();
server.setPriority(Thread.NORM_PRIORITY-2);
m_servers.add(server);
log.fine("#" + noServers);
return startAll();
} // startEnvironment
/**
* Get Server Context
* @return ctx
*/
public Properties getCtx()
{
return m_ctx;
} // getCtx
/**
* Start all servers
* @return true if started
*/
public boolean startAll()
{
log.info ("");
AdempiereServer[] servers = getInActive();
for (int i = 0; i < servers.length; i++)
{
AdempiereServer server = servers[i];
try
{
if (server.isAlive())
continue;
// Wait until dead
if (server.isInterrupted())
{
int maxWait = 10; // 10 iterations = 1 sec
while (server.isAlive())
{
if (maxWait-- == 0)
{
log.severe ("Wait timeout for interruped " + server);
break;
}
try
{
Thread.sleep(100); // 1/10 sec
}
catch (InterruptedException e)
{
log.log(Level.SEVERE, "While sleeping", e);
}
}
}
// Do start
if (!server.isAlive())
{
// replace
server = AdempiereServer.create (server.getModel());
if (server == null)
m_servers.remove(i);
else
m_servers.set(i, server);
server.start();
server.setPriority(Thread.NORM_PRIORITY-2);
}
}
catch (Exception e)
{
log.log(Level.SEVERE, "Server: " + server, e);
}
} // for all servers
// Final Check
int noRunning = 0;
int noStopped = 0;
for (int i = 0; i < servers.length; i++)
{
AdempiereServer server = servers[i];
try
{
if (server.isAlive())
{
log.info("Alive: " + server);
noRunning++;
}
else
{
log.warning("Dead: " + server);
noStopped++;
}
}
catch (Exception e)
{
log.log(Level.SEVERE, "(checking) - " + server, e);
noStopped++;
}
}
log.fine("Running=" + noRunning + ", Stopped=" + noStopped);
AdempiereServerGroup.get().dump();
return noStopped == 0;
} // startAll
/**
* Start Server if not started yet
* @param serverID server ID
* @return true if started
*/
public boolean start (String serverID)
{
AdempiereServer server = getServer(serverID);
if (server == null)
return false;
if (server.isAlive())
return true;
try
{
// replace
int index = m_servers.indexOf(server);
server = AdempiereServer.create (server.getModel());
if (server == null)
m_servers.remove(index);
else
m_servers.set(index, server);
server.start();
server.setPriority(Thread.NORM_PRIORITY-2);
Thread.yield();
}
catch (Exception e)
{
log.log(Level.SEVERE, "Server=" + serverID, e);
return false;
}
log.info(server.toString());
AdempiereServerGroup.get().dump();
if (server == null)
return false;
return server.isAlive();
} // startIt
/**
* Stop all Servers
* @return true if stopped
*/
public boolean stopAll()
{
log.info ("");
AdempiereServer[] servers = getActive();
// Interrupt
for (int i = 0; i < servers.length; i++)
{
AdempiereServer server = servers[i];
try
{
if (server.isAlive() && !server.isInterrupted())
{
server.setPriority(Thread.MAX_PRIORITY-1);
server.interrupt();
}
}
catch (Exception e)
{
log.log(Level.SEVERE, "(interrupting) - " + server, e);
}
} // for all servers
Thread.yield();
// Wait for death
for (int i = 0; i < servers.length; i++)
{
AdempiereServer server = servers[i];
try
{
int maxWait = 10; // 10 iterations = 1 sec
while (server.isAlive())
{
if (maxWait-- == 0)
{
log.severe ("Wait timeout for interruped " + server);
break;
}
Thread.sleep(100); // 1/10
}
}
catch (Exception e)
{
log.log(Level.SEVERE, "(waiting) - " + server, e);
}
} // for all servers
// Final Check
int noRunning = 0;
int noStopped = 0;
for (int i = 0; i < servers.length; i++)
{
AdempiereServer server = servers[i];
try
{
if (server.isAlive())
{
log.warning ("Alive: " + server);
noRunning++;
}
else
{
log.info ("Stopped: " + server);
noStopped++;
}
}
catch (Exception e)
{
log.log(Level.SEVERE, "(checking) - " + server, e);
noRunning++;
}
}
log.fine("Running=" + noRunning + ", Stopped=" + noStopped);
AdempiereServerGroup.get().dump();
return noRunning == 0;
} // stopAll
/**
* Stop Server if not stopped
* @param serverID server ID
* @return true if interrupted
*/
public boolean stop (String serverID)
{
AdempiereServer server = getServer(serverID);
if (server == null)
return false;
if (!server.isAlive())
return true;
try
{
server.interrupt();
Thread.sleep(10); // 1/100 sec
}
catch (Exception e)
{
log.log(Level.SEVERE, "stop", e);
return false;
}
log.info(server.toString());
AdempiereServerGroup.get().dump();
return !server.isAlive();
} // stop
/**
* Destroy
*/
public void destroy ()
{
log.info ("");
stopAll();
m_servers.clear();
} // destroy
/**
* Get Active Servers
* @return array of active servers
*/
protected AdempiereServer[] getActive()
{
ArrayList<AdempiereServer> list = new ArrayList<AdempiereServer>();
for (int i = 0; i < m_servers.size(); i++)
{
AdempiereServer server = (AdempiereServer)m_servers.get(i);
if (server != null && server.isAlive() && !server.isInterrupted())
list.add (server);
}
AdempiereServer[] retValue = new AdempiereServer[list.size ()];
list.toArray (retValue);
return retValue;
} // getActive
/**
* Get InActive Servers
* @return array of inactive servers
*/
protected AdempiereServer[] getInActive()
{
ArrayList<AdempiereServer> list = new ArrayList<AdempiereServer>();
for (int i = 0; i < m_servers.size(); i++)
{
AdempiereServer server = (AdempiereServer)m_servers.get(i);
if (server != null && (!server.isAlive() || !server.isInterrupted()))
list.add (server);
}
AdempiereServer[] retValue = new AdempiereServer[list.size()];
list.toArray (retValue);
return retValue;
} // getInActive
/**
* Get all Servers
* @return array of servers
*/
public AdempiereServer[] getAll()
{
AdempiereServer[] retValue = new AdempiereServer[m_servers.size()];
m_servers.toArray (retValue);
return retValue;
} // getAll
/**
* Get Server with ID
* @param serverID server id
* @return server or null
*/
public AdempiereServer getServer (String serverID)
{
if (serverID == null)
return null;
for (int i = 0; i < m_servers.size(); i++)
{
AdempiereServer server = (AdempiereServer)m_servers.get(i);
if (serverID.equals(server.getServerID()))
return server;
}
return null;
} // getServer
/**
* String Representation
* @return info
*/
public String toString ()
{
StringBuffer sb = new StringBuffer ("AdempiereServerMgr[");
sb.append("Servers=").append(m_servers.size())
.append(",ContextSize=").append(m_ctx.size())
.append(",Started=").append(m_start)
.append ("]");
return sb.toString ();
} // toString
/**
* Get Description
* @return description
*/
public String getDescription()
{
return "$Revision: 1.4 $";
} // getDescription
/**
* Get Number Servers
* @return no of servers
*/
public String getServerCount()
{
int noRunning = 0;
int noStopped = 0;
for (int i = 0; i < m_servers.size(); i++)
{
AdempiereServer server = (AdempiereServer)m_servers.get(i);
if (server.isAlive())
noRunning++;
else
noStopped++;
}
String info = String.valueOf(m_servers.size())
+ " - Running=" + noRunning
+ " - Stopped=" + noStopped;
return info;
} // getServerCount
/**
* Get start date
* @return start date
*/
public Timestamp getStartTime()
{
return m_start;
} // getStartTime
} // AdempiereServerMgr

View File

@ -0,0 +1,323 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.server;
import java.sql.*;
import java.util.logging.*;
import org.compiere.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Alert Processor
*
* @author Jorg Janke
* @version $Id: AlertProcessor.java,v 1.4 2006/07/30 00:53:33 jjanke Exp $
*/
public class AlertProcessor extends AdempiereServer
{
/**
* Alert Processor
* @param model model
*/
public AlertProcessor (MAlertProcessor model)
{
super (model, 180); // 3 monute delay
m_model = model;
m_client = MClient.get(model.getCtx(), model.getAD_Client_ID());
} // AlertProcessor
/** The Concrete Model */
private MAlertProcessor m_model = null;
/** Last Summary */
private StringBuffer m_summary = new StringBuffer();
/** Last Error Msg */
private StringBuffer m_errors = new StringBuffer();
/** Client onfo */
private MClient m_client = null;
/**
* Work
*/
protected void doWork ()
{
m_summary = new StringBuffer();
m_errors = new StringBuffer();
//
int count = 0;
int countError = 0;
MAlert[] alerts = m_model.getAlerts(false);
for (int i = 0; i < alerts.length; i++)
{
if (!processAlert(alerts[i]))
countError++;
count++;
}
//
String summary = "Total=" + count;
if (countError > 0)
summary += ", Not processed=" + countError;
summary += " - ";
m_summary.insert(0, summary);
//
int no = m_model.deleteLog();
m_summary.append("Logs deleted=").append(no);
//
MAlertProcessorLog pLog = new MAlertProcessorLog(m_model, m_summary.toString());
pLog.setReference("#" + String.valueOf(p_runCount)
+ " - " + TimeUtil.formatElapsed(new Timestamp(p_startWork)));
pLog.setTextMsg(m_errors.toString());
pLog.save();
} // doWork
/**
* Process Alert
* @param alert alert
* @return true if processed
*/
private boolean processAlert (MAlert alert)
{
if (!alert.isValid())
return false;
log.info("" + alert);
StringBuffer message = new StringBuffer(alert.getAlertMessage())
.append(Env.NL);
//
boolean valid = true;
boolean processed = false;
MAlertRule[] rules = alert.getRules(false);
for (int i = 0; i < rules.length; i++)
{
if (i > 0)
message.append(Env.NL).append("================================").append(Env.NL);
String trxName = null; // assume r/o
MAlertRule rule = rules[i];
if (!rule.isValid())
continue;
log.fine("" + rule);
// Pre
String sql = rule.getPreProcessing();
if (sql != null && sql.length() > 0)
{
int no = DB.executeUpdate(sql, false, trxName);
if (no == -1)
{
ValueNamePair error = CLogger.retrieveError();
rule.setErrorMsg("Pre=" + error.getName());
m_errors.append("Pre=" + error.getName());
rule.setIsValid(false);
rule.save();
valid = false;
break;
}
} // Pre
// The processing
sql = rule.getSql();
if (alert.isEnforceRoleSecurity()
|| alert.isEnforceClientSecurity())
{
int AD_Role_ID = alert.getFirstAD_Role_ID();
if (AD_Role_ID == -1)
AD_Role_ID = alert.getFirstUserAD_Role_ID();
if (AD_Role_ID != -1)
{
MRole role = MRole.get(getCtx(), AD_Role_ID);
sql = role.addAccessSQL(sql, null, true, false);
}
}
try
{
String text = listSqlSelect(sql, trxName);
if (text != null && text.length() > 0)
{
message.append(text);
processed = true;
}
}
catch (Exception e)
{
rule.setErrorMsg("Select=" + e.getLocalizedMessage());
m_errors.append("Select=" + e.getLocalizedMessage());
rule.setIsValid(false);
rule.save();
valid = false;
break;
}
// Post
sql = rule.getPostProcessing();
if (sql != null && sql.length() > 0)
{
int no = DB.executeUpdate(sql, false, trxName);
if (no == -1)
{
ValueNamePair error = CLogger.retrieveError();
rule.setErrorMsg("Post=" + error.getName());
m_errors.append("Post=" + error.getName());
rule.setIsValid(false);
rule.save();
valid = false;
break;
}
} // Post
/** Trx */
if (trxName != null)
{
Trx trx = Trx.get(trxName, false);
if (trx != null)
{
trx.commit();
trx.close();
}
}
} // for all rules
// Update header if error
if (!valid)
{
alert.setIsValid(false);
alert.save();
return false;
}
// Nothing to report
if (!processed)
{
m_summary.append(alert.getName()).append("=No Result - ");
return true;
}
// Send Message
int countMail = 0;
MAlertRecipient[] recipients = alert.getRecipients(false);
for (int i = 0; i < recipients.length; i++)
{
MAlertRecipient recipient = recipients[i];
if (recipient.getAD_User_ID() >= 0) // System == 0
if (m_client.sendEMail(recipient.getAD_User_ID(),
alert.getAlertSubject(), message.toString(), null))
countMail++;
if (recipient.getAD_Role_ID() >= 0) // SystemAdministrator == 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;
if (m_client.sendEMail (ur.getAD_User_ID(),
alert.getAlertSubject(), message.toString(), null))
countMail++;
}
}
}
m_summary.append(alert.getName()).append(" (EMails=").append(countMail).append(") - ");
return valid;
} // processAlert
/**
* List Sql Select
* @param sql sql select
* @param trxName transaction
* @return list of rows & values
* @throws Exception
*/
private String listSqlSelect (String sql, String trxName) throws Exception
{
StringBuffer result = new StringBuffer();
PreparedStatement pstmt = null;
Exception error = null;
try
{
pstmt = DB.prepareStatement (sql, trxName);
ResultSet rs = pstmt.executeQuery ();
ResultSetMetaData meta = rs.getMetaData();
while (rs.next ())
{
result.append("------------------").append(Env.NL);
for (int col = 1; col <= meta.getColumnCount(); col++)
{
result.append(meta.getColumnLabel(col)).append(" = ");
result.append(rs.getString(col));
result.append(Env.NL);
} // for all columns
}
if (result.length() == 0)
log.fine("No rows selected");
rs.close ();
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
log.log(Level.SEVERE, sql, e);
error = e;
}
try
{
if (pstmt != null)
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
pstmt = null;
}
// Error occured
if (error != null)
throw new Exception ("(" + sql + ") " + Env.NL
+ error.getLocalizedMessage());
return result.toString();
} // listSqlSelect
/**
* Get Server Info
* @return info
*/
public String getServerInfo()
{
return "#" + p_runCount + " - Last=" + m_summary.toString();
} // getServerInfo
/***************************************************************************
* Test
* @param args ignored
*/
public static void main (String[] args)
{
Adempiere.startup(true);
MAlertProcessor model = new MAlertProcessor (Env.getCtx(), 100, null);
AlertProcessor ap = new AlertProcessor(model);
ap.start();
} // main
} // AlertProcessor

View File

@ -0,0 +1,700 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.server;
import java.io.*;
import java.util.*;
import java.util.logging.*;
import javax.mail.*;
import org.compiere.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Request Mail Processor
*
* @author Jorg Janke
* @version $Id: EMailProcessor.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class EMailProcessor
{
/**
* EMail Processor
* @param client client
*/
public EMailProcessor (MClient client)
{
this (client.getSMTPHost(), client.getRequestUser(), client.getRequestUserPW());
} // EMailProcessor
/**
* EMail Processor
* @param host host
* @param user user id
* @param password password
*/
public EMailProcessor (String host, String user, String password)
{
m_host = host;
m_user = user;
m_pass = password;
} // EMail
/** EMail Host Parameter */
private String m_host = null;
/** EMail User Parameter */
private String m_user = null;
/** Password Parameter */
private String m_pass = null;
/** Session */
private Session m_session = null;
/** Store */
private Store m_store = null;
/** Logger */
protected CLogger log = CLogger.getCLogger(getClass());
/** Process Error */
private static final int ERROR = 0;
/** Process Request */
private static final int REQUEST = 1;
/** Process Workflow */
private static final int WORKFLOW = 2;
/** Process Delivery Confirm */
private static final int DELIVERY = 9;
/**
* Process Messages in InBox
* @return number of mails processed
*/
public int processMessages()
{
int processed = 0;
try
{
getSession();
getStore();
processed = processInBox();
}
catch (Exception e)
{
log.log(Level.SEVERE, "processInBox", e);
}
// Cleanup
try
{
if (m_store.isConnected())
m_store.close();
}
catch (Exception e)
{
}
m_store = null;
return processed;
} // processMessages
/**************************************************************************
* Get Session
* @return Session
* @throws Exception
*/
private Session getSession() throws Exception
{
if (m_session != null)
return m_session;
// Session
Properties props = System.getProperties();
props.put("mail.store.protocol", "smtp");
props.put("mail.transport.protocol", "smtp");
props.put("mail.host", m_host);
props.put("mail.smtp.auth","true");
EMailAuthenticator auth = new EMailAuthenticator (m_user, m_pass);
//
m_session = Session.getDefaultInstance(props, auth);
m_session.setDebug(CLogMgt.isLevelFinest());
log.fine("getSession - " + m_session);
return m_session;
} // getSession
/**
* Get Store
* @return Store
* @throws Exception
*/
private Store getStore() throws Exception
{
if (m_store != null)
return m_store;
if (getSession() == null)
throw new IllegalStateException("No Session");
// Get IMAP Store
m_store = m_session.getStore("imap");
// Connect
m_store.connect();
//
log.fine("getStore - " + m_store);
return m_store;
} // getStore
/**
* Process InBox
* @return number of processed
* @throws Exception
*/
private int processInBox() throws Exception
{
// Folder
Folder folder;
folder = m_store.getDefaultFolder();
if (folder == null)
throw new IllegalStateException("No default folder");
// Open Inbox
Folder inbox = folder.getFolder("INBOX");
if (!inbox.exists())
throw new IllegalStateException("No Inbox");
inbox.open(Folder.READ_WRITE);
log.fine("processInBox - " + inbox.getName()
+ "; Messages Total=" + inbox.getMessageCount()
+ "; New=" + inbox.getNewMessageCount());
// Open Request
Folder requestFolder = folder.getFolder("CRequest");
if (!requestFolder.exists() && !requestFolder.create(Folder.HOLDS_MESSAGES))
throw new IllegalStateException("Cannot create Request Folder");
requestFolder.open(Folder.READ_WRITE);
// Open Workflow
Folder workflowFolder = folder.getFolder("CWorkflow");
if (!workflowFolder.exists() && !workflowFolder.create(Folder.HOLDS_MESSAGES))
throw new IllegalStateException("Cannot create Workflow Folder");
workflowFolder.open(Folder.READ_WRITE);
// Open Error
Folder errorFolder = folder.getFolder("AdempiereError");
if (!errorFolder.exists() && !errorFolder.create(Folder.HOLDS_MESSAGES))
throw new IllegalStateException("Cannot create Error Folder");
errorFolder.open(Folder.READ_WRITE);
// Messages
Message[] messages = inbox.getMessages();
/**
FetchProfile fp = new FetchProfile();
fp.add(FetchProfile.Item.ENVELOPE);
fp.add(FetchProfile.Item.FLAGS);
fp.add("X-Mailer");
inbox.fetch(messages, fp);
**/
//
int noProcessed = 0;
int noError = 0;
for (int i = 0; i < messages.length; i++)
// for (int i = messages.length-1; i >= 0; i--) // newest first
{
Message msg = messages[i];
int result = processMessage (msg);
if (result == REQUEST)
{
msg.setFlag(Flags.Flag.SEEN, true);
msg.setFlag(Flags.Flag.ANSWERED, true);
// Copy to processed
requestFolder.appendMessages(new Message[]{msg});
}
else if (result == WORKFLOW)
{
msg.setFlag(Flags.Flag.SEEN, true);
msg.setFlag(Flags.Flag.ANSWERED, true);
// Copy to processed
workflowFolder.appendMessages(new Message[]{msg});
}
else if (result == DELIVERY)
{
msg.setFlag(Flags.Flag.SEEN, true);
msg.setFlag(Flags.Flag.ANSWERED, true);
}
else // error
{
errorFolder.appendMessages(new Message[]{msg});
noError++;
}
// Delete in InBox
// msg.setFlag(Flags.Flag.DELETED, true);
// Message[] deleted = inbox.expunge();
//
noProcessed++;
}
log.info("processInBox - Total=" + noProcessed + " - Errors=" + noError);
// Fini
errorFolder.close(false);
requestFolder.close(false);
workflowFolder.close(false);
//
inbox.close(true);
return noProcessed;
} // processInBox
/**
* Process Message
* @param msg message
* @return Type of Message
* @throws Exception
*/
private int processMessage (Message msg) throws Exception
{
dumpEnvelope (msg);
dumpBody (msg);
printOut (":::::::::::::::");
printOut (getSubject(msg));
printOut (":::::::::::::::");
printOut (getMessage(msg));
printOut (":::::::::::::::");
String delivery = getDeliveryReport(msg);
printOut (delivery);
printOut (":::::::::::::::");
// if (delivery != null)
// return DELIVERY;
// Unknown
return ERROR;
} // processMessage
/**
* Get Subject
* @param msg message
* @return subject or ""
*/
private String getSubject (Message msg)
{
try
{
String str = msg.getSubject();
if (str != null)
return str.trim();
}
catch (MessagingException e)
{
log.log(Level.SEVERE, "getSubject", e);
}
return "";
} // getSubject
/**
* Get Message
* @param msg Message
* @return message or ""
*/
private String getMessage (Part msg)
{
StringBuffer sb = new StringBuffer();
try
{
// Text
if (msg.isMimeType("text/plain"))
{
sb.append(msg.getContent());
}
// Other Text (e.g. html/xml)
else if (msg.isMimeType("text/*"))
{
sb.append(msg.getContent());
}
// Nested
else if (msg.isMimeType("message/rfc822"))
{
sb.append(msg.getContent());
}
// Multi Part Alternative
else if (msg.isMimeType("multipart/alternative"))
{
String plainText = null;
String otherStuff = null;
//
Multipart mp = (Multipart)msg.getContent();
int count = mp.getCount();
for (int i = 0; i < count; i++)
{
Part part = mp.getBodyPart(i);
Object content = part.getContent();
if (content == null || content.toString().trim().length() == 0)
continue;
if (part.isMimeType("text/plain"))
plainText = content.toString();
else
otherStuff = content.toString();
}
if (plainText != null)
sb.append(plainText);
else if (otherStuff != null)
sb.append(otherStuff);
}
// Multi Part
else if (msg.isMimeType("multipart/*"))
{
Multipart mp = (Multipart)msg.getContent();
int count = mp.getCount();
for (int i = 0; i < count; i++)
{
String str = getMessage(mp.getBodyPart(i));
if (str.length() > 0)
{
if (sb.length() > 0)
sb.append("\n-----\n");
sb.append(str);
}
}
}
else
{
/*
* If we actually want to see the data, and it's not a
* MIME type we know, fetch it and check its Java type.
*/
Object o = msg.getContent();
if (o instanceof String)
{
sb.append(o);
}
}
}
catch (Exception e)
{
log.log(Level.SEVERE, "getMessage", e);
}
return sb.toString().trim();
} // getMessage
/**
* Get Delivery Report
* @param msg message
* @return delivery info or null
*/
private String getDeliveryReport (Part msg)
{
try
{
if (msg.isMimeType("multipart/report"))
{
String deliveryMessage = null;
String otherStuff = null;
//
Multipart mp = (Multipart)msg.getContent();
int count = mp.getCount();
for (int i = 0; i < count; i++)
{
Part part = mp.getBodyPart(i);
Object content = part.getContent();
if (content == null)
continue;
if (part.isMimeType("message/*"))
deliveryMessage = getDeliveredReportDetail (part);
else
otherStuff = content.toString().trim();
}
if (deliveryMessage != null)
return deliveryMessage;
return otherStuff;
}
else if (msg.isMimeType("message/*"))
{
return getDeliveredReportDetail (msg);
}
}
catch (Exception e)
{
log.log(Level.SEVERE, "getDeliveryReport", e);
}
// Nothing
return null;
} // getDeliveryReport
/**
* Get Delivered Report Detail
* @param part Mime Type message/*
* @return info or null
* @throws Exception
*/
private String getDeliveredReportDetail (Part part) throws Exception
{
Object content = part.getContent();
if (content == null)
return null;
String deliveryMessage = null;
if (content instanceof InputStream)
{
StringBuffer sb = new StringBuffer();
InputStream is = (InputStream)content;
int c;
while ((c = is.read()) != -1)
sb.append((char)c);
deliveryMessage = sb.toString().trim();
}
else
deliveryMessage = content.toString().trim();
//
if (deliveryMessage == null)
return null;
// Final-Recipient: RFC822; jjanke@adempiere.org
int index = deliveryMessage.indexOf("Final-Recipient:");
if (index != -1)
{
String finalRecipient = deliveryMessage.substring(index);
int atIndex = finalRecipient.indexOf("@");
if (atIndex != -1)
{
index = finalRecipient.lastIndexOf(' ', atIndex);
if (index != -1)
finalRecipient = finalRecipient.substring(index+1);
atIndex = finalRecipient.indexOf("@");
if (atIndex != -1)
index = finalRecipient.indexOf(' ', atIndex);
if (index != -1)
finalRecipient = finalRecipient.substring(0, index);
index = finalRecipient.indexOf('\n');
if (index != -1)
finalRecipient = finalRecipient.substring(0, index);
return finalRecipient.trim();
}
}
return deliveryMessage;
} // getDeliveredReportDetail
/**************************************************************************
* Print Envelope
* @param m message
* @throws Exception
*/
private void dumpEnvelope(Message m) throws Exception
{
printOut("-----------------------------------------------------------------");
Address[] a;
// FROM
if ((a = m.getFrom()) != null)
{
for (int j = 0; j < a.length; j++)
printOut("FROM: " + a[j].toString());
}
// TO
if ((a = m.getRecipients(Message.RecipientType.TO)) != null)
{
for (int j = 0; j < a.length; j++)
printOut("TO: " + a[j].toString());
}
// SUBJECT
printOut("SUBJECT: " + m.getSubject());
// DATE
java.util.Date d = m.getSentDate();
printOut("SendDate: " + (d != null ? d.toString() : "UNKNOWN"));
// FLAGS
Flags flags = m.getFlags();
StringBuffer sb = new StringBuffer();
Flags.Flag[] sf = flags.getSystemFlags(); // get the system flags
boolean first = true;
for (int i = 0; i < sf.length; i++)
{
String s;
Flags.Flag f = sf[i];
if (f == Flags.Flag.ANSWERED)
s = "\\Answered";
else if (f == Flags.Flag.DELETED)
s = "\\Deleted";
else if (f == Flags.Flag.DRAFT)
s = "\\Draft";
else if (f == Flags.Flag.FLAGGED)
s = "\\Flagged";
else if (f == Flags.Flag.RECENT)
s = "\\Recent";
else if (f == Flags.Flag.SEEN)
s = "\\Seen";
else
continue; // skip it
if (first)
first = false;
else
sb.append(' ');
sb.append(s);
}
String[] uf = flags.getUserFlags(); // get the user flag strings
for (int i = 0; i < uf.length; i++)
{
if (first)
first = false;
else
sb.append(' ');
sb.append(uf[i]);
}
printOut("FLAGS: " + sb.toString());
// X-MAILER
String[] hdrs = m.getHeader("X-Mailer");
if (hdrs != null)
{
StringBuffer sb1 = new StringBuffer("X-Mailer: ");
for (int i = 0; i < hdrs.length; i++)
sb1.append(hdrs[i]).append(" ");
printOut(sb1.toString());
}
else
printOut("X-Mailer NOT available");
// Message ID
hdrs = m.getHeader("Message-ID");
if (hdrs != null)
{
StringBuffer sb1 = new StringBuffer("Message-ID: ");
for (int i = 0; i < hdrs.length; i++)
sb1.append(hdrs[i]).append(" ");
printOut(sb1.toString());
}
else
printOut("Message-ID NOT available");
// All
printOut("ALL HEADERs:");
Enumeration en = m.getAllHeaders();
while (en.hasMoreElements())
{
Header hdr = (Header)en.nextElement();
printOut (" " + hdr.getName() + " = " + hdr.getValue());
}
printOut("-----------------------------------------------------------------");
} // printEnvelope
/**
* Print Body
* @param p
* @throws Exception
*/
private void dumpBody (Part p) throws Exception
{
// http://www.iana.org/assignments/media-types/
printOut("=================================================================");
printOut("CONTENT-TYPE: " + p.getContentType());
/**
Enumeration en = p.getAllHeaders();
while (en.hasMoreElements())
{
Header hdr = (Header)en.nextElement();
printOut (" " + hdr.getName() + " = " + hdr.getValue());
}
printOut("= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =");
/** **/
/**
* Using isMimeType to determine the content type avoids
* fetching the actual content data until we need it.
*/
if (p.isMimeType("text/plain"))
{
printOut("Plain text ---------------------------");
System.out.println((String)p.getContent());
}
else if (p.getContentType().toUpperCase().startsWith("TEXT"))
{
printOut("Other text ---------------------------");
System.out.println((String)p.getContent());
}
else if (p.isMimeType("multipart/*"))
{
printOut("Multipart ---------------------------");
Multipart mp = (Multipart)p.getContent();
int count = mp.getCount();
for (int i = 0; i < count; i++)
dumpBody(mp.getBodyPart(i));
}
else if (p.isMimeType("message/rfc822"))
{
printOut("Nested ---------------------------");
dumpBody((Part)p.getContent());
}
else
{
/*
* If we actually want to see the data, and it's not a
* MIME type we know, fetch it and check its Java type.
*/
Object o = p.getContent();
if (o instanceof String)
{
printOut("This is a string ---------------------------");
System.out.println((String)o);
}
else if (o instanceof InputStream)
{
printOut("This is just an input stream ---------------------------");
InputStream is = (InputStream)o;
int c;
while ((c = is.read()) != -1)
System.out.write(c);
}
else
{
printOut("This is an unknown type ---------------------------");
printOut(o.toString());
}
}
printOut("=================================================================");
} // printBody
/**
* Print
* @param s string
*/
private static void printOut(String s)
{
// System.out.print(indentStr.substring(0, level * 2));
System.out.println(s);
}
/**************************************************************************
* Main Test
* @param args ignored
*/
public static void main (String[] args)
{
Adempiere.startupEnvironment(true);
EMailProcessor m = new EMailProcessor("admin", "test", "testadempiere");
m.processMessages();
// System.out.println(EMailServer.send("main", "jjanke@adempiere.org", "jjanke@yahoo.com", "test1", "test1 message"));
// System.out.println(EMailServer.send("main", "administrator@adempiere.org", "jjanke@yahoo.com", "test2", "test2 message"));
// System.out.println(EMailServer.send("main", "jjanke@adempiere.org", "jjanke@yahoo.com", "test3", "test3 message"));
} // main
} // EMailProcessor

View File

@ -0,0 +1,655 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.server;
import java.sql.*;
import java.util.*;
import java.util.logging.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Request Processor
*
* @author Jorg Janke
* @version $Id: RequestProcessor.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class RequestProcessor extends AdempiereServer
{
/**
* RequestProcessor
* @param model model
*/
public RequestProcessor (MRequestProcessor model)
{
super (model, 60); // 1 minute delay
m_model = model;
m_client = MClient.get(model.getCtx(), model.getAD_Client_ID());
} // RequestProcessor
/** The Concrete Model */
private MRequestProcessor m_model = null;
/** Last Summary */
private StringBuffer m_summary = new StringBuffer();
/** Client onfo */
private MClient m_client = null;
/**************************************************************************
* Do the actual Work
*/
protected void doWork()
{
m_summary = new StringBuffer();
//
processEMail();
findSalesRep ();
processRequests ();
processStatus();
processECR();
//
int no = m_model.deleteLog();
m_summary.append("Logs deleted=").append(no);
//
MRequestProcessorLog pLog = new MRequestProcessorLog(m_model, m_summary.toString());
pLog.setReference("#" + String.valueOf(p_runCount)
+ " - " + TimeUtil.formatElapsed(new Timestamp(p_startWork)));
pLog.save();
} // doWork
/**************************************************************************
* Process requests.
* Scheduled - are they due?
*/
private void processRequests ()
{
/**
* Due Requests
*/
String sql = "SELECT * FROM R_Request "
+ "WHERE DueType='" + MRequest.DUETYPE_Scheduled + "' AND Processed='N'"
+ " AND DateNextAction > SysDate"
+ " AND AD_Client_ID=?";
if (m_model.getR_RequestType_ID() != 0)
sql += " AND R_RequestType_ID=?";
PreparedStatement pstmt = null;
int count = 0;
int countEMails = 0;
try
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setInt (1, m_model.getAD_Client_ID());
if (m_model.getR_RequestType_ID() != 0)
pstmt.setInt(2, m_model.getR_RequestType_ID());
ResultSet rs = pstmt.executeQuery ();
while (rs.next ())
{
MRequest request = new MRequest (getCtx(), rs, null);
request.setDueType();
if (request.isDue())
{
if (request.getRequestType().isEMailWhenDue())
{
if (sendEmail (request, "RequestDue"))
{
request.setDateLastAlert();
countEMails++;
}
}
request.save();
count++;
}
}
rs.close ();
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
log.log(Level.SEVERE, sql, e);
}
m_summary.append("New Due #").append(count);
if (countEMails > 0)
m_summary.append(" (").append(countEMails).append(" EMail)");
m_summary.append (" - ");
/**
* Overdue Requests.
* Due Requests - are they overdue?
*/
sql = "SELECT * FROM R_Request r "
+ "WHERE r.DueType='" + MRequest.DUETYPE_Due + "' AND r.Processed='N'"
+ " AND AD_Client_ID=?"
+ " AND EXISTS (SELECT * FROM R_RequestType rt "
+ "WHERE r.R_RequestType_ID=rt.R_RequestType_ID"
+ " AND (r.DateNextAction+rt.DueDateTolerance) > SysDate)";
if (m_model.getR_RequestType_ID() != 0)
sql += " AND r.R_RequestType_ID=?";
count = 0;
countEMails = 0;
try
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setInt (1, m_model.getAD_Client_ID());
if (m_model.getR_RequestType_ID() != 0)
pstmt.setInt(2, m_model.getR_RequestType_ID());
ResultSet rs = pstmt.executeQuery ();
while (rs.next ())
{
MRequest request = new MRequest (getCtx(), rs, null);
request.setDueType();
if (request.isOverdue())
{
if (request.getRequestType().isEMailWhenOverdue()
&& !TimeUtil.isSameDay(request.getDateLastAlert(), null))
{
if (sendEmail (request, "RequestDue"))
{
request.setDateLastAlert();
countEMails++;
}
}
request.save();
count++;
}
}
rs.close ();
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
log.log(Level.SEVERE, sql, e);
}
m_summary.append("New Overdue #").append(count);
if (countEMails > 0)
m_summary.append(" (").append(countEMails).append(" EMail)");
m_summary.append (" - ");
/**
* Send (over)due alerts
*/
if (m_model.getOverdueAlertDays() > 0)
{
sql = "SELECT * FROM R_Request "
+ "WHERE Processed='N'"
+ " AND AD_Client_ID=?"
+ " AND (DateNextAction+" + m_model.getOverdueAlertDays() + ") > SysDate"
+ " AND (DateLastAlert IS NULL";
if (m_model.getRemindDays() > 0)
sql += " OR (DateLastAlert+" + m_model.getRemindDays()
+ ") > SysDate";
sql += ")";
if (m_model.getR_RequestType_ID() != 0)
sql += " AND R_RequestType_ID=?";
count = 0;
countEMails = 0;
try
{
pstmt = DB.prepareStatement(sql, null);
pstmt.setInt(1, m_model.getAD_Client_ID());
if (m_model.getR_RequestType_ID() != 0)
pstmt.setInt(2, m_model.getR_RequestType_ID());
ResultSet rs = pstmt.executeQuery();
while (rs.next())
{
MRequest request = new MRequest (getCtx(), rs, null);
request.setDueType();
if (request.getRequestType().isEMailWhenOverdue()
&& (request.getDateLastAlert() == null
|| !TimeUtil.isSameDay(request.getDateLastAlert(), null)))
{
if (sendEmail (request, "RequestAlert"))
{
request.setDateLastAlert();
countEMails++;
}
}
request.save();
count++;
}
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, sql, e);
}
m_summary.append("Alerts #").append(count);
if (countEMails > 0)
m_summary.append(" (").append(countEMails).append(" EMail)");
m_summary.append (" - ");
} // Overdue
/**
* Escalate
*/
if (m_model.getOverdueAssignDays() > 0)
{
sql = "SELECT * FROM R_Request "
+ "WHERE Processed='N'"
+ " AND AD_Client_ID=?"
+ " AND IsEscalated='N'"
+ " AND (DateNextAction+" + m_model.getOverdueAssignDays()
+ ") > SysDate";
if (m_model.getR_RequestType_ID() != 0)
sql += " AND R_RequestType_ID=?";
count = 0;
countEMails = 0;
try
{
pstmt = DB.prepareStatement(sql, null);
pstmt.setInt(1, m_model.getAD_Client_ID());
if (m_model.getR_RequestType_ID() != 0)
pstmt.setInt(2, m_model.getR_RequestType_ID());
ResultSet rs = pstmt.executeQuery();
while (rs.next())
{
MRequest request = new MRequest (getCtx(), rs, null);
if (escalate(request))
count++;
}
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, sql, e);
}
m_summary.append("Escalated #").append(count).append(" - ");
} // Esacalate
/**
* Send inactivity alerts
*/
if (m_model.getInactivityAlertDays() > 0)
{
sql = "SELECT * FROM R_Request "
+ "WHERE Processed='N'"
+ " AND AD_Client_ID=?"
+ " AND (Updated+" + m_model.getInactivityAlertDays() + ") > SysDate"
+ " AND (DateLastAlert IS NULL";
if (m_model.getRemindDays() > 0)
sql += " OR (DateLastAlert+" + m_model.getRemindDays()
+ ") < SysDate";
sql += ")";
if (m_model.getR_RequestType_ID() != 0)
sql += " AND R_RequestType_ID=?";
count = 0;
countEMails = 0;
try
{
pstmt = DB.prepareStatement(sql, null);
pstmt.setInt(1, m_model.getAD_Client_ID());
if (m_model.getR_RequestType_ID() != 0)
pstmt.setInt(2, m_model.getR_RequestType_ID());
ResultSet rs = pstmt.executeQuery();
while (rs.next())
{
MRequest request = new MRequest (getCtx(), rs, null);
request.setDueType();
if (request.getDateLastAlert() == null
|| !TimeUtil.isSameDay(request.getDateLastAlert(), null))
{
if (sendEmail (request, "RequestInactive"))
{
request.setDateLastAlert();
countEMails++;
}
request.save();
count++;
}
}
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, sql, e);
}
m_summary.append("Inactivity #").append(count);
if (countEMails > 0)
m_summary.append(" (").append(countEMails).append(" EMail)");
m_summary.append (" - ");
} // Inactivity
//
try
{
if (pstmt != null)
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
pstmt = null;
}
} // processRequests
/**
* Send Alert EMail
* @param request request
* @param AD_Message message
* @return true if sent
*/
private boolean sendEmail (MRequest request, String AD_Message)
{
// Alert: Request {0} overdue
String subject = Msg.getMsg(m_client.getAD_Language(), AD_Message,
new String[] {request.getDocumentNo()});
return m_client.sendEMail(request.getSalesRep_ID(),
subject, request.getSummary(), request.createPDF());
} // sendAlert
/**
* Escalate
* @param request request
* @return true if saved
*/
private boolean escalate (MRequest request)
{
// Get Supervisor
MUser supervisor = request.getSalesRep(); // self
int supervisor_ID = request.getSalesRep().getSupervisor_ID();
if (supervisor_ID == 0 && m_model.getSupervisor_ID() != 0)
supervisor_ID = m_model.getSupervisor_ID();
if (supervisor_ID != 0 && supervisor_ID != request.getAD_User_ID())
supervisor = MUser.get(getCtx(), supervisor_ID);
// Escalated: Request {0} to {1}
String subject = Msg.getMsg(m_client.getAD_Language(), "RequestEscalate",
new String[] {request.getDocumentNo(), supervisor.getName()});
String to = request.getSalesRep().getEMail();
if (to == null || to.length() == 0)
log.warning("SalesRep has no EMail - " + request.getSalesRep());
else
m_client.sendEMail(request.getSalesRep_ID(),
subject, request.getSummary(), request.createPDF());
// Not the same - send mail to supervisor
if (request.getSalesRep_ID() != supervisor.getAD_User_ID())
{
to = supervisor.getEMail();
if (to == null || to.length() == 0)
log.warning("Supervisor has no EMail - " + supervisor);
else
m_client.sendEMail(supervisor.getAD_User_ID(),
subject, request.getSummary(), request.createPDF());
}
// ----------------
request.setDueType();
request.setIsEscalated(true);
request.setResult(subject);
return request.save();
} // escalate
/**************************************************************************
* Process Request Status
*/
private void processStatus()
{
int count = 0;
// Requests with status with after timeout
String sql = "SELECT * FROM R_Request r WHERE EXISTS ("
+ "SELECT * FROM R_Status s "
+ "WHERE r.R_Status_ID=s.R_Status_ID"
+ " AND s.TimeoutDays > 0 AND s.Next_Status_ID > 0"
+ " AND r.Updated+s.TimeoutDays < SysDate"
+ ") "
+ "ORDER BY R_Status_ID";
PreparedStatement pstmt = null;
MStatus status = null;
MStatus next = null;
try
{
pstmt = DB.prepareStatement (sql, null);
ResultSet rs = pstmt.executeQuery ();
while (rs.next ())
{
MRequest r = new MRequest(getCtx(), rs, null);
// Get/Check Status
if (status == null || status.getR_Status_ID() != r.getR_Status_ID())
status = MStatus.get(getCtx(), r.getR_Status_ID());
if (status.getTimeoutDays() <= 0
|| status.getNext_Status_ID() == 0)
continue;
// Next Status
if (next == null || next.getR_Status_ID() != status.getNext_Status_ID())
next = MStatus.get(getCtx(), status.getNext_Status_ID());
//
String result = Msg.getMsg(getCtx(), "RequestStatusTimeout")
+ ": " + status.getName() + " -> " + next.getName();
r.setResult(result);
r.setR_Status_ID(status.getNext_Status_ID());
if (r.save())
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;
}
m_summary.append("Status Timeout #").append(count)
.append(" - ");
} // processStatus
/**
* Create ECR
*/
private void processECR()
{
// Get Requests with Request Type-AutoChangeRequest and Group with info
String sql = "SELECT * FROM R_Request r "
+ "WHERE M_ChangeRequest_ID IS NULL"
+ " AND EXISTS ("
+ "SELECT * FROM R_RequestType rt "
+ "WHERE rt.R_RequestType_ID=r.R_RequestType_ID"
+ " AND rt.IsAutoChangeRequest='Y')"
+ "AND EXISTS ("
+ "SELECT * FROM R_Group g "
+ "WHERE g.R_Group_ID=r.R_Group_ID"
+ " AND (g.M_BOM_ID IS NOT NULL OR g.M_ChangeNotice_ID IS NOT NULL) )";
//
int count = 0;
int failure = 0;
//
PreparedStatement pstmt = null;
try
{
pstmt = DB.prepareStatement (sql, null);
ResultSet rs = pstmt.executeQuery ();
while (rs.next ())
{
MRequest r = new MRequest (getCtx(), rs, null);
MGroup rg = MGroup.get(getCtx(), r.getR_Group_ID());
MChangeRequest ecr = new MChangeRequest (r, rg);
if (r.save())
{
r.setM_ChangeRequest_ID(ecr.getM_ChangeRequest_ID());
if (r.save())
count++;
else
failure++;
}
else
failure++;
}
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_summary.append("Auto Change Request #").append(count);
if (failure > 0)
m_summary.append("(fail=").append(failure).append(")");
m_summary.append(" - ");
} // processECR
/**************************************************************************
* Create Reauest / Updates from EMail
*/
private void processEMail ()
{
// m_summary.append("Mail #").append(count)
// .append(" - ");
} // processEMail
/**************************************************************************
* Allocate Sales Rep
*/
private void findSalesRep ()
{
int changed = 0;
int notFound = 0;
Properties ctx = new Properties();
//
String sql = "SELECT * FROM R_Request "
+ "WHERE AD_Client_ID=?"
+ " AND SalesRep_ID=0 AND Processed='N'";
if (m_model.getR_RequestType_ID() != 0)
sql += " AND R_RequestType_ID=?";
PreparedStatement pstmt = null;
try
{
pstmt = DB.prepareStatement(sql, null);
pstmt.setInt(1, m_model.getAD_Client_ID());
if (m_model.getR_RequestType_ID() != 0)
pstmt.setInt(2, m_model.getR_RequestType_ID());
ResultSet rs = pstmt.executeQuery();
while (rs.next())
{
MRequest request = new MRequest (ctx, rs, null);
if (request.getSalesRep_ID() != 0)
continue;
int SalesRep_ID = findSalesRep(request);
if (SalesRep_ID != 0)
{
request.setSalesRep_ID(SalesRep_ID);
request.save();
changed++;
}
else
notFound++;
}
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 (changed == 0 && notFound == 0)
m_summary.append("No unallocated Requests");
else
m_summary.append("Allocated SalesRep=").append(changed);
if (notFound > 0)
m_summary.append(",Not=").append(notFound);
m_summary.append(" - ");
} // findSalesRep
/**
* Find SalesRep/User based on Request Type and Question.
* @param request request
* @return SalesRep_ID user
*/
private int findSalesRep (MRequest request)
{
String QText = request.getSummary();
if (QText == null)
QText = "";
else
QText = QText.toUpperCase();
//
MRequestProcessorRoute[] routes = m_model.getRoutes(false);
for (int i = 0; i < routes.length; i++)
{
MRequestProcessorRoute route = routes[i];
// Match first on Request Type
if (request.getR_RequestType_ID() == route.getR_RequestType_ID()
&& route.getR_RequestType_ID() != 0)
return route.getAD_User_ID();
// Match on element of keyword
String keyword = route.getKeyword();
if (keyword != null)
{
StringTokenizer st = new StringTokenizer(keyword.toUpperCase(), " ,;\t\n\r\f");
while (st.hasMoreElements())
{
if (QText.indexOf(st.nextToken()) != -1)
return route.getAD_User_ID();
}
}
} // for all routes
return m_model.getSupervisor_ID();
} // findSalesRep
/**
* Get Server Info
* @return info
*/
public String getServerInfo()
{
return "#" + p_runCount + " - Last=" + m_summary.toString();
} // getServerInfo
} // RequestProcessor

View File

@ -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 *
*****************************************************************************/
package org.compiere.server;
import java.io.*;
import java.math.*;
import java.sql.*;
import java.util.logging.*;
import org.compiere.model.*;
import org.compiere.print.*;
import org.compiere.process.*;
import org.compiere.util.*;
/**
* Scheduler
*
* @author Jorg Janke
* @version $Id: Scheduler.java,v 1.5 2006/07/30 00:53:33 jjanke Exp $
*/
public class Scheduler extends AdempiereServer
{
/**
* Scheduler
* @param model model
*/
public Scheduler (MScheduler model)
{
super (model, 240); // nap
m_model = model;
// m_client = MClient.get(model.getCtx(), model.getAD_Client_ID());
} // Scheduler
/** The Concrete Model */
private MScheduler m_model = null;
/** Last Summary */
private StringBuffer m_summary = new StringBuffer();
/** Transaction */
private Trx m_trx = null;
/**
* Work
*/
protected void doWork ()
{
m_summary = new StringBuffer(m_model.toString())
.append(" - ");
//
MProcess process = m_model.getProcess();
try
{
m_trx = Trx.get(Trx.createTrxName("Scheduler"), true);
if (process.isReport())
m_summary.append(runReport(process));
else
m_summary.append(runProcess(process));
m_trx.commit();
}
catch (Exception e)
{
if (m_trx != null)
m_trx.rollback();
log.log(Level.WARNING, process.toString(), e);
m_summary.append(e.toString());
}
if (m_trx != null)
m_trx.close();
//
int no = m_model.deleteLog();
m_summary.append("Logs deleted=").append(no);
//
MSchedulerLog pLog = new MSchedulerLog(m_model, m_summary.toString());
pLog.setReference("#" + String.valueOf(p_runCount)
+ " - " + TimeUtil.formatElapsed(new Timestamp(p_startWork)));
pLog.save();
} // doWork
/**
* Run Report
* @param process
* @return summary
* @throws Exception
*/
private String runReport(MProcess process) throws Exception
{ log.info(process.toString());
if (!process.isReport() || process.getAD_ReportView_ID() == 0)
return "Not a Report AD_Process_ID=" + process.getAD_Process_ID()
+ " - " + process.getName();
// Process
int AD_Table_ID = 0;
int Record_ID = 0;
//
MPInstance pInstance = new MPInstance(process, Record_ID);
fillParameter(pInstance);
//
ProcessInfo pi = new ProcessInfo (process.getName(), process.getAD_Process_ID(),
AD_Table_ID, Record_ID);
pi.setAD_User_ID(m_model.getUpdatedBy());
pi.setAD_Client_ID(m_model.getAD_Client_ID());
pi.setAD_PInstance_ID(pInstance.getAD_PInstance_ID());
if (!process.processIt(pi, m_trx) && pi.getClassName() != null)
return "Process failed: (" + pi.getClassName() + ") " + pi.getSummary();
// Report
ReportEngine re = ReportEngine.get(getCtx(), pi);
if (re == null)
return "Cannot create Report AD_Process_ID=" + process.getAD_Process_ID()
+ " - " + process.getName();
File report = re.getPDF();
// Notice
int AD_Message_ID = 884; // HARDCODED SchedulerResult
Integer[] userIDs = m_model.getRecipientAD_User_IDs();
for (int i = 0; i < userIDs.length; i++)
{
MNote note = new MNote(getCtx(),
AD_Message_ID, userIDs[i].intValue(), m_trx.getTrxName());
note.setClientOrg(m_model.getAD_Client_ID(), m_model.getAD_Org_ID());
note.setTextMsg(m_model.getName());
note.setDescription(m_model.getDescription());
note.setRecord(AD_Table_ID, Record_ID);
note.save();
// Attachment
MAttachment attachment = new MAttachment (getCtx(),
X_AD_Note.Table_ID, note.getAD_Note_ID(), m_trx.getTrxName());
attachment.setClientOrg(m_model.getAD_Client_ID(), m_model.getAD_Org_ID());
attachment.addEntry(report);
attachment.setTextMsg(m_model.getName());
attachment.save();
}
//
return pi.getSummary();
} // runReport
/**
* Run Process
* @param process process
* @return summary
* @throws Exception
*/
private String runProcess(MProcess process) throws Exception
{
log.info(process.toString());
// Process (see also MWFActivity.performWork
int AD_Table_ID = 0;
int Record_ID = 0;
//
MPInstance pInstance = new MPInstance(process, Record_ID);
fillParameter(pInstance);
//
ProcessInfo pi = new ProcessInfo (process.getName(), process.getAD_Process_ID(),
AD_Table_ID, Record_ID);
pi.setAD_User_ID(m_model.getUpdatedBy());
pi.setAD_Client_ID(m_model.getAD_Client_ID());
pi.setAD_PInstance_ID(pInstance.getAD_PInstance_ID());
process.processIt(pi, m_trx);
return pi.getSummary();
} // runProcess
/**
* Fill Parameter
* @param pInstance process instance
*/
private void fillParameter(MPInstance pInstance)
{
MSchedulerPara[] sParams = m_model.getParameters (false);
MPInstancePara[] iParams = pInstance.getParameters();
for (int pi = 0; pi < iParams.length; pi++)
{
MPInstancePara iPara = iParams[pi];
for (int np = 0; np < sParams.length; np++)
{
MSchedulerPara sPara = sParams[np];
if (iPara.getParameterName().equals(sPara.getColumnName()))
{
String variable = sPara.getParameterDefault();
log.fine(sPara.getColumnName() + " = " + variable);
// Value - Constant/Variable
Object value = variable;
if (variable == null
|| (variable != null && variable.length() == 0))
value = null;
else if (variable.indexOf("@") != -1) // we have a variable
{
// Strip
int index = variable.indexOf("@");
String columnName = variable.substring(index+1);
index = columnName.indexOf("@");
if (index == -1)
{
log.warning(sPara.getColumnName()
+ " - cannot evaluate=" + variable);
break;
}
columnName = columnName.substring(0, index);
// try Env
String env = Env.getContext(getCtx(), columnName);
if (env.length() == 0)
{
log.warning(sPara.getColumnName()
+ " - not in environment =" + columnName
+ "(" + variable + ")");
break;
}
else
value = env;
} // @variable@
// No Value
if (value == null)
{
log.fine(sPara.getColumnName() + " - empty");
break;
}
// Convert to Type
try
{
if (DisplayType.isNumeric(sPara.getDisplayType())
|| DisplayType.isID(sPara.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(sPara.getColumnName()
+ " = " + variable + " (=" + bd + "=)");
}
else if (DisplayType.isDate(sPara.getDisplayType()))
{
Timestamp ts = null;
if (value instanceof Timestamp)
ts = (Timestamp)value;
else
ts = Timestamp.valueOf(value.toString());
iPara.setP_Date(ts);
log.fine(sPara.getColumnName()
+ " = " + variable + " (=" + ts + "=)");
}
else
{
iPara.setP_String(value.toString());
log.fine(sPara.getColumnName()
+ " = " + variable
+ " (=" + value + "=) " + value.getClass().getName());
}
if (!iPara.save())
log.warning("Not Saved - " + sPara.getColumnName());
}
catch (Exception e)
{
log.warning(sPara.getColumnName()
+ " = " + variable + " (" + value
+ ") " + value.getClass().getName()
+ " - " + e.getLocalizedMessage());
}
break;
} // parameter match
} // scheduler parameter loop
} // instance parameter loop
} // fillParameter
/**
* Get Server Info
* @return info
*/
public String getServerInfo()
{
return "#" + p_runCount + " - Last=" + m_summary.toString();
} // getServerInfo
} // Scheduler

View File

@ -0,0 +1,485 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.server;
import java.sql.*;
import java.util.*;
import java.io.*;
import java.util.logging.*;
import org.compiere.util.*;
import org.compiere.wf.*;
import org.compiere.model.*;
import org.compiere.process.*;
/**
* Workflow Processor
*
* @author Jorg Janke
* @version $Id: WorkflowProcessor.java,v 1.4 2006/07/30 00:53:33 jjanke Exp $
*/
public class WorkflowProcessor extends AdempiereServer
{
/**
* WorkflowProcessor
* @param model model
*/
public WorkflowProcessor (MWorkflowProcessor model)
{
super (model, 120); // 2 minute dalay
m_model = model;
m_client = MClient.get(model.getCtx(), model.getAD_Client_ID());
} // WorkflowProcessor
/** The Concrete Model */
private MWorkflowProcessor m_model = null;
/** Last Summary */
private StringBuffer m_summary = new StringBuffer();
/** Client onfo */
private MClient m_client = null;
/**
* Work
*/
protected void doWork ()
{
m_summary = new StringBuffer();
//
wakeup();
dynamicPriority();
sendAlerts();
//
int no = m_model.deleteLog();
m_summary.append("Logs deleted=").append(no);
//
MWorkflowProcessorLog pLog = new MWorkflowProcessorLog(m_model, m_summary.toString());
pLog.setReference("#" + String.valueOf(p_runCount)
+ " - " + TimeUtil.formatElapsed(new Timestamp(p_startWork)));
pLog.save();
} // doWork
/**
* Continue Workflow After Sleep
*/
private void wakeup()
{
String sql = "SELECT * "
+ "FROM AD_WF_Activity a "
+ "WHERE Processed='N' AND WFState='OS'" // suspended
+ " AND EndWaitTime > SysDate"
+ " AND AD_Client_ID=?"
+ " AND EXISTS (SELECT * FROM AD_Workflow wf "
+ " INNER JOIN AD_WF_Node wfn ON (wf.AD_Workflow_ID=wfn.AD_Workflow_ID) "
+ "WHERE a.AD_WF_Node_ID=wfn.AD_WF_Node_ID"
+ " AND wfn.Action='Z'" // sleeping
+ " AND wf.AD_WorkflowProcessor_ID IS NULL OR wf.AD_WorkflowProcessor_ID=?)";
PreparedStatement pstmt = null;
int count = 0;
int countEMails = 0;
try
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setInt (1, m_model.getAD_Client_ID());
pstmt.setInt (2, m_model.getAD_WorkflowProcessor_ID());
ResultSet rs = pstmt.executeQuery ();
while (rs.next ())
{
MWFActivity activity = new MWFActivity (getCtx(), rs, null);
activity.setWFState (StateEngine.STATE_Completed);
// saves and calls MWFProcess.checkActivities();
count++;
}
rs.close ();
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
log.log(Level.SEVERE, "wakeup", e);
}
m_summary.append("Wakeup #").append(count).append (" - ");
} // wakeup
/**
* Set/Increase Priority dynamically
*/
private void dynamicPriority()
{
// suspened activities with dynamic priority node
String sql = "SELECT * "
+ "FROM AD_WF_Activity a "
+ "WHERE Processed='N' AND WFState='OS'" // suspended
+ " AND EXISTS (SELECT * FROM AD_Workflow wf"
+ " INNER JOIN AD_WF_Node wfn ON (wf.AD_Workflow_ID=wfn.AD_Workflow_ID) "
+ "WHERE a.AD_WF_Node_ID=wfn.AD_WF_Node_ID AND wf.AD_WorkflowProcessor_ID=?"
+ " AND wfn.DynPriorityUnit IS NOT NULL AND wfn.DynPriorityChange IS NOT NULL)";
PreparedStatement pstmt = null;
int count = 0;
int countEMails = 0;
try
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setInt(1, m_model.getAD_WorkflowProcessor_ID());
ResultSet rs = pstmt.executeQuery ();
while (rs.next ())
{
MWFActivity activity = new MWFActivity (getCtx(), rs, null);
if (activity.getDynPriorityStart() == 0)
activity.setDynPriorityStart(activity.getPriority());
long ms = System.currentTimeMillis() - activity.getCreated().getTime();
MWFNode node = activity.getNode();
int prioDiff = node.calculateDynamicPriority ((int)(ms / 1000));
activity.setPriority(activity.getDynPriorityStart() + prioDiff);
activity.save();
count++;
}
rs.close ();
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
log.log(Level.SEVERE, sql, e);
}
m_summary.append("DynPriority #").append(count).append (" - ");
// Clean-up
try
{
if (pstmt != null)
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
pstmt = null;
}
} // setPriority
/**
* Send Alerts
*/
private void sendAlerts()
{
// Alert over Priority
if (m_model.getAlertOverPriority() > 0)
{
String sql = "SELECT * "
+ "FROM AD_WF_Activity a "
+ "WHERE Processed='N' AND WFState='OS'" // suspended
+ " AND Priority >= ?" // ##1
+ " AND (DateLastAlert IS NULL";
if (m_model.getRemindDays() > 0)
sql += " OR (DateLastAlert+" + m_model.getRemindDays()
+ ") < SysDate";
sql += ") AND EXISTS (SELECT * FROM AD_Workflow wf "
+ " INNER JOIN AD_WF_Node wfn ON (wf.AD_Workflow_ID=wfn.AD_Workflow_ID) "
+ "WHERE a.AD_WF_Node_ID=wfn.AD_WF_Node_ID"
+ " AND wf.AD_WorkflowProcessor_ID IS NULL OR wf.AD_WorkflowProcessor_ID=?)";
int count = 0;
int countEMails = 0;
try
{
PreparedStatement pstmt = DB.prepareStatement(sql, null);
pstmt.setInt (1, m_model.getAlertOverPriority());
pstmt.setInt (2, m_model.getAD_WorkflowProcessor_ID());
ResultSet rs = pstmt.executeQuery();
while (rs.next())
{
MWFActivity activity = new MWFActivity (getCtx(), rs, null);
boolean escalate = activity.getDateLastAlert() != null;
countEMails += sendEmail (activity, "ActivityOverPriority",
escalate, true);
activity.setDateLastAlert(new Timestamp(System.currentTimeMillis()));
activity.save();
count++;
}
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, "(Priority) - " + sql, e);
}
m_summary.append("OverPriority #").append(count);
if (countEMails > 0)
m_summary.append(" (").append(countEMails).append(" EMail)");
m_summary.append (" - ");
} // Alert over Priority
/**
* Over End Wait
*/
String sql = "SELECT * "
+ "FROM AD_WF_Activity a "
+ "WHERE Processed='N' AND WFState='OS'" // suspended
+ " AND EndWaitTime > SysDate"
+ " AND (DateLastAlert IS NULL";
if (m_model.getRemindDays() > 0)
sql += " OR (DateLastAlert+" + m_model.getRemindDays()
+ ") < SysDate";
sql += ") AND EXISTS (SELECT * FROM AD_Workflow wf "
+ " INNER JOIN AD_WF_Node wfn ON (wf.AD_Workflow_ID=wfn.AD_Workflow_ID) "
+ "WHERE a.AD_WF_Node_ID=wfn.AD_WF_Node_ID"
+ " AND wfn.Action<>'Z'" // not sleeping
+ " AND wf.AD_WorkflowProcessor_ID IS NULL OR wf.AD_WorkflowProcessor_ID=?)";
PreparedStatement pstmt = null;
int count = 0;
int countEMails = 0;
try
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setInt(1, m_model.getAD_WorkflowProcessor_ID());
ResultSet rs = pstmt.executeQuery ();
while (rs.next ())
{
MWFActivity activity = new MWFActivity (getCtx(), rs, null);
boolean escalate = activity.getDateLastAlert() != null;
countEMails += sendEmail (activity, "ActivityEndWaitTime",
escalate, false);
activity.setDateLastAlert(new Timestamp(System.currentTimeMillis()));
activity.save();
count++;
}
rs.close ();
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
log.log(Level.SEVERE, "(EndWaitTime) - " + sql, e);
}
m_summary.append("EndWaitTime #").append(count);
if (countEMails > 0)
m_summary.append(" (").append(countEMails).append(" EMail)");
m_summary.append (" - ");
/**
* Send inactivity alerts
*/
if (m_model.getInactivityAlertDays() > 0)
{
sql = "SELECT * "
+ "FROM AD_WF_Activity a "
+ "WHERE Processed='N' AND WFState='OS'" // suspended
+ " AND (Updated+" + m_model.getInactivityAlertDays() + ") < SysDate"
+ " AND (DateLastAlert IS NULL";
if (m_model.getRemindDays() > 0)
sql += " OR (DateLastAlert+" + m_model.getRemindDays()
+ ") < SysDate";
sql += ") AND EXISTS (SELECT * FROM AD_Workflow wf "
+ " INNER JOIN AD_WF_Node wfn ON (wf.AD_Workflow_ID=wfn.AD_Workflow_ID) "
+ "WHERE a.AD_WF_Node_ID=wfn.AD_WF_Node_ID"
+ " AND wf.AD_WorkflowProcessor_ID IS NULL OR wf.AD_WorkflowProcessor_ID=?)";
count = 0;
countEMails = 0;
try
{
pstmt = DB.prepareStatement(sql, null);
pstmt.setInt (1, m_model.getAD_WorkflowProcessor_ID());
ResultSet rs = pstmt.executeQuery();
while (rs.next())
{
MWFActivity activity = new MWFActivity (getCtx(), rs, null);
boolean escalate = activity.getDateLastAlert() != null;
countEMails += sendEmail (activity, "ActivityInactivity",
escalate, false);
activity.setDateLastAlert(new Timestamp(System.currentTimeMillis()));
activity.save();
count++;
}
rs.close();
pstmt.close();
}
catch (SQLException e)
{
log.log(Level.SEVERE, "(Inactivity): " + sql, e);
}
m_summary.append("Inactivity #").append(count);
if (countEMails > 0)
m_summary.append(" (").append(countEMails).append(" EMail)");
m_summary.append (" - ");
} // Inactivity
// Clean-up
try
{
if (pstmt != null)
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
pstmt = null;
}
} // sendAlerts
/**
* Send Alert EMail
* @param activity activity
* @param AD_Message message
* @param toProcess true if to process owner
* @param toSupervisor true if to Supervisor
* @return number of mails sent
*/
private int sendEmail (MWFActivity activity, String AD_Message,
boolean toProcess, boolean toSupervisor)
{
if (m_client == null || m_client.getAD_Client_ID() != activity.getAD_Client_ID())
m_client = MClient.get(getCtx(), activity.getAD_Client_ID());
MWFProcess process = new MWFProcess (getCtx(), activity.getAD_WF_Process_ID(), null);
String subjectVar = activity.getNode().getName();
String message = activity.getTextMsg();
if (message == null || message.length() == 0)
message = process.getTextMsg();
File pdf = null;
PO po = activity.getPO();
if (po instanceof DocAction)
{
message = ((DocAction)po).getDocumentInfo() + "\n" + message;
pdf = ((DocAction)po).createPDF();
}
// Inactivity Alert: Workflow Activity {0}
String subject = Msg.getMsg(m_client.getAD_Language(), AD_Message,
new Object[] {subjectVar});
// Prevent duplicates
ArrayList<Integer> list = new ArrayList<Integer>();
int counter = 0;
// To Activity Owner
if (m_client.sendEMail(activity.getAD_User_ID(), subject, message, pdf))
counter++;
list.add (new Integer(activity.getAD_User_ID()));
// To Process Owner
if (toProcess
&& process.getAD_User_ID() != activity.getAD_User_ID())
{
if (m_client.sendEMail(process.getAD_User_ID(), subject, message, pdf))
counter++;
list.add (new Integer(process.getAD_User_ID()));
}
// To Activity Responsible
MWFResponsible responsible = MWFResponsible.get(getCtx(), activity.getAD_WF_Responsible_ID());
counter += sendAlertToResponsible (responsible, list, process,
subject, message, pdf);
// To Process Responsible
if (toProcess
&& process.getAD_WF_Responsible_ID() != activity.getAD_WF_Responsible_ID())
{
responsible = MWFResponsible.get(getCtx(), process.getAD_WF_Responsible_ID());
counter += sendAlertToResponsible (responsible, list, process,
subject, message, pdf);
}
// Processor SuperVisor
if (toSupervisor
&& m_model.getSupervisor_ID() != 0
&& !list.contains(new Integer(m_model.getSupervisor_ID())))
{
if (m_client.sendEMail(m_model.getSupervisor_ID(), subject, message, pdf))
counter++;
list.add (new Integer(m_model.getSupervisor_ID()));
}
return counter;
} // sendAlert
/**
* Send Alert To Responsible
* @param responsible responsible
* @param list list of already sent users
* @param process process
* @param subject subject
* @param message message
* @param pdf optional pdf
* @return number of mail sent
*/
private int sendAlertToResponsible (MWFResponsible responsible,
ArrayList<Integer> list, MWFProcess process,
String subject, String message, File pdf)
{
int counter = 0;
if (responsible.isInvoker())
;
// Human
else if (MWFResponsible.RESPONSIBLETYPE_Human.equals(responsible.getResponsibleType())
&& responsible.getAD_User_ID() != 0
&& !list.contains(new Integer(responsible.getAD_User_ID())))
{
if (m_client.sendEMail(responsible.getAD_User_ID(), subject, message, pdf))
counter++;
list.add (new Integer(responsible.getAD_User_ID()));
}
// Org of the Document
else if (MWFResponsible.RESPONSIBLETYPE_Organization.equals(responsible.getResponsibleType()))
{
PO document = process.getPO();
if (document != null)
{
MOrgInfo org = MOrgInfo.get (getCtx(), document.getAD_Org_ID());
if (org.getSupervisor_ID() != 0
&& !list.contains(new Integer(org.getSupervisor_ID())))
{
if (m_client.sendEMail(org.getSupervisor_ID(), subject, message, pdf))
counter++;
list.add (new Integer(org.getSupervisor_ID()));
}
}
}
// Role
else if (MWFResponsible.RESPONSIBLETYPE_Role.equals(responsible.getResponsibleType())
&& responsible.getAD_Role_ID() != 0)
{
MUserRoles[] userRoles = MUserRoles.getOfRole(getCtx(), responsible.getAD_Role_ID());
for (int i = 0; i < userRoles.length; i++)
{
MUserRoles roles = userRoles[i];
if (!roles.isActive())
continue;
int AD_User_ID = roles.getAD_User_ID();
if (!list.contains(new Integer(AD_User_ID)))
{
if (m_client.sendEMail(AD_User_ID, subject, message, pdf))
counter++;
list.add (new Integer(AD_User_ID));
}
}
}
return counter;
} // sendAlertToResponsible
/**
* Get Server Info
* @return info
*/
public String getServerInfo()
{
return "#" + p_runCount + " - Last=" + m_summary.toString();
} // getServerInfo
} // WorkflowProcessor

View File

@ -0,0 +1,869 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.web;
import java.io.*;
import java.lang.management.*;
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.db.*;
import org.compiere.model.*;
import org.compiere.server.*;
import org.compiere.util.*;
/**
* Adempiere Server Monitor
*
* @author Jorg Janke
* @version $Id: AdempiereMonitor.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class AdempiereMonitor extends HttpServlet
{
/** Logger */
private static CLogger log = CLogger.getCLogger(AdempiereMonitor.class);
/** The Server */
private AdempiereServerMgr m_serverMgr = null;
/** Message */
private p m_message = null;
/**
* Get
* @param request request
* @param response response
* @throws javax.servlet.ServletException
* @throws java.io.IOException
*/
protected void doGet (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
m_message = null;
if (processLogParameter (request, response))
return;
if (processTraceParameter (request, response))
return;
if (processEMailParameter (request, response))
return;
if (processCacheParameter (request, response))
return;
//
if (processRunNowParameter (request))
;
else
processActionParameter (request);
createSummaryPage(request, response);
} // doGet
/**
* Post
* @param request request
* @param response response
* @throws ServletException
* @throws IOException
*/
protected void doPost (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
doGet(request, response);
} // doPost
/**
* Process Log Parameter and return log page
* @param request request
* @param response response
* @return true if it was a log request
* @throws ServletException
* @throws IOException
*/
private boolean processLogParameter (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String serverID = WebUtil.getParameter (request, "Log");
if (serverID == null || serverID.length() == 0)
return false;
log.info ("ServerID=" + serverID);
AdempiereServer server = m_serverMgr.getServer(serverID);
if (server == null)
{
m_message = new p();
m_message.addElement(new strong("Server not found: "));
m_message.addElement(serverID);
return false;
}
WebDoc doc = WebDoc.create ("Adempiere Server Monitor Log");
// Body
body b = doc.getBody();
//
p para = new p();
a link = new a ("adempiereMonitor#" + serverID, "Return");
para.addElement(link);
b.addElement(para);
//
b.addElement(new h2(server.getName()));
//
table table = new table();
table.setBorder(1);
table.setCellSpacing(2);
table.setCellPadding(2);
// Header
tr line = new tr();
line.addElement(new th().addElement("Created"));
line.addElement(new th().addElement("Summary"));
// line.addElement(new th().addElement("Error"));
line.addElement(new th().addElement("Reference"));
line.addElement(new th().addElement("TextMsg"));
// line.addElement(new th().addElement("Description"));
table.addElement(line);
AdempiereProcessorLog[] logs = server.getLogs();
for (int i = 0; i < logs.length; i++)
{
AdempiereProcessorLog pLog = logs[i];
line = new tr();
line.addElement(new td().addElement(WebEnv.getCellContent(pLog.getCreated())));
line.addElement(new td().addElement(WebEnv.getCellContent(pLog.getSummary())));
line.addElement(new td().addElement(WebEnv.getCellContent(pLog.getReference())));
line.addElement(new td().addElement(WebEnv.getCellContent(pLog.getTextMsg())));
table.addElement(line);
}
//
b.addElement(table);
link = new a ("#top", "Top");
b.addElement(link);
// fini
WebUtil.createResponse (request, response, this, null, doc, false);
return true;
} // processLogParameter
/**
* Process Run Parameter
* @param request request
* @return true if it was a Run request
* @throws ServletException
* @throws IOException
*/
private boolean processRunNowParameter (HttpServletRequest request)
throws ServletException, IOException
{
String serverID = WebUtil.getParameter (request, "RunNow");
if (serverID == null || serverID.length() == 0)
return false;
log.info ("ServerID=" + serverID);
AdempiereServer server = m_serverMgr.getServer(serverID);
if (server == null)
{
m_message = new p();
m_message.addElement(new strong("Server not found: "));
m_message.addElement(serverID);
return false;
}
//
server.runNow();
//
return true;
} // processRunParameter
/**
* Process Action Parameter
* @param request request
*/
private void processActionParameter (HttpServletRequest request)
{
String action = WebUtil.getParameter (request, "Action");
if (action == null || action.length() == 0)
return;
log.info ("Action=" + action);
try
{
boolean start = action.startsWith("Start");
m_message = new p();
String msg = (start ? "Started" : "Stopped") + ": ";
m_message.addElement(new strong(msg));
//
String serverID = action.substring(action.indexOf("_")+1);
boolean ok = false;
if (serverID.equals("All"))
{
if (start)
ok = m_serverMgr.startAll();
else
ok = m_serverMgr.stopAll();
m_message.addElement("All");
}
else
{
AdempiereServer server = m_serverMgr.getServer(serverID);
if (server == null)
{
m_message = new p();
m_message.addElement(new strong("Server not found: "));
m_message.addElement(serverID);
return;
}
else
{
if (start)
ok = m_serverMgr.start (serverID);
else
ok = m_serverMgr.stop (serverID);
m_message.addElement(server.getName());
}
}
m_message.addElement(ok ? " - OK" : " - Error!");
}
catch (Exception e)
{
m_message = new p();
m_message.addElement(new strong("Error processing parameter: " + action));
m_message.addElement(new br());
m_message.addElement(e.toString());
}
} // processActionParameter
/**
* Process Trace Parameter
* @param request request
* @param response response
* @return true if it was a trace request with output
* @throws ServletException
* @throws IOException
*/
private boolean processTraceParameter (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String traceCmd = WebUtil.getParameter (request, "Trace");
String traceLevel = WebUtil.getParameter (request, "TraceLevel");
if (traceLevel != null && traceLevel.length() > 0)
{
log.info ("New Level: " + traceLevel);
CLogMgt.setLevel(traceLevel);
Ini.setProperty(Ini.P_TRACELEVEL, traceLevel);
Ini.saveProperties(false);
return false;
}
if (traceCmd == null || traceCmd.length() == 0)
return false;
log.info ("Command: " + traceCmd);
CLogFile fileHandler = CLogFile.get (false, null, false);
//
if (traceCmd.equals("ROTATE"))
{
if (fileHandler != null)
fileHandler.rotateLog();
return false; // re-display
}
else if (traceCmd.equals("DELETE"))
{
File logDir = fileHandler.getLogDirectory();
if (logDir != null && logDir.isDirectory())
{
File[] logs = logDir.listFiles();
for (int i = 0; i < logs.length; i++)
{
String fileName = logs[i].getAbsolutePath();
if (fileName.equals(fileHandler.getFileName()))
continue;
if (logs[i].delete())
log.warning("Deleted: " + fileName);
else
log.warning("Not Deleted: " + fileName);
}
}
return false; // re-display
}
// Display current log File
if (fileHandler != null && fileHandler.getFileName().equals(traceCmd))
fileHandler.flush();
// Spool File
File file = new File (traceCmd);
if (!file.exists())
{
log.warning ("Did not find File: " + traceCmd);
return false;
}
if (file.length() == 0)
{
log.warning ("File Length=0: " + traceCmd);
return false;
}
// Stream Log
log.info ("Streaming: " + traceCmd);
try
{
long time = System.currentTimeMillis(); // timer start
int fileLength = (int)file.length();
int bufferSize = 2048; // 2k Buffer
byte[] buffer = new byte[bufferSize];
//
response.setContentType("text/plain");
response.setBufferSize(bufferSize);
response.setContentLength(fileLength);
//
FileInputStream fis = new FileInputStream(file);
ServletOutputStream out = response.getOutputStream ();
int read = 0;
while ((read = fis.read(buffer)) > 0)
out.write (buffer, 0, read);
out.flush();
out.close();
fis.close();
//
time = System.currentTimeMillis() - time;
double speed = (fileLength/1024) / ((double)time/1000);
log.info("length="
+ fileLength + " - "
+ time + " ms - "
+ speed + " kB/sec");
}
catch (IOException ex)
{
log.log(Level.SEVERE, "stream" + ex);
}
return true;
} // processTraceParameter
/**
* Process EMail Parameter
* @param request request
* @param response response
* @return true if it was a email request with output
* @throws ServletException
* @throws IOException
*/
private boolean processEMailParameter (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String email = WebUtil.getParameter (request, "EMail");
if (email == null || email.length() == 0)
return false;
int AD_Client_ID = -1;
try
{
AD_Client_ID = Integer.parseInt(email);
}
catch (Exception e)
{
log.warning("Parsing: " + email + " - " + e.toString());
}
if (AD_Client_ID < 0)
{
m_message = new p();
m_message.addElement("No EMail: " + email);
return false;
}
// log.info ("Test EMail: " + AD_Client_ID);
MClient client = MClient.get(new Properties(), AD_Client_ID);
log.info ("Test: " + client);
m_message = new p();
m_message.addElement(client.getName() + ": " + client.testEMail());
return false;
} // processEMailParameter
/**
* Process Cache Parameter
* @param request request
* @param response response
* @return true if it was a email request with output
* @throws ServletException
* @throws IOException
*/
private boolean processCacheParameter (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String cmd = WebUtil.getParameter (request, "CacheReset");
if (cmd == null || cmd.length() == 0)
return false;
String tableName = WebUtil.getParameter (request, "CacheTableName");
String record_ID = WebUtil.getParameter (request, "CacheRecord_ID");
m_message = new p();
try
{
if (tableName == null || tableName.length() == 0)
{
CacheMgt.get().reset();
m_message.addElement("Cache Reset: All");
}
else if (record_ID == null || record_ID.length() == 0)
{
CacheMgt.get().reset(tableName);
m_message.addElement("Cache Reset: " + tableName);
}
else
{
CacheMgt.get().reset(tableName, Integer.parseInt(record_ID));
m_message.addElement("Cache Reset: " + tableName + ", Record_ID=" + record_ID);
}
}
catch (Exception e)
{
log.severe(e.toString());
m_message.addElement("Error: " + e.toString());
}
return false; // continue
} // processEMailParameter
/**************************************************************************
* Create & Return Summary Page
* @param request request
* @param response response
* @throws ServletException
* @throws IOException
*/
private void createSummaryPage (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
WebDoc doc = WebDoc.create ("Adempiere Server Monitor");
// log.info("ServletConfig=" + getServletConfig());
// AdempiereServerGroup.get().dump();
// Body
body bb = doc.getBody();
// Message
if (m_message != null)
{
bb.addElement(new hr());
bb.addElement(m_message);
bb.addElement(new hr());
}
// Summary
table table = new table();
table.setBorder(1);
table.setCellSpacing(2);
table.setCellPadding(2);
//
tr line = new tr();
line.addElement(new th().addElement(Adempiere.getName()));
line.addElement(new td().addElement(Adempiere.getVersion()));
table.addElement(line);
line = new tr();
line.addElement(new th().addElement(Adempiere.getImplementationVendor()));
line.addElement(new td().addElement(Adempiere.getImplementationVersion()));
table.addElement(line);
line = new tr();
line.addElement(new th().addElement("Manager"));
line.addElement(new td().addElement(WebEnv.getCellContent(m_serverMgr.getDescription())));
table.addElement(line);
line = new tr();
line.addElement(new th().addElement("Start - Elapsed"));
line.addElement(new td().addElement(WebEnv.getCellContent(m_serverMgr.getStartTime())
+ " - " + TimeUtil.formatElapsed(m_serverMgr.getStartTime())));
table.addElement(line);
line = new tr();
line.addElement(new th().addElement("Servers"));
line.addElement(new td().addElement(WebEnv.getCellContent(m_serverMgr.getServerCount())));
table.addElement(line);
line = new tr();
line.addElement(new th().addElement("Last Updated"));
line.addElement(new td().addElement(new Timestamp(System.currentTimeMillis()).toString()));
table.addElement(line);
bb.addElement(table);
//
p para = new p();
a link = new a ("adempiereMonitor?Action=Start_All", "Start All");
para.addElement(link);
para.addElement(" - ");
link = new a ("adempiereMonitor?Action=Stop_All", "Stop All");
para.addElement(link);
para.addElement(" - ");
link = new a ("adempiereMonitor", "Refresh");
para.addElement(link);
bb.addElement(para);
// ***** Server Links *****
bb.addElement(new hr());
para = new p();
AdempiereServer[] servers = m_serverMgr.getAll();
for (int i = 0; i < servers.length; i++)
{
if (i > 0)
para.addElement(new br());
AdempiereServer server = servers[i];
link = new a ("#" + server.getServerID(), server.getName());
para.addElement(link);
font status = null;
if (server.isAlive())
status = new font().setColor(HtmlColor.GREEN).addElement(" (Running)");
else
status = new font().setColor(HtmlColor.RED).addElement(" (Stopped)");
para.addElement(status);
}
bb.addElement(para);
// **** Log Management ****
createLogMgtPage(bb);
// ***** Server Details *****
for (int i = 0; i < servers.length; i++)
{
AdempiereServer server = servers[i];
bb.addElement(new hr());
bb.addElement(new a().setName(server.getServerID()));
bb.addElement(new h2(server.getName()));
//
table = new table();
table.setBorder(1);
table.setCellSpacing(2);
table.setCellPadding(2);
// Status
line = new tr();
if (server.isAlive())
{
String msg = "Stop";
if (server.isInterrupted())
msg += " (Interrupted)";
link = new a ("adempiereMonitor?Action=Stop_" + server.getServerID(), msg);
if (server.isSleeping())
{
line.addElement(new th().addElement("Sleeping"));
line.addElement(new td().addElement(link));
}
else
{
line.addElement(new th().addElement("Running"));
line.addElement(new td().addElement(link));
}
table.addElement(line);
line = new tr();
line.addElement(new th().addElement("Start - Elapsed"));
line.addElement(new td().addElement(WebEnv.getCellContent(server.getStartTime())
+ " - " + TimeUtil.formatElapsed(server.getStartTime())));
}
else
{
String msg = "Start";
if (server.isInterrupted())
msg += " (Interrupted)";
line.addElement(new th().addElement("Not Started"));
link = new a ("adempiereMonitor?Action=Start_" + server.getServerID(), msg);
line.addElement(new td().addElement(link));
}
table.addElement(line);
//
line = new tr();
line.addElement(new th().addElement("Description"));
line.addElement(new td().addElement(WebEnv.getCellContent(server.getDescription())));
table.addElement(line);
//
line = new tr();
line.addElement(new th().addElement("Last Run"));
line.addElement(new td().addElement(WebEnv.getCellContent(server.getDateLastRun())));
table.addElement(line);
line = new tr();
line.addElement(new th().addElement("Info"));
line.addElement(new td().addElement(WebEnv.getCellContent(server.getServerInfo())));
table.addElement(line);
//
line = new tr();
line.addElement(new th().addElement("Next Run"));
td td = new td();
td.addElement(WebEnv.getCellContent(server.getDateNextRun(false)));
td.addElement(" - ");
link = new a ("adempiereMonitor?RunNow=" + server.getServerID(), "(Run Now)");
td.addElement(link);
line.addElement(td);
table.addElement(line);
//
line = new tr();
line.addElement(new th().addElement("Statistics"));
line.addElement(new td().addElement(server.getStatistics()));
table.addElement(line);
//
// Add table to Body
bb.addElement(table);
link = new a ("#top", "Top");
bb.addElement(link);
bb.addElement(" - ");
link = new a ("adempiereMonitor?Log=" + server.getServerID(), "Log");
bb.addElement(link);
bb.addElement(" - ");
link = new a ("adempiereMonitor", "Refresh");
bb.addElement(link);
}
// fini
WebUtil.createResponse (request, response, this, null, doc, false);
} // createSummaryPage
/**
* Add Log Management to page
* @param bb body
*/
private void createLogMgtPage (body bb)
{
bb.addElement(new hr());
// Ini Parameters
table table = new table();
table.setBorder(1);
table.setCellSpacing(2);
table.setCellPadding(2);
//
Properties ctx = new Properties();
MSystem system = MSystem.get(ctx);
tr line = new tr();
line.addElement(new th().addElement(system.getDBAddress()));
line.addElement(new td().addElement(Ini.getAdempiereHome()));
table.addElement(line);
// OS + Name
line = new tr();
String info = System.getProperty("os.name")
+ " " + System.getProperty("os.version");
String s = System.getProperty("sun.os.patch.level");
if (s != null && s.length() > 0)
info += " (" + s + ")";
line.addElement(new th().addElement(info));
info = system.getName();
if (system.getCustomPrefix() != null)
info += " (" + system.getCustomPrefix() + ")";
line.addElement(new td().addElement(info));
table.addElement(line);
// Java + email
line = new tr();
info = System.getProperty("java.vm.name")
+ " " + System.getProperty("java.vm.version");
line.addElement(new th().addElement(info));
line.addElement(new td().addElement(system.getUserName()));
table.addElement(line);
// DB + Instance
line = new tr();
CConnection cc = CConnection.get();
AdempiereDatabase db = cc.getDatabase();
info = db.getDescription();
line.addElement(new th().addElement(info));
line.addElement(new td().addElement(cc.getConnectionURL()));
// line.addElement(new td().addElement(system.getDBInstance()));
table.addElement(line);
// Processors/Support
line = new tr();
line.addElement(new th().addElement("Processor/Support"));
line.addElement(new td().addElement(system.getNoProcessors() + "/" + system.getSupportUnits()));
table.addElement(line);
// Memory
line = new tr();
MemoryMXBean memory = ManagementFactory.getMemoryMXBean();
line.addElement(new th().addElement("VM Memory"));
line.addElement(new td().addElement(new CMemoryUsage(memory.getNonHeapMemoryUsage()).toString()));
table.addElement(line);
line = new tr();
line.addElement(new th().addElement("Heap Memory"));
line.addElement(new td().addElement(new CMemoryUsage(memory.getHeapMemoryUsage()).toString()));
table.addElement(line);
// Runtime
line = new tr();
RuntimeMXBean rt = ManagementFactory.getRuntimeMXBean();
line.addElement(new th().addElement("Runtime " + rt.getName()));
line.addElement(new td().addElement(TimeUtil.formatElapsed(rt.getUptime())));
table.addElement(line);
// Threads
line = new tr();
ThreadMXBean th = ManagementFactory.getThreadMXBean();
line.addElement(new th().addElement("Threads " + th.getThreadCount()));
line.addElement(new td().addElement("Peak=" + th.getPeakThreadCount()
+ ", Demons=" + th.getDaemonThreadCount()
+ ", Total=" + th.getTotalStartedThreadCount()));
table.addElement(line);
// Cache Reset
line = new tr();
line.addElement(new th().addElement(CacheMgt.get().toStringX()));
line.addElement(new td().addElement(new a ("adempiereMonitor?CacheReset=Yes", "Reset Cache")));
table.addElement(line);
// Trace Level
line = new tr();
line.addElement(new th().addElement(new label("TraceLevel").addElement("Trace Log Level")));
form myForm = new form("adempiereMonitor", form.METHOD_POST, form.ENC_DEFAULT);
// LogLevel Selection
option[] options = new option[CLogMgt.LEVELS.length];
for (int i = 0; i < options.length; i++)
{
options[i] = new option(CLogMgt.LEVELS[i].getName());
options[i].addElement(CLogMgt.LEVELS[i].getName());
if (CLogMgt.LEVELS[i] == CLogMgt.getLevel())
options[i].setSelected(true);
}
select sel = new select("TraceLevel", options);
myForm.addElement(sel);
myForm.addElement(new input(input.TYPE_SUBMIT, "Set", "Set"));
line.addElement(new td().addElement(myForm));
table.addElement(line);
//
line = new tr();
CLogFile fileHandler = CLogFile.get (true, null, false);
line.addElement(new th().addElement("Trace File"));
line.addElement(new td().addElement(new a ("adempiereMonitor?Trace=" + fileHandler.getFileName(), "Current")));
table.addElement(line);
//
line = new tr();
line.addElement(new td().addElement(new a ("adempiereMonitor?Trace=ROTATE", "Rotate Trace Log")));
line.addElement(new td().addElement(new a ("adempiereMonitor?Trace=DELETE", "Delete all Trace Logs")));
table.addElement(line);
//
bb.addElement(table);
// List Log Files
p p = new p();
p.addElement(new b("All Log Files: "));
// All in dir
File logDir = fileHandler.getLogDirectory();
if (logDir != null && logDir.isDirectory())
{
File[] logs = logDir.listFiles();
for (int i = 0; i < logs.length; i++)
{
if (i != 0)
p.addElement(" - ");
String fileName = logs[i].getAbsolutePath();
a link = new a ("adempiereMonitor?Trace=" + fileName, fileName);
p.addElement(link);
int size = (int)(logs[i].length()/1024);
if (size < 1024)
p.addElement(" (" + size + "k)");
else
p.addElement(" (" + size/1024 + "M)");
}
}
bb.addElement(p);
// Clients and Web Stores
table = new table();
table.setBorder(1);
table.setCellSpacing(2);
table.setCellPadding(2);
//
line = new tr();
MClient[] clients = MClient.getAll(ctx);
line.addElement(new th().addElement("Client #" + clients.length + " - EMail Test:"));
p = new p();
for (int i = 0; i < clients.length; i++)
{
MClient client = clients[i];
if (i > 0)
p.addElement(" - ");
p.addElement(new a("adempiereMonitor?EMail=" + client.getAD_Client_ID(), client.getName()));
}
if (clients.length == 0)
p.addElement("&nbsp;");
line.addElement(new td().addElement(p));
table.addElement(line);
//
line = new tr();
MStore[] wstores = MStore.getActive();
line.addElement(new th().addElement("Active Web Stores #" + wstores.length));
p = new p();
for (int i = 0; i < wstores.length; i++)
{
MStore store = wstores[i];
if (i > 0)
p.addElement(" - ");
a a = new a(store.getWebContext(), store.getName());
a.setTarget("t" + i);
p.addElement(a);
}
if (wstores.length == 0)
p.addElement("&nbsp;");
line.addElement(new td().addElement(p));
table.addElement(line);
//
bb.addElement(table);
} // createLogMgtPage
/**************************************************************************
* Init
* @param config config
* @throws javax.servlet.ServletException
*/
public void init (ServletConfig config) throws ServletException
{
WebEnv.initWeb(config);
log.info ("");
m_serverMgr = AdempiereServerMgr.get();
} // init
/**
* Destroy
*/
public void destroy ()
{
log.info ("destroy");
m_serverMgr = null;
} // destroy
/**
* Log error/warning
* @param message message
* @param e exception
*/
public void log (String message, Throwable e)
{
if (e == null)
log.warning (message);
log.log(Level.SEVERE, message, e);
} // log
/**
* Log debug
* @param message message
*/
public void log (String message)
{
log.fine(message);
} // log
/**
* Get Servlet Name
* @return servlet name
*/
public String getServletName ()
{
return "AdempiereMonitor";
} // getServletName
/**
* Get Servlet Info
* @return servlet info
*/
public String getServletInfo ()
{
return "Adempiere Server Monitor";
} // getServletName
} // AdempiereMonitor

View File

@ -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.web;
import java.io.*;
import java.util.logging.*;
import javax.servlet.*;
import javax.servlet.Filter;
import javax.servlet.http.*;
import org.compiere.model.*;
import org.compiere.util.*;
import sun.misc.*;
/**
* Adempiere Monitor Filter.
* Application Server independent check of username/password
*
* @author Jorg Janke
* @version $Id: AdempiereMonitorFilter.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $
*/
public class AdempiereMonitorFilter implements Filter
{
/**
* AdempiereMonitorFilter
*/
public AdempiereMonitorFilter ()
{
super ();
m_authorization = new Long (System.currentTimeMillis());
} // AdempiereMonitorFilter
/** Logger */
protected CLogger log = CLogger.getCLogger(getClass());
/** Authorization ID */
private static final String AUTHORIZATION = "AdempiereAuthorization";
/** Authorization Marker */
private Long m_authorization = null;
/**
* Init
* @param config configuration
* @throws ServletException
*/
public void init (FilterConfig config)
throws ServletException
{
log.info ("");
} // Init
/**
* Filter
* @param request request
* @param response response
* @param chain chain
* @throws IOException
* @throws ServletException
*/
public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
boolean error = false;
String errorPage = "/error.html";
boolean pass = false;
try
{
if (!(request instanceof HttpServletRequest && response instanceof HttpServletResponse))
{
request.getRequestDispatcher(errorPage).forward(request, response);
return;
}
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse)response;
// Previously checked
HttpSession session = req.getSession(true);
Long compare = (Long)session.getAttribute(AUTHORIZATION);
if (compare != null && compare.compareTo(m_authorization) == 0)
{
pass = true;
}
else if (checkAuthorization (req.getHeader("Authorization")))
{
session.setAttribute(AUTHORIZATION, m_authorization);
pass = true;
}
// --------------------------------------------
if (pass)
{
chain.doFilter(request, response);
}
else
{
resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
resp.setHeader("WWW-Authenticate", "BASIC realm=\"Adempiere Server\"");
}
return;
}
catch (Exception e)
{
log.log(Level.SEVERE, "filter", e);
}
request.getRequestDispatcher(errorPage).forward(request, response);
} // doFilter
/**
* Check Authorization
* @param authorization authorization
* @return true if authenticated
*/
private boolean checkAuthorization (String authorization)
{
if (authorization == null)
return false;
try
{
String userInfo = authorization.substring(6).trim();
BASE64Decoder decoder = new BASE64Decoder();
String namePassword = new String (decoder.decodeBuffer(userInfo));
// log.fine("checkAuthorization - Name:Password=" + namePassword);
int index = namePassword.indexOf(":");
String name = namePassword.substring(0, index);
String password = namePassword.substring(index+1);
MUser user = MUser.get(Env.getCtx(), name, password);
if (user == null)
{
log.warning ("User not found: '" + name + "/" + password + "'");
return false;
}
if (!user.isAdministrator())
{
log.warning ("Not a Sys Admin = " + name);
return false;
}
log.info ("Name=" + name);
return true;
}
catch (Exception e)
{
log.log(Level.SEVERE, "check", e);
}
return false;
} // check
/**
* Destroy
*/
public void destroy ()
{
log.info ("");
} // destroy
} // AdempiereMonitorFilter

View File

@ -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.web;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
/**
*
*
* @author Jorg Janke
* @version $Id: ServerStatus.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $
*/
public class ServerStatus extends HttpServlet
{
/**
* doGet
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
* @param arg0
* @param arg1
* @throws javax.servlet.ServletException
* @throws java.io.IOException
*/
protected void doGet (HttpServletRequest arg0, HttpServletResponse arg1)
throws ServletException, IOException
{
super.doGet (arg0, arg1);
}
/**
* doPost
* @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
* @param arg0
* @param arg1
* @throws javax.servlet.ServletException
* @throws java.io.IOException
*/
protected void doPost (HttpServletRequest arg0, HttpServletResponse arg1)
throws ServletException, IOException
{
// TODO Auto-generated method stub
super.doPost (arg0, arg1);
}
/**
* getServletInfo
* @see javax.servlet.Servlet#getServletInfo()
* @return servlet info
*/
public String getServletInfo ()
{
return super.getServletInfo ();
}
/**
* init
* @see javax.servlet.GenericServlet#init()
* @throws javax.servlet.ServletException
*/
public void init ()
throws ServletException
{
super.init ();
}
/**
* init
* @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
* @param arg0
* @throws javax.servlet.ServletException
*/
public void init (ServletConfig arg0)
throws ServletException
{
// TODO Auto-generated method stub
super.init (arg0);
}
} // ServerStatus

View File

@ -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.web;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import javax.naming.*;
import javax.sql.*;
import java.sql.*;
import org.compiere.interfaces.*;
/**
* Status Info Servlet
*
* @author Jorg Janke
* @version $Id: StatusInfo.java,v 1.3 2006/07/30 00:53:33 jjanke Exp $
*/
public class StatusInfo extends HttpServlet
{
static final private String CONTENT_TYPE = "text/html";
/**
* Initialize global variables
* @throws ServletException
*/
public void init() throws ServletException
{
getServletContext().log("StatusInfo.init");
}
/**
* Get
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>Status Info</title></head>");
out.println("<body>");
InitialContext context = null;
try
{
context = new InitialContext();
}
catch (Exception ex)
{
out.println("<p><b>" + ex + "</b></p>");
}
try
{
StatusHome statusHome = (StatusHome)context.lookup (StatusHome.JNDI_NAME);
Status status = statusHome.create();
out.println("<p>" + status.getStatus() + "</p>");
status.remove();
}
catch (Exception ex)
{
out.println("<p><b>" + ex + "</b></p>");
}
try
{
ServerHome serverHome = (ServerHome)context.lookup (ServerHome.JNDI_NAME);
Server server = serverHome.create();
out.println("<p>" + server.getStatus() + "</p>");
server.remove();
}
catch (Exception ex)
{
out.println("<p><b>" + ex + "</b></p>");
}
try
{
out.println("<h2>-- /</h2>");
NamingEnumeration ne = context.list("/");
while (ne.hasMore())
out.println("<br> " + ne.nextElement());
out.println("<h2>-- java</h2>");
ne = context.list("java:");
while (ne.hasMore())
out.println("<br> " + ne.nextElement());
out.println("<h2>-- ejb</h2>");
ne = context.list("ejb");
while (ne.hasMore())
out.println("<br> " + ne.nextElement());
//
out.println("<h2>-- DS</h2>");
DataSource ds = (DataSource)context.lookup("java:/OracleDS");
out.println("<br> DataSource " + ds.getClass().getName() + " LoginTimeout=" + ds.getLoginTimeout());
Connection con = ds.getConnection("adempiere","adempiere");
out.println("<br> Connection ");
getServletContext().log("Connection closed=" + con.isClosed());
DatabaseMetaData dbmd = con.getMetaData();
getServletContext().log("DB " + dbmd.getDatabaseProductName());
getServletContext().log("DB V " + dbmd.getDatabaseProductVersion());
getServletContext().log("Driver " + dbmd.getDriverName());
getServletContext().log("Driver V " + dbmd.getDriverVersion());
getServletContext().log("JDBC " + dbmd.getJDBCMajorVersion());
getServletContext().log("JDBC mV " + dbmd.getJDBCMinorVersion());
getServletContext().log("User " + dbmd.getUserName());
getServletContext().log("ANSI 92 " + dbmd.supportsANSI92FullSQL());
getServletContext().log("Connection Alter Table ADD" + dbmd.supportsAlterTableWithAddColumn());
getServletContext().log("Connection Alter Table DROP " + dbmd.supportsAlterTableWithDropColumn());
getServletContext().log("Connection DDL&DML " + dbmd.supportsDataDefinitionAndDataManipulationTransactions());
getServletContext().log("Connection CatalogsIn DML " + dbmd.supportsCatalogsInDataManipulation());
getServletContext().log("Connection Schema In DML " + dbmd.supportsSchemasInDataManipulation());
}
catch (Exception e)
{
out.println("<p><b>" + e + "</b></p>");
}
out.println("</body></html>");
}
/**
* Put - Processes Get
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doGet (request, response);
}
/**
* Destroy
*/
public void destroy()
{
getServletContext().log("StatusInfo.destroy");
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
serverRoot/src/web/C32.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
serverRoot/src/web/Logo.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- edited with XMLSPY v2004 rel. 4 U (http://www.xmlspy.com) by Jorg Janke (ComPiere, Inc.) -->
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>Adempiere Root</display-name>
<description>$Id: web.xml,v 1.1 2006/04/21 18:04:14 jjanke Exp $</description>
<context-param>
<param-name>ServerRoot</param-name>
<param-value>1</param-value>
</context-param>
<filter>
<filter-name>AdempiereMonitorFilter</filter-name>
<display-name>Adempiere Monitor Filter</display-name>
<filter-class>org.compiere.web.AdempiereMonitorFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AdempiereMonitorFilter</filter-name>
<url-pattern>/adempiereMonitor</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>JnlpDownloadServlet</servlet-name>
<display-name>JNLP Download Servlet</display-name>
<servlet-class>jnlp.sample.servlet.JnlpDownloadServlet</servlet-class>
<init-param>
<param-name>logLevel</param-name>
<param-value>INFORMATIONAL</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>StatusInfo</servlet-name>
<display-name>Server Status</display-name>
<description>Adempiere Server Status Info</description>
<servlet-class>org.compiere.web.StatusInfo</servlet-class>
</servlet>
<servlet>
<servlet-name>AdempiereMonitor</servlet-name>
<display-name>Adempiere Monitor</display-name>
<description>Adempiere Server Monitor</description>
<servlet-class>org.compiere.web.AdempiereMonitor</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JnlpDownloadServlet</servlet-name>
<url-pattern>*.jnlp</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>StatusInfo</servlet-name>
<url-pattern>/statusInfo</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AdempiereMonitor</servlet-name>
<url-pattern>/adempiereMonitor/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>15</session-timeout>
</session-config>
<mime-mapping>
<extension>jar</extension>
<mime-type>application/x-java-archive</mime-type>
</mime-mapping>
<mime-mapping>
<extension>jardiff</extension>
<mime-type>application/x-java-archive-diff</mime-type>
</mime-mapping>
<mime-mapping>
<extension>jnlp</extension>
<mime-type>application/x-java-jnlp-file</mime-type>
</mime-mapping>
<welcome-file-list>
<welcome-file>adempiere.html</welcome-file>
</welcome-file-list>
</web-app>

View File

@ -0,0 +1,242 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Adempiere Application Home</title>
<meta name="description" content="Adempiere Application Home">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link href="standard.css" rel="stylesheet" type="text/css">
<script language="JavaScript" type="text/javascript">
<!--
var javawsInstalled = false;
if (navigator.mimeTypes && navigator.mimeTypes.length)
javawsInstalled = navigator.mimeTypes['application/x-java-jnlp-file'];
else
isIE = true;
function insertLink (url, name)
{
if (javawsInstalled)
{
}
else
{
document.write("You need to install Java or configure Java Web Start");
document.write("<br>visit ");
document.write("<a href=\"http://java.sun.com/j2se/1.5.0/download.html\">" );
document.write("Java Installation");
document.write("</a><br>");
}
}
function MM_swapImgRestore() { //v3.0
var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}
function MM_preloadImages() { //v3.0
var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}
function MM_findObj(n, d) { //v4.01
var p,i,x; if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
if(!x && d.getElementById) x=d.getElementById(n); return x;
}
function MM_swapImage() { //v3.0
var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}
//-->
</script>
<script language="VBScript" type="text/vbscript">
on error resume next
If isIE Then
If Not(IsObject(CreateObject("JavaWebStart.IsInstalled"))) Then
javawsInstalled = false
Else
javawsInstalled = true
End If
End If
</script>
</head>
<body leftmargin="0" topmargin="0" onload="MM_preloadImages('adempiere_logo2.gif')" marginheight="0" marginwidth="0">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td background="header_banner.png" height="60">
<table border="0" cellpadding="5" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" valign="middle" width="477"></td>
<td align="left" valign="bottom"><a href="http://www.adempiere.org/"><img src="adempiere_logo.png" alt="Adempiere Logo" align="right" border="0" height="55" width="79"></a></td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td background="header_bar.jpg" height="60">
<table border="0" cellpadding="5" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" valign="middle"><font color="#ffffff" face="Arial, Helvetica, sans-serif" size="4">Welcome to the Adempiere 3.1.1 Home Page!<br>
</font></td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td height="77">
<table id="Adempiere" border="0" cellpadding="5" cellspacing="0" width="100%">
<!--DWLayoutTable-->
<tbody>
<tr>
<td bgcolor="#e9eef5" valign="top" width="23%">
<h2>
<font color="#000000">Web Start</font>
</h2>
</td>
<td bgcolor="#fbf8f1" width="77%">
<p>
<a href="adempiere.jnlp">
<img src="webstart.jpg" alt="Adempiere WebStart" align="right" border="0" height="57" width="237">
</a>
<script language="JavaScript" type="text/javascript">
<!--
insertLink ("adempiere.jnlp","Adempiere Web Start");
// -->
</script>
Install &nbsp;<a href="http://java.sun.com/j2se/1.5.0/download.html" target="sun">Java 1.5.0 JRE (Runtime)</a>
and press WebStart<br>
Check also WebStart <a href="http://www.adempiere.org/support/install/webStart.html" target="c">Details</a>.<br>
If you have trouble starting, try <a href="/admin/adempiereHome/adempiereDirect.jnlp">this</a>
(or via <a href="/admin/applet.html">Applet</a>)
</p>
</td>
</tr>
<tr>
<td bgcolor="#e9eef5">
<h2><font color="#000000">Local Install </font></h2>
</td>
<td bgcolor="#fbf8f1"><a href="/admin/adempiereHome/AdempiereClient.zip"><img src="zip.gif" alt="Adempiere Client Zip" align="right" border="0" height="32" width="32"></a>Install &nbsp;<a href="http://java.sun.com/j2se/1.5.0/download.html" target="sun">Java 1.5.0 JRE (Runtime)</a>; Download and extract the Adempiere Client <a href="/admin/adempiereHome/AdempiereClient.zip" title="Download Adempiere Client">zip</a> file on your Client;. <br>
Start Adempiere via RUN_Adempiere </td>
</tr>
<tr>
<td bgcolor="#e9eef5" valign="top">
<h2><font color="#000000">Web Application</font></h2>
</td>
<td bgcolor="#fbf8f1">
<p><a href="/adempiere">Adempiere Web Application Login (</a><a href="/adempiere/WStart">alternative)</a></p>
</td>
</tr>
<tr>
<td bgcolor="#e9eef5" valign="top">
<h2><font color="#000000">Self Service</font></h2>
</td>
<td bgcolor="#fbf8f1"><a href="/wstore/index.jsp">Web Store</a> - Send <a href="/wstore/request.jsp">Request</a></td>
</tr>
<tr>
<td bgcolor="#e9eef5" valign="top">
<h2><font color="#000000">Server Admin</font></h2>
</td>
<td bgcolor="#fbf8f1">
<p><a href="/admin/adempiereMonitor">Adempiere Server Managment</a>
<!--a href="/jmx-console" target="_blank">JBoss 3.2.3 Management Server Agent</a -->
</p>
</td>
</tr>
<tr>
<td bgcolor="#e9eef5" valign="top">
<h2><font color="#000000">Adempiere Support</font></h2>
</td>
<td bgcolor="#fbf8f1">
<p><a href="http://www.adempiere.com/wiki/">Wiki</a> - <a href="http://www.adempiere.com/wiki/index.php/Manual">Manual</a> - <a href="irc://irc.freenode.net/adempiere">IRC Channel</a><br>
<a href="http://sourceforge.net/forum/?group_id=176962">Forums</a> - <a href="http://sourceforge.net/tracker/?group_id=176962&amp;atid=879333">Support Requests</a></p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td background="footer_bar.gif" height="55">
<table border="0" cellpadding="5" cellspacing="0" width="100%">
<tbody>
<tr>
<td>&copy; Copyright 2006 Adempiere - All rights reserved - <a href="http://www.gnu.org/licenses/gpl.html" target="_blank">Adempiere License is GPL</a></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<h1>&nbsp;</h1>
</body>
</html>

View File

@ -0,0 +1,30 @@
<?xml version = "1.0" encoding = "UTF-8"?>
<jnlp spec = "1.5+" version = "2.5.3"
codebase = "$$context/adempiereHome"
href = "$$context/adempiere.jnlp">
<information>
<title>Adempiere Client 3.1.1 $$context</title>
<vendor>ComPiere, Inc.</vendor>
<homepage href = "http://www.adempiere.org"/>
<offline-allowed/>
<description>Adempiere ERP+CRM ($$context) - Smart Business Solution for Distribution and Service - globally</description>
<description kind = "short">Adempiere ERP+CRM ($$context)</description>
<description kind = "one-line">Adempiere ERP+CRM</description>
<description kind = "tooltip">Adempiere ERP+CRM ($$context)</description>
<icon href = "$$context/C32.gif"/>
<shortcut online="true">
<desktop/>
<menu submenu="Adempiere 3.1.1 $$context"/>
</shortcut>
</information>
<resources>
<j2se version = "1.5+" href = "http://java.sun.com/products/autodl/j2se" initial-heap-size = "32m" max-heap-size = "512m"/>
<jar href = "Adempiere.jar" main = "true" download = "eager"/>
<jar href = "AdempiereCLib.jar" main = "false" download = "eager"/>
<property name="adempiereJNLP" value="$$context"/>
</resources>
<application-desc main-class = "org.compiere.Adempiere"/>
<security>
<all-permissions/>
</security>
</jnlp>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -0,0 +1,81 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Adempiere Client Applet Start</title>
<link href="standard.css" rel="stylesheet" type="text/css" />
<style type="text/css">
<!--
.warning {
color: #FF0000;
font-weight: bold;
}
-->
</style>
</head>
<body>
<h1>Adempiere Client Applet Start</h1>
<p> Due to Browser incompatibilities, here is a list of different ways to start the Adempiere Java Client from a Browser.
This requires that your browser supports Java. <br/>
<a href="http://java.sun.com/j2se/1.5.0/docs/guide/plugin/developer_guide/using_tags.html" target="_blank">Applet Start Details</a>
</p>
<p class="warning">After the Adempiere Client started DO NOT close/use this window as that will crash the application!</p>
<table width="*" border="1" cellspacing="5" cellpadding="5">
<tr>
<td> Microsoft IE <br />
<object classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA"
width="200" height="100"
codebase="http://java.sun.com/products/plugin/autodl/jinstall-1_5_0-windows-i586.cab#Version=1,5,0,0">
<param name="code" value="org/adempiere/apps/AApplet.class" />
<param name="codebase" value="/admin/adempiereHome/" />
<param name="archive" value="Adempiere.jar,AdempiereCLib.jar"/>
<param name="type" value="application/x-java-applet;jpi-version=1.5.0" />
Internet Explorer: No Java 2 SDK, Standard Edition v 1.5.0 support for APPLET
</object>
</td>
</tr>
<tr>
<td><!--[if !IE]> -->
Non IE Browsers <br />
<object classid="java:org/adempiere/apps/AApplet.class"
archive="Adempiere.jar,AdempiereCLib.jar"
codebase="/admin/adempiereHome/"
width="200" height="100">
</object>
<!-- <![endif]-->
</td>
</tr>
<tr>
<td> Browsers supporting the EMBED tag <br />
Code commented out - modify source if required! <br />
<!-- start (add the < before the tag) --
embed type="application/x-java-applet;jpi-version=1.5.0"
width="200" height="100"
code="org/adempiere/apps/AApplet.class"
codebase="/admin/adempiereHome/"
archive="Adempiere.jar AdempiereCLib.jar"
pluginspage="http://java.sun.com/j2se/1.5/download.html">
<noembed>
Browsers supporting the EMBED tag: No Java 2 SDK, Standard Edition v 1.5.0 support for APPLET
</noembed>
</embed>
<!-- end -->
</td>
</tr>
<tr>
<td> Browsers supporting the APPLET tag <br />
Code commented out - modify source if required! <br />
<!-- start (add the < before the tag) --
applet code="org/adempiere/apps/AApplet.class"
archive="Adempiere.jar,AdempiereCLib.jar"
codebase="/admin/adempiereHome/"
width="200" height="200">
Browsers supporting the APPLET tag: No Java 2 SDK, Standard Edition v 1.5.0 support for APPLET
</applet>
<!-- end -->
</td>
</tr>
</table>
<p>&nbsp;</p>
</body>
</html>

View File

@ -0,0 +1,13 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Adempiere Server Error</title>
<link href="/standard.css" rel="stylesheet"/>
</head>
<body>
<h1>Adempiere Server Error </h1>
<p>The Adempiere Server encountered a unrecoverable error.</p>
<h2>Please notify the administrator.</h2>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,13 @@
<html>
<head>
<title>Adempiere</title>
<meta name="description" content="Adempiere Root Page">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<script language="JavaScript" type="text/javascript">
document.location='adempiere.html';
</script>
<p>Click <a href="adempiere.html">here</a> if not forwarded automatically</p>
</body>
</html>

View File

@ -0,0 +1,4 @@
User-agent: *
Disallow: /
Disallow: /adempiere
Disallow: /jmx-console

View File

@ -0,0 +1,151 @@
/* Adempiere Root (c) Jorg Janke */
/* $Id: standard.css,v 1.1 2006/04/21 18:04:14 jjanke Exp $ */
body{
background-color: #FFFFFF;
color: #000000;
font-size: 76%;
font-family: Verdana, Arial, sans-serif;
line-height: 1.3em;
}
a{
color: #3465a4;
text-decoration: none;
}
a:hover{
text-decoration: none;
}
h1{
color: #FF0000;
font-size: x-large;
margin-bottom: 10px;
margin-top: 0;
}
h2{
color: #000066;
font-size: large;
}
h3{
color: #0000CC;
font-size: medium;
font-style: normal;
font-weight: bold;
}
h4{
color: #6600CC;
font-size: medium;
font-style: italic;
}
h5{
color: #660099;
font-size: medium;
font-weight: normal;
}
h6{
font-size: larger;
font-weight: bold;
}
hr{
color: #000099;
padding-bottom: 0;
padding-top: 0;
}
p{
text-align: justify;
}
th{
background-color: #E6E6FA;
text-align: left;
}
caption{
color: #660099;
text-align: left;
font-style: italic;
font-weight: bolder;
}
.menuDetail{
color: #660099;
font-family: Arial,Helvetica,sans-serif;
font-size: 12px;
padding-bottom: 0;
padding-left: 20px;
padding-top: 0;
text-decoration: none;
}
.menuDetail:hover{
color: #660099;
font-family: Arial,Helvetica,sans-serif;
font-size: 12px;
padding-bottom: 0;
padding-left: 20px;
padding-top: 0;
text-decoration: none;
background-color: #99FFFF;
}
.menuMain{
color: #000066;
font-family: Arial,Helvetica,sans-serif;
font-size: 16px;
text-align: left;
text-decoration: none;
}
.menuMain:hover{
color: #000066;
font-family: Arial,Helvetica,sans-serif;
font-size: 16px;
text-align: left;
text-decoration: none;
background-color: #99FFFF;
}
.menuSub{
color: #000066;
font-family: Arial,Helvetica,sans-serif;
font-size: 14px;
padding-left: 10px;
text-align: left;
text-decoration: none;
}
.menuSub:hover{
color: #000066;
font-family: Arial,Helvetica,sans-serif;
font-size: 14px;
padding-left: 10px;
text-align: left;
text-decoration: none;
background-color: #99FFFF;
}
.Cerror{
background:#FF4A4A;
}
.Cmandatory{
background:#9DFFFF;
}
.Cbasket{
font-size: 9px;
display: inline;
}
#imgButton{
border-style:outset;
}
#imgButtonPressed{
border-style:inset;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
serverRoot/src/web/zip.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<project default="_generation_" name="XDoclet Generator">
<path id="xdoclet.classpath"><pathelement location="C:/Adempiere/adempiere-all2/serverRoot/lib"/>
<pathelement location="C:/Adempiere/adempiere-all2/serverRoot/src/web/WEB-INF/lib/jnlp-servlet.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/looks/lib"/>
<pathelement location="C:/Adempiere/adempiere-all2/tools/lib/local"/>
<pathelement location="C:/Adempiere/adempiere-all2/tools/lib/jstl.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/tools/lib/log4j.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/tools/lib/Verisign.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/tools/lib/saxpath.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/tools/lib/bsh-core-1.2b3.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/tools/lib/xdoclet.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/tools/lib/mail.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/tools/lib/activation.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/tools/lib/standard.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/tools/lib/ocrs12.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/dbPort/lib"/>
<pathelement location="C:/Adempiere/adempiere-all2/jboss/client/jbossall-client.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/jboss/server/adempiere/lib/javax.servlet.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/jboss/lib/jboss-jmx.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/jboss/lib/jboss-system.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/lib/oracle.jar"/>
<pathelement location="C:/eclipse/plugins/org.junit_3.8.1/junit.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/interfaces/Interfaces.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/lib/postgresql.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/server/lib"/>
<pathelement location="C:/Adempiere/adempiere-all2/base/lib"/>
<pathelement location="C:/Adempiere/adempiere-all2/print/lib"/>
<pathelement location="C:/Adempiere/adempiere-all2/lib/jPDFPrinterDemo.jar"/>
<pathelement location="C:/Adempiere/adempiere-all2/interfaces/classes"/>
<fileset dir="C:/eclipse/plugins/org.jboss.ide.eclipse.xdoclet.core_1.2.130/">
<include name="*.jar"/>
</fileset>
</path>
<target name="_generation_" depends=""/>
</project>