View Javadoc
1   /*
2    * The Kuali Financial System, a comprehensive financial management system for higher education.
3    * 
4    * Copyright 2005-2014 The Kuali Foundation
5    * 
6    * This program is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU Affero General Public License as
8    * published by the Free Software Foundation, either version 3 of the
9    * License, or (at your option) any later version.
10   * 
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU Affero General Public License for more details.
15   * 
16   * You should have received a copy of the GNU Affero General Public License
17   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  package org.kuali.kfs.sys.service;
20  
21  import java.util.HashMap;
22  import java.util.Map;
23  
24  import org.kuali.kfs.coa.service.AccountService;
25  import org.kuali.kfs.fp.document.AdvanceDepositDocument;
26  import org.kuali.kfs.fp.document.CashReceiptDocument;
27  import org.kuali.kfs.fp.document.CreditCardReceiptDocument;
28  import org.kuali.kfs.fp.document.DisbursementVoucherDocument;
29  import org.kuali.kfs.fp.document.DistributionOfIncomeAndExpenseDocument;
30  import org.kuali.kfs.fp.document.GeneralErrorCorrectionDocument;
31  import org.kuali.kfs.fp.document.IndirectCostAdjustmentDocument;
32  import org.kuali.kfs.fp.document.InternalBillingDocument;
33  import org.kuali.kfs.fp.document.NonCheckDisbursementDocument;
34  import org.kuali.kfs.fp.document.PreEncumbranceDocument;
35  import org.kuali.kfs.fp.document.ServiceBillingDocument;
36  import org.kuali.kfs.fp.document.TransferOfFundsDocument;
37  import org.kuali.kfs.sys.businessobject.AccountingLine;
38  import org.kuali.kfs.sys.businessobject.SourceAccountingLine;
39  import org.kuali.kfs.sys.businessobject.TargetAccountingLine;
40  import org.kuali.kfs.sys.context.SpringContext;
41  import org.kuali.kfs.sys.document.AccountingDocument;
42  import org.kuali.kfs.sys.document.service.DebitDeterminerService;
43  import org.kuali.rice.core.api.util.type.KualiDecimal;
44  import org.kuali.rice.kew.api.exception.WorkflowException;
45  import org.kuali.rice.kns.service.DataDictionaryService;
46  import org.kuali.rice.krad.document.TransactionalDocument;
47  import org.kuali.rice.krad.service.DocumentService;
48  
49  /**
50   * IsDebitTestUtils
51   */
52  public class IsDebitTestUtils {
53      /**
54       * arbitrary amount constants
55       */
56      public static class Amount {
57          public static final KualiDecimal POSITIVE = new KualiDecimal("10");
58          public static final KualiDecimal NEGATIVE = new KualiDecimal("-5");
59      }
60  
61      private static Map<String, String> sourceLines = new HashMap<String, String>();
62      private static Map<String, String> targetLines = new HashMap<String, String>();
63  
64      private static class BaChartObjectCodes {
65          public static final String EXPENSE = "5000";
66          public static final String ASSET = "8010";
67          public static final String INCOME = "1301";
68          public static final String LIABILITY = "9120";
69      }
70  
71      private static class ImportLines {
72          public static final String DEFAULT = "BA,6044900,x,objc,x,x,x,0";
73          public static final String WITH_DESCRIPTION = "BA,6044900,x,objc,x,x,x,description,0";
74          public static final String WITH_REF_NUM_AND_DESCRIPTION = "BA,6044900,x,objc,x,x,x,refnum,description,0";
75          public static final String WITH_REF_NUM = "BA,6044900,x,objc,x,x,x,refnum,0";
76          public static final String WITH_ORIGIN_CODE_AND_REF_NUM_AND_DESCRIPTION = "BA,6044900,x,objc,x,x,x,01,refnum,description,0";
77          public static final String WITHOUT_OBJECT_CODE = "BA,6044900,x,x,x,x,0";
78      }
79  
80  
81      static {
82          sourceLines.put("AD", ImportLines.WITH_DESCRIPTION);
83          sourceLines.put("CR", ImportLines.WITH_DESCRIPTION);
84          sourceLines.put("CCR", ImportLines.WITH_DESCRIPTION);
85          sourceLines.put("DV", ImportLines.WITH_DESCRIPTION);
86          sourceLines.put("DI", ImportLines.DEFAULT);
87          sourceLines.put("GEC", ImportLines.WITH_ORIGIN_CODE_AND_REF_NUM_AND_DESCRIPTION);
88          sourceLines.put("ICA", ImportLines.WITHOUT_OBJECT_CODE);
89          sourceLines.put("IB", ImportLines.DEFAULT);
90          sourceLines.put("ND", ImportLines.WITH_REF_NUM_AND_DESCRIPTION);
91          sourceLines.put("PE", ImportLines.DEFAULT);
92          sourceLines.put("SB", ImportLines.WITH_DESCRIPTION);
93          sourceLines.put("TF", ImportLines.DEFAULT);
94      }
95  
96      static {
97          targetLines.put("DI", ImportLines.DEFAULT);
98          targetLines.put("GEC", ImportLines.WITH_ORIGIN_CODE_AND_REF_NUM_AND_DESCRIPTION);
99          targetLines.put("ICA", ImportLines.WITHOUT_OBJECT_CODE);
100         targetLines.put("IB", ImportLines.DEFAULT);
101         targetLines.put("PE", ImportLines.WITH_REF_NUM);
102         targetLines.put("SB", ImportLines.WITH_DESCRIPTION);
103         targetLines.put("TF", ImportLines.DEFAULT);
104     }
105 
106     /**
107      * @param documentService
108      * @param documentClass
109      * @return TransactionalDocument
110      * @throws WorkflowException
111      */
112     public static AccountingDocument getDocument(DocumentService documentService, Class<? extends AccountingDocument> documentClass) throws WorkflowException {
113         return (AccountingDocument) documentService.getNewDocument(documentClass);
114     }
115 
116     /**
117      * @param documentService
118      * @param documentClass
119      * @return TransactionalDocument
120      * @throws WorkflowException
121      */
122     public static AccountingDocument getErrorCorrectionDocument(DocumentService documentService, Class<? extends AccountingDocument> documentClass) throws WorkflowException {
123         AccountingDocument financialDocument = getDocument(documentService, documentClass);
124         financialDocument.getFinancialSystemDocumentHeader().setFinancialDocumentInErrorNumber("fakeErrorCorrection");
125 
126         return financialDocument;
127     }
128 
129     private static AccountingLine getAccountingLine(AccountingDocument financialDocument, Class<? extends AccountingLine> lineClass, KualiDecimal amount, String objectCode) {
130         String unparsedLine = null;
131         AccountingLine line = null;
132         if (SourceAccountingLine.class.isAssignableFrom(lineClass)) {
133             unparsedLine = sourceLines.get(getDocumentTypeCode(financialDocument));
134             if (unparsedLine == null) {
135                 throw new IllegalArgumentException("no value found in sourceMap for: " + financialDocument.getClass() + ";" + lineClass);
136             }
137             unparsedLine = removeChartIfNotNeeded(unparsedLine);
138             line = financialDocument.getAccountingLineParser().parseSourceAccountingLine(financialDocument, unparsedLine);
139         }
140         else if (TargetAccountingLine.class.isAssignableFrom(lineClass)) {
141             unparsedLine = targetLines.get(getDocumentTypeCode(financialDocument));
142             if (unparsedLine == null) {
143                 throw new IllegalArgumentException("no value found in targetMap for: " + financialDocument.getClass() + ";" + lineClass);
144             }
145             unparsedLine = removeChartIfNotNeeded(unparsedLine);
146             line = financialDocument.getAccountingLineParser().parseTargetAccountingLine(financialDocument, unparsedLine);
147         }
148         else {
149             throw new IllegalArgumentException("invalid accounting line type (" + lineClass + ")");
150         }
151 
152         line.setAmount(amount);
153         line.setFinancialObjectCode(objectCode);
154         return line;
155     }
156     
157     /**
158      * Returns the document type name for the given document
159      * @param financialDocument the document to find a doc type name for
160      * @return the doc type name
161      */
162     private static String getDocumentTypeCode(AccountingDocument financialDocument) {
163         final DataDictionaryService dataDictionaryService = SpringContext.getBean(DataDictionaryService.class);
164         final String docTypeName = dataDictionaryService.getDocumentTypeNameByClass(financialDocument.getClass());
165         return docTypeName;
166     }
167     
168     /**
169      * Checks if accounts can cross charts; if not, removes chart from accounting line
170      * @param accountingLine the accounting line to potentially correct
171      * @return the accounting line, with perhaps the chart removed
172      */
173     private static String removeChartIfNotNeeded(String accountingLine) {
174         final AccountService accountService = SpringContext.getBean(AccountService.class);
175         final String updatedAccountingLine = (!accountService.accountsCanCrossCharts()) ?
176                 accountingLine.substring(3) :
177                 accountingLine;
178         return updatedAccountingLine;
179     }
180 
181     /**
182      * @param financialDocument
183      * @param lineClass
184      * @param amount
185      * @return AccountingLine
186      */
187     public static AccountingLine getExpenseLine(AccountingDocument financialDocument, Class<? extends AccountingLine> lineClass, KualiDecimal amount) {
188         return getAccountingLine(financialDocument, lineClass, amount, BaChartObjectCodes.EXPENSE);
189     }
190 
191     /**
192      * @param financialDocument
193      * @param lineClass
194      * @param amount
195      * @return AccountingLine
196      */
197     public static AccountingLine getAssetLine(AccountingDocument financialDocument, Class<? extends AccountingLine> lineClass, KualiDecimal amount) {
198         return getAccountingLine(financialDocument, lineClass, amount, BaChartObjectCodes.ASSET);
199     }
200 
201     /**
202      * @param financialDocument
203      * @param lineClass
204      * @param amount
205      * @return AccountingLine
206      */
207     public static AccountingLine getIncomeLine(AccountingDocument financialDocument, Class<? extends AccountingLine> lineClass, KualiDecimal amount) {
208         return getAccountingLine(financialDocument, lineClass, amount, BaChartObjectCodes.INCOME);
209     }
210 
211     /**
212      * @param financialDocument
213      * @param lineClass
214      * @param amount
215      * @return AccountingLine
216      */
217     public static AccountingLine getLiabilityLine(AccountingDocument financialDocument, Class<? extends AccountingLine> lineClass, KualiDecimal amount) {
218         return getAccountingLine(financialDocument, lineClass, amount, BaChartObjectCodes.LIABILITY);
219     }
220 
221     /**
222      * @param dataDictionaryService
223      * @param dataDicitionaryService
224      * @param financialDocument
225      * @param accountingLine
226      * @return
227      * @throws InstantiationException
228      * @throws IllegalAccessException
229      */
230     public static boolean isDebit(DataDictionaryService dataDictionaryService, DataDictionaryService dataDicitionaryService, AccountingDocument financialDocument, AccountingLine accountingLine) throws InstantiationException, IllegalAccessException {
231         return financialDocument.isDebit(accountingLine);
232     }
233 
234 
235     /**
236      * @param dataDictionaryService
237      * @param dataDicitionaryService
238      * @param financialDocument
239      * @param accountingLine
240      * @return
241      * @throws InstantiationException
242      * @throws IllegalAccessException
243      */
244     public static boolean isDebitIllegalStateException(DataDictionaryService dataDictionaryService, DataDictionaryService dataDicitionaryService, AccountingDocument financialDocument, AccountingLine accountingLine) throws InstantiationException, IllegalAccessException {
245         boolean failedAsExpected = false;
246         try {
247             IsDebitTestUtils.isDebit(dataDictionaryService, dataDicitionaryService, financialDocument, accountingLine);
248 
249         }
250         catch (IllegalStateException e) {
251             DebitDeterminerService isDebitUtils = SpringContext.getBean(DebitDeterminerService.class);
252             failedAsExpected = isDebitUtils.getDebitCalculationIllegalStateExceptionMessage().equals(e.getMessage());
253         }
254 
255         return failedAsExpected;
256     }
257 
258     /**
259      * @param dataDictionaryService
260      * @param dataDicitionaryService
261      * @param financialDocument
262      * @param accountingLine
263      * @return
264      * @throws InstantiationException
265      * @throws IllegalAccessException
266      */
267     public static boolean isErrorCorrectionIllegalStateException(DataDictionaryService dataDictionaryService, DataDictionaryService dataDicitionaryService, AccountingDocument financialDocument, AccountingLine accountingLine) throws InstantiationException, IllegalAccessException {
268         boolean failedAsExpected = false;
269         try {
270             IsDebitTestUtils.isDebit(dataDictionaryService, dataDicitionaryService, financialDocument, accountingLine);
271 
272         }
273         catch (IllegalStateException e) {
274             DebitDeterminerService isDebitUtils = SpringContext.getBean(DebitDeterminerService.class);
275             failedAsExpected = isDebitUtils.getErrorCorrectionIllegalStateExceptionMessage().equals(e.getMessage());
276         }
277 
278         return failedAsExpected;
279     }
280 }