diff --git a/base/src/org/compiere/acct/Doc_MatchInv.java b/base/src/org/compiere/acct/Doc_MatchInv.java
index 40b04eec85..2eab4ed51b 100644
--- a/base/src/org/compiere/acct/Doc_MatchInv.java
+++ b/base/src/org/compiere/acct/Doc_MatchInv.java
@@ -45,9 +45,7 @@ import org.compiere.util.Env;
*
* FR [ 1840016 ] Avoid usage of clearing accounts - subject to C_AcctSchema.IsPostIfClearingEqual
* Avoid posting if both accounts Not Invoiced Receipts and Inventory Clearing are equal
- *
- * @author Bayu Cahya, Sistematika
- *
BF [ 2268355 ] Invoice price variance doesn't use transactional currency
+ * BF [ 2789949 ] Multicurrency in matching posting
*/
public class Doc_MatchInv extends Doc
{
@@ -257,6 +255,13 @@ public class Doc_MatchInv extends Doc
cr.setUser1_ID(m_invoiceLine.getUser1_ID());
cr.setUser2_ID(m_invoiceLine.getUser2_ID());
+ //AZ Goodwill
+ //Desc: Source Not Balanced problem because Currency is Difference - PO=CNY but AP=USD
+ //see also Fact.java: checking for isMultiCurrency()
+ if (dr.getC_Currency_ID() != cr.getC_Currency_ID())
+ setIsMultiCurrency(true);
+ //end AZ
+
// Avoid usage of clearing accounts
// If both accounts Not Invoiced Receipts and Inventory Clearing are equal
// then remove the posting
@@ -279,16 +284,12 @@ public class Doc_MatchInv extends Doc
// Invoice Price Variance difference
- // Bayu, Sistematika
- // BF [ 2268355 ] Invoice price variance doesn't use transactional currency
- BigDecimal ipv = cr.getSourceBalance().add(dr.getSourceBalance()).negate();
+ BigDecimal ipv = cr.getAcctBalance().add(dr.getAcctBalance()).negate();
if (ipv.signum() != 0)
{
- MInvoice m_invoice = m_invoiceLine.getParent();
- int C_Currency_ID = m_invoice.getC_Currency_ID();
FactLine pv = fact.createLine(null,
m_pc.getAccount(ProductCost.ACCTTYPE_P_IPV, as),
- C_Currency_ID, ipv);
+ 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());
@@ -297,7 +298,7 @@ public class Doc_MatchInv extends Doc
pv.setUser2_ID(m_invoiceLine.getUser2_ID());
}
log.fine("IPV=" + ipv + "; Balance=" + fact.getSourceBalance());
- // end Bayu
+
// Elaine 2008/6/20
/* Source move to MInvoice.createMatchInvCostDetail()
// Cost Detail Record - data from Expense/IncClearing (CR) record
diff --git a/base/src/org/compiere/acct/Fact.java b/base/src/org/compiere/acct/Fact.java
index ba204f3f8d..cc1d5af076 100644
--- a/base/src/org/compiere/acct/Fact.java
+++ b/base/src/org/compiere/acct/Fact.java
@@ -3,19 +3,19 @@
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
- * by the Free Software Foundation. This program is distributed in the hope *
- * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
- * See the GNU General Public License for more details. *
- * You should have received a copy of the GNU General Public License along *
- * with this program; if not, write to the Free Software Foundation, Inc., *
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
- * For the text or an alternative of this public license, you may reach us *
- * ComPiere, Inc., 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;
-
+ * by the Free Software Foundation. This program is distributed in the hope *
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ * See the GNU General Public License for more details. *
+ * You should have received a copy of the GNU General Public License along *
+ * with this program; if not, write to the Free Software Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
+ * For the text or an alternative of this public license, you may reach us *
+ * ComPiere, Inc., 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.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
@@ -30,44 +30,46 @@ import org.compiere.model.MElementValue;
import org.compiere.model.MFactAcct;
import org.compiere.util.CLogger;
import org.compiere.util.Env;
-
-/**
- * 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;
+
+/**
+ * Accounting Fact
+ *
+ * @author Jorg Janke
+ * @version $Id: Fact.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $
+ *
+ * BF [ 2789949 ] Multicurrency in matching posting
+ */
+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;
// Fix [ 1884676 ] Fact not setting transaction
- m_trxName = document.getTrxName();
- //
- 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 */
+ m_trxName = document.getTrxName();
+ //
+ 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 */
@@ -81,87 +83,87 @@ public final class Fact
/** Is Converted */
- private boolean m_converted = false;
-
- /** Lines */
- private ArrayList m_lines = new ArrayList();
-
-
- /**
- * 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
+ private boolean m_converted = false;
+
+ /** Lines */
+ private ArrayList m_lines = new ArrayList();
+
+
+ /**
+ * 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
+ */
+ public void add (FactLine line)
+ {
+ m_lines.add(line);
+ } // add
- /**
- * Add Fact Line
- * @param line fact line
- */
- public void add (FactLine line)
- {
- m_lines.add(line);
- } // add
-
/**
* Remove Fact Line
* @param line fact line
@@ -171,172 +173,177 @@ public final class Fact
m_lines.remove(line);
} // remove
- /**
- * 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);
-
+ /**
+ * 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()
+ {
+ //AZ Goodwill
+ // Multi-Currency documents are source balanced by definition
+ // No lines -> balanced
+ if (m_lines.size() == 0 || m_doc.isMultiCurrency())
+ 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
+ // 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()
+ {
+ //AZ Goodwill
+ // Multi-Currency documents are source balanced by definition
+ // No lines -> balanced
+ if (m_lines.size() == 0 || m_doc.isMultiCurrency())
+ 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)
{
@@ -344,66 +351,66 @@ public final class Fact
{
HashMap map = new HashMap();
// 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 = 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;
-
+ 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 = 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
@@ -411,256 +418,256 @@ public final class Fact
{
HashMap map = new HashMap();
// 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 = keys.next();
- Balance difference = 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())
- {
+ 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 = keys.next();
+ Balance difference = 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.setAccount(m_acctSchema, m_acctSchema.getDueTo_Acct(elementType));
- line.setAmtSource(m_doc.getC_Currency_ID(), Env.ZERO, difference.getPostBalance());
- }
- else
- {
+ line.setAmtSource(m_doc.getC_Currency_ID(), Env.ZERO, difference.getPostBalance());
+ }
+ else
+ {
line.setAccount(m_acctSchema, m_acctSchema.getDueFrom_Acct(elementType));
- line.setAmtSource(m_doc.getC_Currency_ID(), difference.getPostBalance(), Env.ZERO);
- }
- }
- else
- {
- if (difference.isReversal())
- {
+ line.setAmtSource(m_doc.getC_Currency_ID(), difference.getPostBalance(), Env.ZERO);
+ }
+ }
+ else
+ {
+ if (difference.isReversal())
+ {
line.setAccount(m_acctSchema, m_acctSchema.getDueFrom_Acct(elementType));
- line.setAmtSource(m_doc.getC_Currency_ID(), difference.getPostBalance(), Env.ZERO);
- }
- else
- {
+ line.setAmtSource(m_doc.getC_Currency_ID(), difference.getPostBalance(), Env.ZERO);
+ }
+ else
+ {
line.setAccount(m_acctSchema, m_acctSchema.getDueTo_Acct(elementType));
- line.setAmtSource(m_doc.getC_Currency_ID(), Env.ZERO, difference.getPostBalance());
- }
- }
- 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
- */
+ line.setAmtSource(m_doc.getC_Currency_ID(), Env.ZERO, difference.getPostBalance());
+ }
+ }
+ 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
@@ -751,62 +758,62 @@ public final class Fact
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)
+ } // distribute
+
+ /**************************************************************************
+ * String representation
+ * @return String
+ */
+ public String toString()
{
- m_trxName = 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
-
- /**
+ 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)
+ {
+ m_trxName = 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
*/
@@ -814,96 +821,96 @@ public final class Fact
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
-
+ } // 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
\ No newline at end of file