KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > compiere > acct > Fact


1 /******************************************************************************
2  * The contents of this file are subject to the Compiere License Version 1.1
3  * ("License"); You may not use this file except in compliance with the License
4  * You may obtain a copy of the License at http://www.compiere.org/license.html
5  * Software distributed under the License is distributed on an "AS IS" basis,
6  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
7  * the specific language governing rights and limitations under the License.
8  * The Original Code is Compiere ERP & CRM Business Solution
9  * The Initial Developer of the Original Code is Jorg Janke and ComPiere, Inc.
10  * Portions created by Jorg Janke are Copyright (C) 1999-2001 Jorg Janke, parts
11  * created by ComPiere are Copyright (C) ComPiere, Inc.; All Rights Reserved.
12  * Contributor(s): ______________________________________.
13  *****************************************************************************/

14 package org.compiere.acct;
15
16 import java.util.*;
17 import java.math.*;
18 import java.sql.*;
19
20 import org.apache.log4j.Logger;
21 import org.compiere.util.Env;
22 import org.compiere.model.*;
23
24 /**
25  * Accounting Fact
26  *
27  * @author Jorg Janke
28  * @version $Id: Fact.java,v 1.18 2003/07/22 06:28:03 jjanke Exp $
29  */

30 public final class Fact
31 {
32     /**
33      * Constructor
34      * @param document pointer to document
35      * @param acctSchema Account Schema to create accounts
36      * @param defaultPostingType the default Posting type (actual,..) for this posting
37      */

38     public Fact (Doc document, AcctSchema acctSchema, String JavaDoc defaultPostingType)
39     {
40         m_doc = document;
41         m_acctSchema = acctSchema;
42         m_postingType = defaultPostingType;
43         m_docVO = m_doc.p_vo;
44         //
45
log.debug (toString());
46     } // Fact
47

48     /** Log */
49     private Logger log = Logger.getLogger(getClass());
50
51     /** Document */
52     private Doc m_doc = null;
53     /** Accounting Schema */
54     private AcctSchema m_acctSchema = null;
55
56     /** Posting Type */
57     private String JavaDoc m_postingType = null;
58
59     /** Actual Balance Type */
60     public static final String JavaDoc POST_Actual = "A";
61     /** Budget Balance Type */
62     public static final String JavaDoc POST_Budget = "B";
63     /** Encumbrance Posting */
64     public static final String JavaDoc POST_Commitment = "C";
65
66     /** Document VO */
67     private DocVO m_docVO = null;
68
69     /** Is Converted */
70     private boolean m_converted = false;
71
72     /** Lines */
73     private ArrayList m_lines = new ArrayList();
74
75
76     /**
77      * Dispose
78      */

79     public void dispose()
80     {
81         for (int i = 0; i < m_lines.size(); i++)
82             ((FactLine)m_lines.get(i)).dispose();
83         m_lines.clear();
84         m_lines = null;
85     } // dispose
86

87     /**
88      * Create and convert Fact Line.
89      * Used to create a DR and/or CR entry
90      *
91      * @param docLine the document line or null
92      * @param account if null, line is not created
93      * @param C_Currency_ID the currency
94      * @param debitAmt debit amount, can be null
95      * @param creditAmt credit amount, can be null
96      * @return Fact Line
97      */

98     public FactLine createLine (DocLine docLine, Account account,
99         int C_Currency_ID, BigDecimal debitAmt, BigDecimal creditAmt)
100     {
101     // log.debug ("createLine - " + account + " - Dr=" + debitAmt + ", Cr=" + creditAmt);
102

103         // Data Check
104
if (account == null)
105             return null;
106         //
107
FactLine line = new FactLine (m_docVO.AD_Table_ID, m_docVO.Record_ID,
108             docLine == null ? 0 : docLine.getTrxLine_ID());
109         // Set Info & Account
110
line.setDocumentInfo(m_docVO, docLine);
111         line.setAccount(m_acctSchema, account);
112
113         // Amounts - one needs to be both not zero
114
if (!line.setAmtSource(C_Currency_ID, debitAmt, creditAmt))
115             return null;
116         // Convert
117
line.convert(m_acctSchema.getC_Currency_ID(), m_docVO.DateAcct, m_acctSchema.getCurrencyRateType());
118         // Optionally overwrite Acct Amount
119
if (docLine != null && docLine.getAmtAcctDr() != null && docLine.getAmtAcctDr() != null)
120             line.setAmtAcct(docLine.getAmtAcctDr(), docLine.getAmtAcctCr());
121         // Info
122
line.setJournalInfo(m_docVO.GL_Budget_ID, m_docVO.GL_Category_ID);
123         line.setPostingType(m_postingType);
124         //
125
log.debug ("createLine - " + line.toString());
126         add(line);
127         return line;
128     } // createLine
129

130     /**
131      * Add Fact Line
132      * @param line fact line
133      */

134     void add (FactLine line)
135     {
136         m_lines.add(line);
137     } // add
138

139     /**
140      * Create and convert Fact Line.
141      * Used to create either a DR or CR entry
142      *
143      * @param docLine Document Line or null
144      * @param accountDr Account to be used if Amt is DR balance
145      * @param accountCr Account to be used if Amt is CR balance
146      * @param C_Currency_ID Currency
147      * @param Amt if negative Cr else Dr
148      * @return FactLine
149      */

150     public FactLine createLine (DocLine docLine, Account accountDr, Account accountCr,
151         int C_Currency_ID, BigDecimal Amt)
152     {
153         if (Amt.compareTo(Env.ZERO) < 0)
154             return createLine (docLine, accountCr, C_Currency_ID, null, Amt.abs());
155         else
156             return createLine (docLine, accountDr, C_Currency_ID, Amt, null);
157     } // createLine
158

159     /**
160      * Create and convert Fact Line.
161      * Used to create either a DR or CR entry
162      *
163      * @param docLine Document line or null
164      * @param account Account to be used
165      * @param C_Currency_ID Currency
166      * @param Amt if negative Cr else Dr
167      * @return FactLine
168      */

169     public FactLine createLine (DocLine docLine, Account account,
170         int C_Currency_ID, BigDecimal Amt)
171     {
172         if (Amt.compareTo(Env.ZERO) < 0)
173             return createLine (docLine, account, C_Currency_ID, null, Amt.abs());
174         else
175             return createLine (docLine, account, C_Currency_ID, Amt, null);
176     } // createLine
177

178     /**
179      * Is Posting Type
180      * @param PostingType - see POST_*
181      * @return true if document is posting type
182      */

183     public boolean isPostingType (String JavaDoc PostingType)
184     {
185         return m_postingType.equals(PostingType);
186     } // isPostingType
187

188     /**
189      * Is converted
190      * @return true if converted
191      */

192     public boolean isConverted()
193     {
194         return m_converted;
195     } // isConverted
196

197     /**
198      * Get AcctSchema
199      * @return AcctSchema
200      */

201     public AcctSchema getAcctSchema()
202     {
203         return m_acctSchema;
204     } // getAcctSchema
205

206     /*************************************************************************/
207
208     /**
209      * Are the lines Source Balanced
210      * @return true if source lines balanced
211      */

212     public boolean isSourceBalanced()
213     {
214         // No lines -> balanded
215
if (m_lines.size() == 0)
216             return true;
217         BigDecimal balance = getSourceBalance();
218         boolean retValue = balance.compareTo(Env.ZERO) == 0;
219         if (retValue)
220             log.debug ("isSourceBalanced - " + toString());
221         else
222             log.warn ("isSourceBalanced NO - " + toString() + ", Balance=" + balance);
223         return retValue;
224     } // isSourceBalanced
225

226     /**
227      * Return Source Balance
228      * @return source balance
229      */

230     protected BigDecimal getSourceBalance()
231     {
232         BigDecimal result = Env.ZERO;
233         for (int i = 0; i < m_lines.size(); i++)
234         {
235             FactLine line = (FactLine)m_lines.get(i);
236             result = result.add (line.getSourceBalance());
237         }
238     // log.debug ("getSourceBalance - " + result.toString());
239
return result;
240     } // getSourceBalance
241

242     /**
243      * Create Source Line for Suspense Balancing.
244      * Only if Suspense Balancing is enabled and not a multi-currency document
245      * (double check as otherwise the rule should not have fired)
246      * If not balanced create balancing entry in currency of the document
247      * @return FactLine
248      */

249     public FactLine balanceSource()
250     {
251         if (!m_acctSchema.isSuspenseBalancing() || m_docVO.MultiCurrency)
252             return null;
253         BigDecimal diff = getSourceBalance();
254         log.debug ("balanceSource = " + diff);
255
256         // new line
257
FactLine line = new FactLine (m_docVO.AD_Table_ID, m_docVO.Record_ID, 0);
258         line.setDocumentInfo(m_docVO, null);
259         line.setJournalInfo(m_docVO.GL_Budget_ID, m_docVO.GL_Category_ID);
260         line.setPostingType(m_postingType);
261
262         // Amount
263
if (diff.compareTo(Env.ZERO) < 0) // negative balance => DR
264
line.setAmtSource(m_docVO.C_Currency_ID, diff.abs(), Env.ZERO);
265         else // positive balance => CR
266
line.setAmtSource(m_docVO.C_Currency_ID, Env.ZERO, diff);
267         // Convert
268
line.convert(m_acctSchema.getC_Currency_ID(), m_docVO.DateAcct, m_acctSchema.getCurrencyRateType());
269         line.setAccount(m_acctSchema, m_acctSchema.getSuspenseBalancing_Acct());
270         //
271
log.debug ("balanceSource - " + line.toString());
272         m_lines.add(line);
273         return line;
274     } // balancingSource
275

276     /*************************************************************************/
277
278     /**
279      * Are all segments balanced
280      * @return true if segments are balanced
281      */

282     public boolean isSegmentBalanced()
283     {
284         if (m_lines.size() == 0)
285             return true;
286
287         ArrayList elementList = m_acctSchema.getAcctSchemaElementList();
288         int size = elementList.size();
289         // check all balancing segments
290
for (int i = 0; i < size; i++)
291         {
292             AcctSchemaElement ase = (AcctSchemaElement)elementList.get(i);
293             if (ase.isBalanced() && !isSegmentBalanced (ase.getSegmentType()))
294                 return false;
295         }
296         return true;
297     } // isSegmentBalanced
298

299     /**
300      * Is Source Segment balanced.
301      * @param segmentType - see AcctSchemaElement.SEGMENT_*
302      * Implemented only for Org
303      * Other sensible candidates are Project, User1/2
304      * @return true if segments are balanced
305      */

306     public boolean isSegmentBalanced (String JavaDoc segmentType)
307     {
308         if (segmentType.equals(AcctSchemaElement.SEGMENT_Org))
309         {
310             HashMap map = new HashMap();
311             // Add up values by key
312
for (int i = 0; i < m_lines.size(); i++)
313             {
314                 FactLine line = (FactLine)m_lines.get(i);
315                 Integer JavaDoc key = new Integer JavaDoc(line.getAD_Org_ID());
316                 BigDecimal bal = line.getSourceBalance();
317                 BigDecimal oldBal = (BigDecimal)map.get(key);
318                 if (oldBal != null)
319                     bal = bal.add(oldBal);
320                 map.put(key, bal);
321             // System.out.println("Add Key=" + key + ", Bal=" + bal + " <- " + line);
322
}
323             // check if all keys are zero
324
Iterator values = map.values().iterator();
325             while (values.hasNext())
326             {
327                 BigDecimal bal = (BigDecimal)values.next();
328                 if (bal.compareTo(Env.ZERO) != 0)
329                 {
330                     map.clear();
331                     log.warn ("isSegmentBalanced (" + segmentType + ") NO - " + toString() + ", Balance=" + bal);
332                     return false;
333                 }
334             }
335             map.clear();
336             log.debug ("isSegmentBalanced (" + segmentType + ") - " + toString());
337             return true;
338         }
339         log.debug ("isSegmentBalanced (" + segmentType + ") (not checked) - " + toString());
340         return true;
341     } // isSegmentBalanced
342

343     /**
344      * Balance all segments.
345      * - For all balancing segments
346      * - For all segment values
347      * - If balance <> 0 create dueTo/dueFrom line
348      * overwriting the segment value
349      */

350     public void balanceSegments()
351     {
352         log.debug("balanceSegments");
353         //
354
ArrayList elementList = m_acctSchema.getAcctSchemaElementList();
355         int size = elementList.size();
356         // check all balancing segments
357
for (int i = 0; i < size; i++)
358         {
359             AcctSchemaElement ase = (AcctSchemaElement)elementList.get(i);
360             if (ase.isBalanced())
361                 balanceSegment (ase.getSegmentType());
362         }
363     } // balanceSegments
364

365     /**
366      * Balance Source Segment
367      * @param segmentType segment type
368      */

369     private void balanceSegment (String JavaDoc segmentType)
370     {
371         // no lines -> balanced
372
if (m_lines.size() == 0)
373             return;
374
375         log.debug ("balanceSegment (" + segmentType + ") - " + toString());
376
377         // Org
378
if (segmentType.equals(AcctSchemaElement.SEGMENT_Org))
379         {
380             HashMap map = new HashMap();
381             // Add up values by key
382
for (int i = 0; i < m_lines.size(); i++)
383             {
384                 FactLine line = (FactLine)m_lines.get(i);
385                 Integer JavaDoc key = new Integer JavaDoc(line.getAD_Org_ID());
386                 BigDecimal bal = line.getSourceBalance();
387                 BigDecimal oldBal = (BigDecimal)map.get(key);
388                 if (oldBal != null)
389                     bal = bal.add(oldBal);
390                 map.put(key, bal);
391             }
392
393             // Create entry for non-zero element
394
Iterator keys = map.keySet().iterator();
395             while (keys.hasNext())
396             {
397                 Integer JavaDoc key = (Integer JavaDoc)keys.next();
398                 BigDecimal diff = (BigDecimal)map.get(key);
399                 //
400
if (diff.compareTo(Env.ZERO) != 0)
401                 {
402                     // Create Balancing Entry
403
FactLine line = new FactLine (m_docVO.AD_Table_ID, m_docVO.Record_ID, 0);
404                     line.setDocumentInfo(m_docVO, null);
405                     line.setJournalInfo(m_docVO.GL_Budget_ID, m_docVO.GL_Category_ID);
406                     line.setPostingType(m_postingType);
407                     // Amount & Account
408
if (diff.compareTo(Env.ZERO) < 0)
409                     {
410                         line.setAmtSource(m_docVO.C_Currency_ID, diff.abs(), Env.ZERO);
411                         line.setAccount(m_acctSchema, m_acctSchema.getDueFrom_Acct(segmentType));
412                     }
413                     else
414                     {
415                         line.setAmtSource(m_docVO.C_Currency_ID, Env.ZERO, diff.abs());
416                         line.setAccount(m_acctSchema, m_acctSchema.getDueTo_Acct(segmentType));
417                     }
418                     line.convert(m_acctSchema.getC_Currency_ID(), m_docVO.DateAcct, m_acctSchema.getCurrencyRateType());
419                     line.setAD_Org_ID(key.intValue());
420                     log.debug ("balanceSegment (" + segmentType + ") - " + toString());
421                     m_lines.add(line);
422                 }
423             }
424             map.clear();
425         }
426     } // balanceSegment
427

428     /*************************************************************************/
429
430     /**
431      * Are the lines Accounting Balanced
432      * @return true if accounting lines are balanced
433      */

434     public boolean isAcctBalanced()
435     {
436         // no lines -> balanced
437
if (m_lines.size() == 0)
438             return true;
439         BigDecimal balance = getAcctBalance();
440         boolean retValue = balance.compareTo(Env.ZERO) == 0;
441         if (retValue)
442             log.debug("isAcctBalanced - " + toString());
443         else
444             log.warn("isAcctBalanced NO - " + toString() + ", Balance=" + balance);
445         return retValue;
446     } // isAcctBalanced
447

448     /**
449      * Return Accounting Balance
450      * @return true if accounting lines are balanced
451      */

452     protected BigDecimal getAcctBalance()
453     {
454         BigDecimal result = Env.ZERO;
455         for (int i = 0; i < m_lines.size(); i++)
456         {
457             FactLine line = (FactLine)m_lines.get(i);
458             result = result.add(line.getAcctBalance());
459         }
460     // log.debug ("getAcctBalance " + result.toString());
461
return result;
462     } // getAcctBalance
463

464     /**
465      * Balance Accounting Currency.
466      * If the accounting currency is not balanced,
467      * if Currency balancing is enabled
468      * create a new line using the currency balancing account with zero source balance
469      * or
470      * adjust the line with the largest balance sheet account
471      * or if no balance sheet account exist, the line with the largest amount
472      * @return FactLine
473      */

474     public FactLine balanceAccounting()
475     {
476         BigDecimal diff = getAcctBalance();
477         log.debug ("balanceAccounting - " + toString() + ", Balance=" + diff);
478         FactLine line = null;
479
480         // Create Currency Entry
481
if (m_acctSchema.isCurrencyBalancing())
482         {
483             line = new FactLine (m_docVO.AD_Table_ID, m_docVO.Record_ID, 0);
484             line.setDocumentInfo(m_docVO, null);
485             line.setJournalInfo(m_docVO.GL_Budget_ID, m_docVO.GL_Category_ID);
486             line.setPostingType(m_postingType);
487
488             // Amount
489
line.setAmtSource(m_docVO.C_Currency_ID, Env.ZERO, Env.ZERO);
490             line.convert(m_acctSchema.getC_Currency_ID(), m_docVO.DateAcct, m_acctSchema.getCurrencyRateType());
491             if (diff.compareTo(Env.ZERO) < 0)
492                 line.setAmtAcct(diff.abs(), Env.ZERO);
493             else
494                 line.setAmtAcct(Env.ZERO, diff.abs());
495             line.setAccount(m_acctSchema, m_acctSchema.getCurrencyBalancing_Acct());
496             log.debug ("balanceAccounting - " + line.toString());
497             m_lines.add(line);
498         }
499         else
500         // Adjust biggest (Balance Sheet) line amount
501
{
502             BigDecimal BSamount = Env.ZERO;
503             FactLine BSline = null;
504             BigDecimal PLamount = Env.ZERO;
505             FactLine PLline = null;
506
507             // Find line
508
for (int i = 0; i < m_lines.size(); i++)
509             {
510                 FactLine l = (FactLine)m_lines.get(i);
511                 BigDecimal amt = l.getAcctBalance().abs();
512                 if (l.isBalanceSheet() && amt.compareTo(BSamount) > 0)
513                 {
514                     BSamount = amt;
515                     BSline = l;
516                 }
517                 else if (!l.isBalanceSheet() && amt.compareTo(PLamount) > 0)
518                 {
519                     PLamount = amt;
520                     PLline = l;
521                 }
522             }
523             if (BSline != null)
524                 line = BSline;
525             else
526                 line = PLline;
527             if (line == null)
528                 log.error ("balanceAccounting - No Line found");
529             else
530             {
531                 log.debug ("Adjusting Amt=" + diff.toString() + "; Line=" + line.toString());
532                 line.currencyCorrect(diff);
533                 log.debug ("balanceAccounting - " + line.toString());
534             }
535         } // correct biggest amount
536

537         // Debug info only
538
this.isAcctBalanced();
539
540         return line;
541     } // balanceAccounting
542

543     /*************************************************************************/
544
545     /**
546      * Correct Tax
547      */

548     public void createTaxCorrection()
549     {
550         log.debug ("createTaxCorrection - (NIY)" + toString());
551     } // correct Tax
552

553     /**
554      * Create Realized Gain/Loss
555      */

556     public void createRealizedGainLoss()
557     {
558         log.debug ("createRealizedGainLoss - (NIY)" + toString());
559     } // createRealizedGainLoss
560

561     /**
562      * String representation
563      * @return String
564      */

565     public String JavaDoc toString()
566     {
567         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("Fact[");
568         sb.append(m_doc.toString());
569         sb.append(",").append(m_acctSchema.toString());
570         sb.append(",PostType=").append(m_postingType);
571         sb.append("]");
572         return sb.toString();
573     } // toString
574

575     /**
576      * Get Lines
577      * @return FactLine Array
578      */

579     public FactLine[] getLines()
580     {
581         FactLine[] temp = new FactLine[m_lines.size()];
582         m_lines.toArray(temp);
583         return temp;
584     } // getLines
585

586     /**
587      * Save Fact
588      * @param con connection
589      * @return true if all lines were saved
590      */

591     public boolean save (Connection con)
592     {
593         // save Lines
594
for (int i = 0; i < m_lines.size(); i++)
595         {
596             FactLine fl = (FactLine)m_lines.get(i);
597             if (!fl.save(con)) // abort on first error
598
return false;
599         }
600         return true;
601     } // commit
602

603 } // Fact
604
Popular Tags