📄 fact.java
字号:
/******************************************************************************
* The contents of this file are subject to the Compiere License Version 1.1
* ("License"); You may not use this file except in compliance with the License
* You may obtain a copy of the License at http://www.compiere.org/license.html
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
* The Original Code is Compiere ERP & CRM Smart Business Solution. The Initial
* Developer of the Original Code is Jorg Janke. Portions created by Jorg Janke
* are Copyright (C) 1999-2005 Jorg Janke.
* All parts are Copyright (C) 1999-2005 ComPiere, Inc. All Rights Reserved.
* Contributor(s): ______________________________________.
*****************************************************************************/
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.12 2005/11/01 16:38:56 jjanke Exp $
*/
public final class Fact
{
/**
* Constructor
* @param document pointer to document
* @param acctSchema Account Schema to create accounts
* @param defaultPostingType the default Posting type (actual,..) for this posting
*/
public Fact (Doc document, MAcctSchema acctSchema, String defaultPostingType)
{
m_doc = document;
m_acctSchema = acctSchema;
m_postingType = defaultPostingType;
//
log.config(toString());
} // Fact
/** Log */
private CLogger log = CLogger.getCLogger(getClass());
/** Document */
private Doc m_doc = null;
/** Accounting Schema */
private MAcctSchema m_acctSchema = null;
/** Transaction */
private String m_trxName;
/** Posting Type */
private String m_postingType = null;
/** Actual Balance Type */
public static final String POST_Actual = MFactAcct.POSTINGTYPE_Actual;
/** Budget Balance Type */
public static final String POST_Budget = MFactAcct.POSTINGTYPE_Budget;;
/** Encumbrance Posting */
public static final String POST_Commitment = MFactAcct.POSTINGTYPE_Commitment;
/** Encumbrance Posting */
public static final String POST_Reservation = MFactAcct.POSTINGTYPE_Reservation;
/** Is Converted */
private boolean m_converted = false;
/** Lines */
private ArrayList<FactLine> m_lines = new ArrayList<FactLine>();
/**
* Dispose
*/
public void dispose()
{
m_lines.clear();
m_lines = null;
} // dispose
/**
* Create and convert Fact Line.
* Used to create a DR and/or CR entry
*
* @param docLine the document line or null
* @param account if null, line is not created
* @param C_Currency_ID the currency
* @param debitAmt debit amount, can be null
* @param creditAmt credit amount, can be null
* @return Fact Line
*/
public FactLine createLine (DocLine docLine, MAccount account,
int C_Currency_ID, BigDecimal debitAmt, BigDecimal creditAmt)
{
// log.fine("createLine - " + account + " - Dr=" + debitAmt + ", Cr=" + creditAmt);
// Data Check
if (account == null)
{
log.info("No account for " + docLine
+ ": Amt=" + debitAmt + "/" + creditAmt
+ " - " + toString());
return null;
}
//
FactLine line = new FactLine (m_doc.getCtx(), m_doc.get_Table_ID(),
m_doc.get_ID(),
docLine == null ? 0 : docLine.get_ID(), m_trxName);
// Set Info & Account
line.setDocumentInfo(m_doc, docLine);
line.setPostingType(m_postingType);
line.setAccount(m_acctSchema, account);
// Amounts - one needs to not zero
if (!line.setAmtSource(C_Currency_ID, debitAmt, creditAmt))
{
if (docLine == null || docLine.getQty() == null || docLine.getQty().signum() == 0)
{
log.fine("Both amounts & qty = 0/Null - " + docLine
+ " - " + toString());
return null;
}
log.fine("Both amounts = 0/Null, Qty=" + docLine.getQty() + " - " + docLine
+ " - " + toString());
}
// Convert
line.convert();
// Optionally overwrite Acct Amount
if (docLine != null
&& (docLine.getAmtAcctDr() != null || docLine.getAmtAcctCr() != null))
line.setAmtAcct(docLine.getAmtAcctDr(), docLine.getAmtAcctCr());
//
log.fine(line.toString());
add(line);
return line;
} // createLine
/**
* Add Fact Line
* @param line fact line
*/
void add (FactLine line)
{
m_lines.add(line);
} // add
/**
* Create and convert Fact Line.
* Used to create either a DR or CR entry
*
* @param docLine Document Line or null
* @param accountDr Account to be used if Amt is DR balance
* @param accountCr Account to be used if Amt is CR balance
* @param C_Currency_ID Currency
* @param Amt if negative Cr else Dr
* @return FactLine
*/
public FactLine createLine (DocLine docLine, MAccount accountDr, MAccount accountCr,
int C_Currency_ID, BigDecimal Amt)
{
if (Amt.signum() < 0)
return createLine (docLine, accountCr, C_Currency_ID, null, Amt.abs());
else
return createLine (docLine, accountDr, C_Currency_ID, Amt, null);
} // createLine
/**
* Create and convert Fact Line.
* Used to create either a DR or CR entry
*
* @param docLine Document line or null
* @param account Account to be used
* @param C_Currency_ID Currency
* @param Amt if negative Cr else Dr
* @return FactLine
*/
public FactLine createLine (DocLine docLine, MAccount account,
int C_Currency_ID, BigDecimal Amt)
{
if (Amt.signum() < 0)
return createLine (docLine, account, C_Currency_ID, null, Amt.abs());
else
return createLine (docLine, account, C_Currency_ID, Amt, null);
} // createLine
/**
* Is Posting Type
* @param PostingType - see POST_*
* @return true if document is posting type
*/
public boolean isPostingType (String PostingType)
{
return m_postingType.equals(PostingType);
} // isPostingType
/**
* Is converted
* @return true if converted
*/
public boolean isConverted()
{
return m_converted;
} // isConverted
/**
* Get AcctSchema
* @return AcctSchema
*/
public MAcctSchema getAcctSchema()
{
return m_acctSchema;
} // getAcctSchema
/**************************************************************************
* Are the lines Source Balanced
* @return true if source lines balanced
*/
public boolean isSourceBalanced()
{
// No lines -> balanded
if (m_lines.size() == 0)
return true;
BigDecimal balance = getSourceBalance();
boolean retValue = balance.signum() == 0;
if (retValue)
log.finer(toString());
else
log.warning ("NO - Diff=" + balance + " - " + toString());
return retValue;
} // isSourceBalanced
/**
* Return Source Balance
* @return source balance
*/
protected BigDecimal getSourceBalance()
{
BigDecimal result = Env.ZERO;
for (int i = 0; i < m_lines.size(); i++)
{
FactLine line = (FactLine)m_lines.get(i);
result = result.add (line.getSourceBalance());
}
// log.fine("getSourceBalance - " + result.toString());
return result;
} // getSourceBalance
/**
* Create Source Line for Suspense Balancing.
* Only if Suspense Balancing is enabled and not a multi-currency document
* (double check as otherwise the rule should not have fired)
* If not balanced create balancing entry in currency of the document
* @return FactLine
*/
public FactLine balanceSource()
{
if (!m_acctSchema.isSuspenseBalancing() || m_doc.isMultiCurrency())
return null;
BigDecimal diff = getSourceBalance();
log.finer("Diff=" + diff);
// new line
FactLine line = new FactLine (m_doc.getCtx(), m_doc.get_Table_ID(),
m_doc.get_ID(), 0, m_trxName);
line.setDocumentInfo(m_doc, null);
line.setPostingType(m_postingType);
// Amount
if (diff.signum() < 0) // negative balance => DR
line.setAmtSource(m_doc.getC_Currency_ID(), diff.abs(), Env.ZERO);
else // positive balance => CR
line.setAmtSource(m_doc.getC_Currency_ID(), Env.ZERO, diff);
// Account
line.setAccount(m_acctSchema, m_acctSchema.getSuspenseBalancing_Acct());
// Convert
line.convert();
//
log.fine(line.toString());
m_lines.add(line);
return line;
} // balancingSource
/**************************************************************************
* Are all segments balanced
* @return true if segments are balanced
*/
public boolean isSegmentBalanced()
{
if (m_lines.size() == 0)
return true;
MAcctSchemaElement[] elements = m_acctSchema.getAcctSchemaElements();
// check all balancing segments
for (int i = 0; i < elements.length; i++)
{
MAcctSchemaElement ase = elements[i];
if (ase.isBalanced() && !isSegmentBalanced (ase.getElementType()))
return false;
}
return true;
} // isSegmentBalanced
/**
* Is Source Segment balanced.
* @param segmentType - see AcctSchemaElement.SEGMENT_*
* Implemented only for Org
* Other sensible candidates are Project, User1/2
* @return true if segments are balanced
*/
public boolean isSegmentBalanced (String segmentType)
{
if (segmentType.equals(MAcctSchemaElement.ELEMENTTYPE_Organization))
{
HashMap<Integer,BigDecimal> map = new HashMap<Integer,BigDecimal>();
// Add up values by key
for (int i = 0; i < m_lines.size(); i++)
{
FactLine line = (FactLine)m_lines.get(i);
Integer key = new Integer(line.getAD_Org_ID());
BigDecimal bal = line.getSourceBalance();
BigDecimal oldBal = (BigDecimal)map.get(key);
if (oldBal != null)
bal = bal.add(oldBal);
map.put(key, bal);
// System.out.println("Add Key=" + key + ", Bal=" + bal + " <- " + line);
}
// check if all keys are zero
Iterator values = map.values().iterator();
while (values.hasNext())
{
BigDecimal bal = (BigDecimal)values.next();
if (bal.signum() != 0)
{
map.clear();
log.warning ("(" + segmentType + ") NO - " + toString() + ", Balance=" + bal);
return false;
}
}
map.clear();
log.finer("(" + segmentType + ") - " + toString());
return true;
}
log.finer("(" + segmentType + ") (not checked) - " + toString());
return true;
} // isSegmentBalanced
/**
* Balance all segments.
* - For all balancing segments
* - For all segment values
* - If balance <> 0 create dueTo/dueFrom line
* overwriting the segment value
*/
public void balanceSegments()
{
MAcctSchemaElement[] elements = m_acctSchema.getAcctSchemaElements();
// check all balancing segments
for (int i = 0; i < elements.length; i++)
{
MAcctSchemaElement ase = elements[i];
if (ase.isBalanced())
balanceSegment (ase.getElementType());
}
} // balanceSegments
/**
* Balance Source Segment
* @param elementType segment element type
*/
private void balanceSegment (String elementType)
{
// no lines -> balanced
if (m_lines.size() == 0)
return;
log.fine ("(" + elementType + ") - " + toString());
// Org
if (elementType.equals(MAcctSchemaElement.ELEMENTTYPE_Organization))
{
HashMap<Integer,Balance> map = new HashMap<Integer,Balance>();
// Add up values by key
for (int i = 0; i < m_lines.size(); i++)
{
FactLine line = (FactLine)m_lines.get(i);
Integer key = new Integer(line.getAD_Org_ID());
// BigDecimal balance = line.getSourceBalance();
Balance oldBalance = (Balance)map.get(key);
if (oldBalance == null)
{
oldBalance = new Balance (line.getAmtSourceDr(), line.getAmtSourceCr());
map.put(key, oldBalance);
}
else
oldBalance.add(line.getAmtSourceDr(), line.getAmtSourceCr());
// log.info ("Key=" + key + ", Balance=" + balance + " - " + line);
}
// Create entry for non-zero element
Iterator keys = map.keySet().iterator();
while (keys.hasNext())
{
Integer key = (Integer)keys.next();
Balance difference = (Balance)map.get(key);
log.info (elementType + "=" + key + ", " + difference);
//
if (!difference.isZeroBalance())
{
// Create Balancing Entry
FactLine line = new FactLine (m_doc.getCtx(), m_doc.get_Table_ID(),
m_doc.get_ID(), 0, m_trxName);
line.setDocumentInfo(m_doc, null);
line.setPostingType(m_postingType);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -