View Javadoc
1   /*
2    * Copyright 2008 The Kuali Foundation
3    * 
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.opensource.org/licenses/ecl2.php
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.sys.document.service.impl;
17  
18  import java.text.DecimalFormat;
19  
20  import org.apache.commons.lang.StringUtils;
21  import org.apache.log4j.Logger;
22  import org.kuali.ole.gl.service.impl.StringHelper;
23  import org.kuali.ole.sys.OLEConstants;
24  import org.kuali.ole.sys.businessobject.AccountingLine;
25  import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
26  import org.kuali.ole.sys.businessobject.SystemOptions;
27  import org.kuali.ole.sys.document.AccountingDocument;
28  import org.kuali.ole.sys.document.GeneralLedgerPendingEntrySource;
29  import org.kuali.ole.sys.document.service.AccountingDocumentRuleHelperService;
30  import org.kuali.ole.sys.document.service.DebitDeterminerService;
31  import org.kuali.ole.sys.service.OptionsService;
32  import org.kuali.rice.core.api.util.type.KualiDecimal;
33  
34  /**
35   * Default implementation of the DebitDeterminerService.
36   */
37  public class DebitDeterminerServiceImpl implements DebitDeterminerService {
38      private static Logger LOG = Logger.getLogger(DebitDeterminerServiceImpl.class);
39      protected static final String isDebitCalculationIllegalStateExceptionMessage = "an invalid debit/credit check state was detected";
40      protected static final String isErrorCorrectionIllegalStateExceptionMessage = "invalid (error correction) document not allowed";
41      protected static final String isInvalidLineTypeIllegalArgumentExceptionMessage = "invalid accounting line type";
42      
43      private AccountingDocumentRuleHelperService accountingDocumentRuleUtil;
44      private OptionsService optionsService;
45  
46      /**
47       * @see org.kuali.ole.sys.document.service.DebitDeterminerService#disallowErrorCorrectionDocumentCheck(org.kuali.ole.sys.document.GeneralLedgerPendingEntrySource)
48       */
49      public void disallowErrorCorrectionDocumentCheck(GeneralLedgerPendingEntrySource poster) {
50          LOG.debug("disallowErrorCorrectionDocumentCheck(AccountingDocumentRuleBase, AccountingDocument) - start");
51  
52          if (isErrorCorrection(poster)) {
53              throw new IllegalStateException(isErrorCorrectionIllegalStateExceptionMessage);
54          }
55  
56          LOG.debug("disallowErrorCorrectionDocumentCheck(AccountingDocumentRuleBase, AccountingDocument) - end");
57      }
58  
59      /**
60       * @see org.kuali.ole.sys.document.service.DebitDeterminerService#isAsset(org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail)
61       */
62      public boolean isAsset(GeneralLedgerPendingEntrySourceDetail postable) {
63          LOG.debug("isAsset(AccountingLine) - start");
64  
65          boolean returnboolean = isAssetTypeCode(accountingDocumentRuleUtil.getObjectCodeTypeCodeWithoutSideEffects(postable));
66          LOG.debug("isAsset(AccountingLine) - end");
67          return returnboolean;
68      }
69  
70      /**
71       * @see org.kuali.ole.sys.document.service.DebitDeterminerService#isAssetTypeCode(java.lang.String)
72       */
73      public boolean isAssetTypeCode(String objectTypeCode) {
74          LOG.debug("isAssetTypeCode(String) - start");
75  
76          boolean returnboolean = optionsService.getCurrentYearOptions().getFinancialObjectTypeAssetsCd().equals(objectTypeCode);
77          LOG.debug("isAssetTypeCode(String) - end");
78          return returnboolean;
79      }
80  
81      /**
82       * @see org.kuali.ole.sys.document.service.DebitDeterminerService#isDebitCode(java.lang.String)
83       */
84      public boolean isDebitCode(String debitCreditCode) {
85          LOG.debug("isDebitCode(String) - start");
86  
87          boolean returnboolean = StringUtils.equals(OLEConstants.GL_DEBIT_CODE, debitCreditCode);
88          LOG.debug("isDebitCode(String) - end");
89          return returnboolean;
90      }
91  
92      /**
93       * @see org.kuali.ole.sys.document.service.DebitDeterminerService#isDebitConsideringNothingPositiveOnly(org.kuali.ole.sys.document.GeneralLedgerPendingEntrySource, org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail)
94       */
95      public boolean isDebitConsideringNothingPositiveOnly(GeneralLedgerPendingEntrySource poster, GeneralLedgerPendingEntrySourceDetail postable) {
96          LOG.debug("isDebitConsideringNothingPositiveOnly(AccountingDocumentRuleBase, AccountingDocument, AccountingLine) - start");
97  
98          boolean isDebit = false;
99          KualiDecimal amount = postable.getAmount();
100         boolean isPositiveAmount = amount.isPositive();
101         // isDebit if income/liability/expense/asset and line amount is positive
102         if (isPositiveAmount && (isIncomeOrLiability(postable) || isExpenseOrAsset(postable))) {
103             isDebit = true;
104         }
105         else {
106             // non error correction
107             if (!isErrorCorrection(poster)) {
108                 throw new IllegalStateException(isDebitCalculationIllegalStateExceptionMessage);
109 
110             }
111             // error correction
112             else {
113                 isDebit = false;
114             }
115         }
116 
117         LOG.debug("isDebitConsideringNothingPositiveOnly(AccountingDocumentRuleBase, AccountingDocument, AccountingLine) - end");
118         return isDebit;
119     }
120 
121     /**
122      * @see org.kuali.ole.sys.document.service.DebitDeterminerService#isDebitConsideringSection(org.kuali.ole.sys.document.AccountingDocument, org.kuali.ole.sys.businessobject.AccountingLine)
123      */
124     public boolean isDebitConsideringSection(AccountingDocument accountingDocument, AccountingLine accountingLine) {
125         LOG.debug("isDebitConsideringSection(AccountingDocumentRuleBase, AccountingDocument, AccountingLine) - start");
126 
127         KualiDecimal amount = accountingLine.getAmount();
128         // zero amounts are not allowed
129         if (amount.isZero()) {
130             throw new IllegalStateException(isDebitCalculationIllegalStateExceptionMessage);
131         }
132         boolean isDebit = false;
133         boolean isPositiveAmount = accountingLine.getAmount().isPositive();
134         // source line
135         if (accountingLine.isSourceAccountingLine()) {
136             // income/liability/expense/asset
137             if (isIncomeOrLiability(accountingLine) || isExpenseOrAsset(accountingLine)) {
138                 isDebit = !isPositiveAmount;
139             }
140             else {
141                 throw new IllegalStateException(isDebitCalculationIllegalStateExceptionMessage);
142             }
143         }
144         // target line
145         else {
146             if (accountingLine.isTargetAccountingLine()) {
147                 if (isIncomeOrLiability(accountingLine) || isExpenseOrAsset(accountingLine)) {
148                     isDebit = isPositiveAmount;
149                 }
150                 else {
151                     throw new IllegalStateException(isDebitCalculationIllegalStateExceptionMessage);
152                 }
153             }
154             else {
155                 throw new IllegalArgumentException(isInvalidLineTypeIllegalArgumentExceptionMessage);
156             }
157         }
158 
159         LOG.debug("isDebitConsideringSection(AccountingDocumentRuleBase, AccountingDocument, AccountingLine) - end");
160         return isDebit;
161     }
162 
163     /**
164      * @see org.kuali.ole.sys.document.service.DebitDeterminerService#isDebitConsideringSectionAndTypePositiveOnly(org.kuali.ole.sys.document.AccountingDocument, org.kuali.ole.sys.businessobject.AccountingLine)
165      */
166     public boolean isDebitConsideringSectionAndTypePositiveOnly(AccountingDocument accountingDocument, AccountingLine accountingLine) {
167         LOG.debug("isDebitConsideringSectionAndTypePositiveOnly(AccountingDocumentRuleBase, AccountingDocument, AccountingLine) - start");
168 
169         boolean isDebit = false;
170         KualiDecimal amount = accountingLine.getAmount();
171         boolean isPositiveAmount = amount.isPositive();
172         // non error correction - only allow amount >0
173         if (!isPositiveAmount && !isErrorCorrection(accountingDocument)) {
174             throw new IllegalStateException(isDebitCalculationIllegalStateExceptionMessage);
175         }
176         // source line
177         if (accountingLine.isSourceAccountingLine()) {
178             // could write below block in one line using == as XNOR operator, but that's confusing to read:
179             // isDebit = (rule.isIncomeOrLiability(accountingLine) == isPositiveAmount);
180             if (isPositiveAmount) {
181                 isDebit = isIncomeOrLiability(accountingLine);
182             }
183             else {
184                 isDebit = isExpenseOrAsset(accountingLine);
185             }
186         }
187         // target line
188         else {
189             if (accountingLine.isTargetAccountingLine()) {
190                 if (isPositiveAmount) {
191                     isDebit = isExpenseOrAsset(accountingLine);
192                 }
193                 else {
194                     isDebit = isIncomeOrLiability(accountingLine);
195                 }
196             }
197             else {
198                 throw new IllegalArgumentException(isInvalidLineTypeIllegalArgumentExceptionMessage);
199             }
200         }
201 
202         LOG.debug("isDebitConsideringSectionAndTypePositiveOnly(AccountingDocumentRuleBase, AccountingDocument, AccountingLine) - end");
203         return isDebit;
204     }
205 
206     /**
207      * @see org.kuali.ole.sys.document.service.DebitDeterminerService#isDebitConsideringType(org.kuali.ole.sys.document.GeneralLedgerPendingEntrySource, org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail)
208      */
209     public boolean isDebitConsideringType(GeneralLedgerPendingEntrySource poster, GeneralLedgerPendingEntrySourceDetail postable) {
210         LOG.debug("isDebitConsideringType(AccountingDocumentRuleBase, AccountingDocument, AccountingLine) - start");
211 
212         KualiDecimal amount = postable.getAmount();
213         // zero amounts are not allowed
214         if (amount.isZero()) {
215             throw new IllegalStateException(isDebitCalculationIllegalStateExceptionMessage);
216         }
217         boolean isDebit = false;
218         boolean isPositiveAmount = postable.getAmount().isPositive();
219 
220         // income/liability
221         if (isIncomeOrLiability(postable)) {
222             isDebit = !isPositiveAmount;
223         }
224         // expense/asset
225         else {
226             if (isExpenseOrAsset(postable)) {
227                 isDebit = isPositiveAmount;
228             }
229             else {
230                 throw new IllegalStateException(isDebitCalculationIllegalStateExceptionMessage);
231             }
232         }
233 
234         LOG.debug("isDebitConsideringType(AccountingDocumentRuleBase, AccountingDocument, AccountingLine) - end");
235         return isDebit;
236     }
237 
238     /**
239      * @see org.kuali.ole.sys.document.service.DebitDeterminerService#isErrorCorrection(org.kuali.ole.sys.document.GeneralLedgerPendingEntrySource)
240      */
241     public boolean isErrorCorrection(GeneralLedgerPendingEntrySource poster) {
242         return StringUtils.isNotBlank(poster.getFinancialSystemDocumentHeader().getFinancialDocumentInErrorNumber());
243     }
244 
245     /**
246      * @see org.kuali.ole.sys.document.service.DebitDeterminerService#isExpense(org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail)
247      */
248     public boolean isExpense(GeneralLedgerPendingEntrySourceDetail postable) {
249         LOG.debug("isExpense(AccountingLine) - start");
250 
251         boolean returnboolean = accountingDocumentRuleUtil.isExpense(postable);
252         LOG.debug("isExpense(AccountingLine) - end");
253         return returnboolean;
254     }
255 
256     /**
257      * @see org.kuali.ole.sys.document.service.DebitDeterminerService#isExpenseOrAsset(org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail)
258      */
259     public boolean isExpenseOrAsset(GeneralLedgerPendingEntrySourceDetail postable) {
260         LOG.debug("isExpenseOrAsset(AccountingLine) - start");
261 
262         boolean returnboolean = isAsset(postable) || isExpense(postable);
263         LOG.debug("isExpenseOrAsset(AccountingLine) - end");
264         return returnboolean;
265     }
266 
267     /**
268      * @see org.kuali.ole.sys.document.service.DebitDeterminerService#isIncome(org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail)
269      */
270     public boolean isIncome(GeneralLedgerPendingEntrySourceDetail postable) {
271         LOG.debug("isIncome(AccountingLine) - start");
272 
273         boolean returnboolean = accountingDocumentRuleUtil.isIncome(postable);
274         LOG.debug("isIncome(AccountingLine) - end");
275         return returnboolean;
276     }
277 
278     /**
279      * @see org.kuali.ole.sys.document.service.DebitDeterminerService#isIncomeOrLiability(org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail)
280      */
281     public boolean isIncomeOrLiability(GeneralLedgerPendingEntrySourceDetail postable) {
282         LOG.debug("isIncomeOrLiability(AccountingLine) - start");
283 
284         boolean returnboolean = isLiability(postable) || isIncome(postable);
285         LOG.debug("isIncomeOrLiability(AccountingLine) - end");
286         return returnboolean;
287     }
288 
289     /**
290      * @see org.kuali.ole.sys.document.service.DebitDeterminerService#isLiability(org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail)
291      */
292     public boolean isLiability(GeneralLedgerPendingEntrySourceDetail postable) {
293         LOG.debug("isLiability(AccountingLine) - start");
294 
295         boolean returnboolean = isLiabilityTypeCode(accountingDocumentRuleUtil.getObjectCodeTypeCodeWithoutSideEffects(postable));
296         LOG.debug("isLiability(AccountingLine) - end");
297         return returnboolean;
298     }
299 
300     /**
301      * @see org.kuali.ole.sys.document.service.DebitDeterminerService#isLiabilityTypeCode(java.lang.String)
302      */
303     public boolean isLiabilityTypeCode(String objectTypeCode) {
304         LOG.debug("isLiabilityTypeCode(String) - start");
305 
306         boolean returnboolean = optionsService.getCurrentYearOptions().getFinObjectTypeLiabilitiesCode().equals(objectTypeCode);
307         LOG.debug("isLiabilityTypeCode(String) - end");
308         return returnboolean;
309     }
310 
311     public String getConvertedAmount(String objectType , String debitCreditCode , String amount ) {
312         SystemOptions systemOption = optionsService.getCurrentYearOptions();
313         
314         // If entries lack a debit and credit code that means they're budget entries and should already be signed appropriately + or -.
315         // so we should just be able to grab those without having to do any change.
316         if(StringHelper.isNullOrEmpty(debitCreditCode)) {
317             return amount;
318         }
319         
320         if(systemOption.getFinancialObjectTypeAssetsCd().equals(objectType)
321                 ||systemOption.getFinObjTypeExpendNotExpCode().equals(objectType)  
322                 ||systemOption.getFinObjTypeExpenditureexpCd().equals(objectType)
323                 ||systemOption.getFinObjTypeExpendNotExpCode().equals(objectType) 
324                 ||systemOption.getFinancialObjectTypeTransferExpenseCd().equals(objectType)) {
325            
326             if  (OLEConstants.GL_CREDIT_CODE.equals(debitCreditCode)) {
327                 amount = "-" + amount;
328             }   
329         }
330         else if (systemOption.getFinObjTypeCshNotIncomeCd().equals(objectType)
331                 || systemOption.getFinObjectTypeFundBalanceCd().equals(objectType)
332                 || systemOption.getFinObjectTypeIncomecashCode().equals(objectType)
333                 || systemOption.getFinObjTypeCshNotIncomeCd().equals(objectType)
334                 || systemOption.getFinObjectTypeLiabilitiesCode().equals(objectType)
335                 || systemOption.getFinancialObjectTypeTransferIncomeCd().equals(objectType)) {
336             if (OLEConstants.GL_DEBIT_CODE.equals(debitCreditCode)) {
337               amount = "-" + amount;
338             }
339           
340         }
341       
342         return amount;
343     }
344 
345 
346 
347 
348 
349 /**
350      * @see org.kuali.ole.sys.document.service.DebitDeterminerService#isRevenue(org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail)
351      */
352 public boolean isRevenue(GeneralLedgerPendingEntrySourceDetail postable) {
353         LOG.debug("isRevenue(AccountingLine) - start");
354 
355         boolean returnboolean = !isExpense(postable);
356         LOG.debug("isRevenue(AccountingLine) - end");
357         return returnboolean;
358 }
359 
360 /**
361      * Sets the accountingDocumentRuleUtils attribute value.
362      * @param accountingDocumentRuleUtils The accountingDocumentRuleUtils to set.
363      */
364 public void setAccountingDocumentRuleUtils(AccountingDocumentRuleHelperService accountingDocumentRuleUtil) {
365         this.accountingDocumentRuleUtil = accountingDocumentRuleUtil;
366 }
367 
368 /**
369      * Sets the optionsService attribute value.
370      * @param optionsService The optionsService to set.
371      */
372 public void setOptionsService(OptionsService optionsService) {
373         this.optionsService = optionsService;
374 }
375 
376 /**
377      * Gets the isDebitCalculationIllegalStateExceptionMessage attribute. 
378      * @return Returns the isDebitCalculationIllegalStateExceptionMessage.
379      */
380 public String getDebitCalculationIllegalStateExceptionMessage() {
381         return isDebitCalculationIllegalStateExceptionMessage;
382 }
383 
384 /**
385      * Gets the isErrorCorrectionIllegalStateExceptionMessage attribute. 
386      * @return Returns the isErrorCorrectionIllegalStateExceptionMessage.
387      */
388 public String getErrorCorrectionIllegalStateExceptionMessage() {
389         return isErrorCorrectionIllegalStateExceptionMessage;
390 }
391 
392 /**
393      * Gets the isInvalidLineTypeIllegalArgumentExceptionMessage attribute. 
394      * @return Returns the isInvalidLineTypeIllegalArgumentExceptionMessage.
395      */
396 public String getInvalidLineTypeIllegalArgumentExceptionMessage() {
397         return isInvalidLineTypeIllegalArgumentExceptionMessage;
398 }
399 
400     
401 }