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