Implemented FR [ 1696228 ] ModelValidator for BeforePost and AfterPost
Moved lots of sources and packages to base as discussed in forums
|
@ -21,7 +21,7 @@
|
||||||
<pathelement path="${classpath}"/>
|
<pathelement path="${classpath}"/>
|
||||||
<pathelement location="../tools/lib/j2ee.jar" />
|
<pathelement location="../tools/lib/j2ee.jar" />
|
||||||
<pathelement location="../JasperReports/CompiereJasper.jar" />
|
<pathelement location="../JasperReports/CompiereJasper.jar" />
|
||||||
<pathelement location="../dbPort/dbPort.jar" />
|
<pathelement location="../base/Base.jar" />
|
||||||
</path>
|
</path>
|
||||||
|
|
||||||
<target name="compile">
|
<target name="compile">
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
<path id="project.class.path">
|
<path id="project.class.path">
|
||||||
<pathelement path="${classpath}"/>
|
<pathelement path="${classpath}"/>
|
||||||
<pathelement path="${jar.path}/CCTools.jar"/>
|
<pathelement path="${jar.path}/CCTools.jar"/>
|
||||||
|
<pathelement path="${jar.path}/oracle.jar"/>
|
||||||
|
<pathelement path="${jar.path}/postgresql.jar"/>
|
||||||
|
<pathelement path="${jar.path}/jboss.jar"/>
|
||||||
<pathelement path="../dbPort/dbPort.jar"/>
|
<pathelement path="../dbPort/dbPort.jar"/>
|
||||||
<pathelement path="../looks/CLooks.jar"/>
|
<pathelement path="../looks/CLooks.jar"/>
|
||||||
<pathelement path="../print/Print.jar"/>
|
<pathelement path="../print/Print.jar"/>
|
||||||
|
@ -52,7 +55,7 @@
|
||||||
|
|
||||||
<target name="compile" depends="makedir">
|
<target name="compile" depends="makedir">
|
||||||
<!-- compile the java code from ${src} into ${build.dir} -->
|
<!-- compile the java code from ${src} into ${build.dir} -->
|
||||||
<javac srcdir="${src}" destdir="${build.dir}" deprecation="on" debug="on">
|
<javac fork="true" srcdir="${src}" destdir="${build.dir}" deprecation="on" debug="on" memoryinitialsize="512m" memorymaximumsize="512m">
|
||||||
<classpath refid="project.class.path"/>
|
<classpath refid="project.class.path"/>
|
||||||
</javac>
|
</javac>
|
||||||
<!-- copy all image & sound files from src to the build directory -->
|
<!-- copy all image & sound files from src to the build directory -->
|
||||||
|
|
Before Width: | Height: | Size: 972 B After Width: | Height: | Size: 972 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1013 B After Width: | Height: | Size: 1013 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 688 B After Width: | Height: | Size: 688 B |
Before Width: | Height: | Size: 689 B After Width: | Height: | Size: 689 B |
Before Width: | Height: | Size: 908 B After Width: | Height: | Size: 908 B |
Before Width: | Height: | Size: 901 B After Width: | Height: | Size: 901 B |
Before Width: | Height: | Size: 908 B After Width: | Height: | Size: 908 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,895 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Product: Adempiere ERP & CRM Smart Business Solution *
|
||||||
|
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms version 2 of the GNU General Public License as published *
|
||||||
|
* by the Free Software Foundation. This program is distributed in the hope *
|
||||||
|
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||||
|
* See the GNU General Public License for more details. *
|
||||||
|
* You should have received a copy of the GNU General Public License along *
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||||
|
* For the text or an alternative of this public license, you may reach us *
|
||||||
|
* ComPiere, Inc., 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 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());
|
||||||
|
//Modified Lines by Armen
|
||||||
|
//Old:
|
||||||
|
//BigDecimal allocationAccounted = null; // AR/AP balance corrected
|
||||||
|
BigDecimal allocationAccounted = Env.ZERO; // AR/AP balance corrected
|
||||||
|
//End of Modified Lines
|
||||||
|
|
||||||
|
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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,305 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Product: Adempiere ERP & CRM Smart Business Solution *
|
||||||
|
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms version 2 of the GNU General Public License as published *
|
||||||
|
* by the Free Software Foundation. This program is distributed in the hope *
|
||||||
|
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||||
|
* See the GNU General Public License for more details. *
|
||||||
|
* You should have received a copy of the GNU General Public License along *
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||||
|
* For the text or an alternative of this public license, you may reach us *
|
||||||
|
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
|
||||||
|
* or via info@compiere.org or http://www.compiere.org/license.html *
|
||||||
|
*****************************************************************************/
|
||||||
|
package org.compiere.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 InOut 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 = null;
|
||||||
|
MProduct product = line.getProduct();
|
||||||
|
//get costing method for product
|
||||||
|
String costingMethod = as.getCostingMethod();
|
||||||
|
MProductCategoryAcct pca = MProductCategoryAcct.get(getCtx(),
|
||||||
|
product.getM_Product_Category_ID(), as.getC_AcctSchema_ID(), getTrxName());
|
||||||
|
if (pca.getCostingMethod() != null)
|
||||||
|
costingMethod = pca.getCostingMethod();
|
||||||
|
if (MAcctSchema.COSTINGMETHOD_AveragePO.equals(costingMethod) ||
|
||||||
|
MAcctSchema.COSTINGMETHOD_LastPOPrice.equals(costingMethod) )
|
||||||
|
{
|
||||||
|
int C_OrderLine_ID = line.getC_OrderLine_ID();
|
||||||
|
MOrderLine orderLine = new MOrderLine (getCtx(), C_OrderLine_ID, getTrxName());
|
||||||
|
costs = orderLine.getPriceCost();
|
||||||
|
if (costs == null || costs.signum() == 0)
|
||||||
|
costs = orderLine.getPriceActual();
|
||||||
|
costs = costs.multiply(line.getQty());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
costs = line.getProductCosts(as, line.getAD_Org_ID(), false); // current costs
|
||||||
|
}
|
||||||
|
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(
|
||||||
|
//FYRACLE add pc. everywhere
|
||||||
|
"UPDATE M_Product_Costing pc "
|
||||||
|
+ "SET (CostAverageCumQty, CostAverageCumAmt)="
|
||||||
|
+ "(SELECT pc.CostAverageCumQty - SUM(il.MovementQty),"
|
||||||
|
+ " pc.CostAverageCumAmt - SUM(il.MovementQty*pc.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
|
|
@ -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
|
|
@ -0,0 +1,967 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Product: Adempiere ERP & CRM Smart Business Solution *
|
||||||
|
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms version 2 of the GNU General Public License as published *
|
||||||
|
* by the Free Software Foundation. This program is distributed in the hope *
|
||||||
|
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||||
|
* See the GNU General Public License for more details. *
|
||||||
|
* You should have received a copy of the GNU General Public License along *
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||||
|
* For the text or an alternative of this public license, you may reach us *
|
||||||
|
* ComPiere, Inc., 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");
|
||||||
|
//jz + " AND ROWNUM=1 AND i.C_Invoice_ID=").append(get_ID()).append(") ")
|
||||||
|
if (DB.isOracle()) //jz
|
||||||
|
{
|
||||||
|
sql.append(" AND ROWNUM=1 ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sql.append(" AND il.C_InvoiceLine_ID = (SELECT MIN(il1.C_InvoiceLine_ID) "
|
||||||
|
+ "FROM C_Invoice i1, C_InvoiceLine il1 "
|
||||||
|
+ "WHERE i1.C_Invoice_ID=il1.C_Invoice_ID"
|
||||||
|
+ " AND po.M_Product_ID=il1.M_Product_ID AND po.C_BPartner_ID=i1.C_BPartner_ID")
|
||||||
|
.append(" AND i1.C_Invoice_ID=").append(get_ID()).append(") ");
|
||||||
|
}
|
||||||
|
sql.append(" 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 il2" +
|
||||||
|
" WHERE il2.M_PRODUCT_ID=il.M_PRODUCT_ID AND 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
|
|
@ -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
|
|
@ -0,0 +1,251 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Product: Adempiere ERP & CRM Smart Business Solution *
|
||||||
|
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms version 2 of the GNU General Public License as published *
|
||||||
|
* by the Free Software Foundation. This program is distributed in the hope *
|
||||||
|
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||||
|
* See the GNU General Public License for more details. *
|
||||||
|
* You should have received a copy of the GNU General Public License along *
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||||
|
* For the text or an alternative of this public license, you may reach us *
|
||||||
|
* ComPiere, Inc., 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());
|
||||||
|
|
||||||
|
// Calculate PPV for standard costing
|
||||||
|
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();
|
||||||
|
|
||||||
|
//get standard cost and also makesure cost for other costing method is updated
|
||||||
|
BigDecimal costs = m_pc.getProductCosts(as, getAD_Org_ID(),
|
||||||
|
MAcctSchema.COSTINGMETHOD_StandardCosting, m_C_OrderLine_ID, false); // non-zero costs
|
||||||
|
|
||||||
|
if (MAcctSchema.COSTINGMETHOD_StandardCosting.equals(costingMethod))
|
||||||
|
{
|
||||||
|
// 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());
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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
|
|
@ -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
|
|
@ -0,0 +1,646 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Product: Adempiere ERP & CRM Smart Business Solution *
|
||||||
|
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms version 2 of the GNU General Public License as published *
|
||||||
|
* by the Free Software Foundation. This program is distributed in the hope *
|
||||||
|
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||||
|
* See the GNU General Public License for more details. *
|
||||||
|
* You should have received a copy of the GNU General Public License along *
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||||
|
* For the text or an alternative of this public license, you may reach us *
|
||||||
|
* ComPiere, Inc., 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
|
||||||
|
FactLine fl = null;
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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 ");
|
||||||
|
//jz + " AND ROWNUM=1 AND o.C_Order_ID=").append(get_ID()).append(") ")
|
||||||
|
if (DB.isOracle()) //jz
|
||||||
|
{
|
||||||
|
sql.append(" AND ROWNUM=1 ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sql.append(" AND ol.C_OrderLine_ID = (SELECT MIN(ol1.C_OrderLine_ID) "
|
||||||
|
+ "FROM C_Order o1, C_OrderLine ol1 "
|
||||||
|
+ "WHERE o1.C_Order_ID=ol1.C_Order_ID"
|
||||||
|
+ " AND po.M_Product_ID=ol1.M_Product_ID AND po.C_BPartner_ID=o1.C_BPartner_ID")
|
||||||
|
.append(" AND o1.C_Order_ID=").append(get_ID()).append(") ");
|
||||||
|
sql.append(" 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;
|
||||||
|
FactLine fl = null;
|
||||||
|
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);
|
||||||
|
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 ");
|
||||||
|
if (DB.isOracle()) //jz
|
||||||
|
{
|
||||||
|
sql.append(" AND ROWNUM=1 ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sql.append(" AND ol.C_OrderLine_ID = (SELECT MIN(ol1.C_OrderLine_ID) "
|
||||||
|
+ "FROM C_Order o1, C_OrderLine ol1 "
|
||||||
|
+ "WHERE o1.C_Order_ID=ol1.C_Order_ID"
|
||||||
|
+ " AND pc.M_Product_ID=ol1.M_Product_ID ")
|
||||||
|
.append(" AND o1.C_Order_ID=").append(get_ID()).append(") ");
|
||||||
|
sql.append(" 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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -0,0 +1,861 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Product: Adempiere ERP & CRM Smart Business Solution *
|
||||||
|
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms version 2 of the GNU General Public License as published *
|
||||||
|
* by the Free Software Foundation. This program is distributed in the hope *
|
||||||
|
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||||
|
* See the GNU General Public License for more details. *
|
||||||
|
* You should have received a copy of the GNU General Public License along *
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||||
|
* For the text or an alternative of this public license, you may reach us *
|
||||||
|
* ComPiere, Inc., 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);
|
||||||
|
|
||||||
|
// Account
|
||||||
|
line.setAccount(m_acctSchema, m_acctSchema.getSuspenseBalancing_Acct());
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
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
|
|
@ -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
|
|
@ -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
|
Before Width: | Height: | Size: 590 B After Width: | Height: | Size: 590 B |
Before Width: | Height: | Size: 642 B After Width: | Height: | Size: 642 B |