/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.sys.service;
import java.util.HashMap;
import java.util.Map;
import org.kuali.kfs.coa.service.AccountService;
import org.kuali.kfs.fp.document.AdvanceDepositDocument;
import org.kuali.kfs.fp.document.CashReceiptDocument;
import org.kuali.kfs.fp.document.CreditCardReceiptDocument;
import org.kuali.kfs.fp.document.DisbursementVoucherDocument;
import org.kuali.kfs.fp.document.DistributionOfIncomeAndExpenseDocument;
import org.kuali.kfs.fp.document.GeneralErrorCorrectionDocument;
import org.kuali.kfs.fp.document.IndirectCostAdjustmentDocument;
import org.kuali.kfs.fp.document.InternalBillingDocument;
import org.kuali.kfs.fp.document.NonCheckDisbursementDocument;
import org.kuali.kfs.fp.document.PreEncumbranceDocument;
import org.kuali.kfs.fp.document.ServiceBillingDocument;
import org.kuali.kfs.fp.document.TransferOfFundsDocument;
import org.kuali.kfs.sys.businessobject.AccountingLine;
import org.kuali.kfs.sys.businessobject.SourceAccountingLine;
import org.kuali.kfs.sys.businessobject.TargetAccountingLine;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.kfs.sys.document.AccountingDocument;
import org.kuali.kfs.sys.document.service.DebitDeterminerService;
import org.kuali.rice.core.api.util.type.KualiDecimal;
import org.kuali.rice.kew.api.exception.WorkflowException;
import org.kuali.rice.kns.service.DataDictionaryService;
import org.kuali.rice.krad.document.TransactionalDocument;
import org.kuali.rice.krad.service.DocumentService;
/**
* IsDebitTestUtils
*/
public class IsDebitTestUtils {
/**
* arbitrary amount constants
*/
public static class Amount {
public static final KualiDecimal POSITIVE = new KualiDecimal("10");
public static final KualiDecimal NEGATIVE = new KualiDecimal("-5");
}
private static Map<String, String> sourceLines = new HashMap<String, String>();
private static Map<String, String> targetLines = new HashMap<String, String>();
private static class BaChartObjectCodes {
public static final String EXPENSE = "5000";
public static final String ASSET = "8010";
public static final String INCOME = "1301";
public static final String LIABILITY = "9120";
}
private static class ImportLines {
public static final String DEFAULT = "BA,6044900,x,objc,x,x,x,0";
public static final String WITH_DESCRIPTION = "BA,6044900,x,objc,x,x,x,description,0";
public static final String WITH_REF_NUM_AND_DESCRIPTION = "BA,6044900,x,objc,x,x,x,refnum,description,0";
public static final String WITH_REF_NUM = "BA,6044900,x,objc,x,x,x,refnum,0";
public static final String WITH_ORIGIN_CODE_AND_REF_NUM_AND_DESCRIPTION = "BA,6044900,x,objc,x,x,x,01,refnum,description,0";
public static final String WITHOUT_OBJECT_CODE = "BA,6044900,x,x,x,x,0";
}
static {
sourceLines.put("AD", ImportLines.WITH_DESCRIPTION);
sourceLines.put("CR", ImportLines.WITH_DESCRIPTION);
sourceLines.put("CCR", ImportLines.WITH_DESCRIPTION);
sourceLines.put("DV", ImportLines.WITH_DESCRIPTION);
sourceLines.put("DI", ImportLines.DEFAULT);
sourceLines.put("GEC", ImportLines.WITH_ORIGIN_CODE_AND_REF_NUM_AND_DESCRIPTION);
sourceLines.put("ICA", ImportLines.WITHOUT_OBJECT_CODE);
sourceLines.put("IB", ImportLines.DEFAULT);
sourceLines.put("ND", ImportLines.WITH_REF_NUM_AND_DESCRIPTION);
sourceLines.put("PE", ImportLines.DEFAULT);
sourceLines.put("SB", ImportLines.WITH_DESCRIPTION);
sourceLines.put("TF", ImportLines.DEFAULT);
}
static {
targetLines.put("DI", ImportLines.DEFAULT);
targetLines.put("GEC", ImportLines.WITH_ORIGIN_CODE_AND_REF_NUM_AND_DESCRIPTION);
targetLines.put("ICA", ImportLines.WITHOUT_OBJECT_CODE);
targetLines.put("IB", ImportLines.DEFAULT);
targetLines.put("PE", ImportLines.WITH_REF_NUM);
targetLines.put("SB", ImportLines.WITH_DESCRIPTION);
targetLines.put("TF", ImportLines.DEFAULT);
}
/**
* @param documentService
* @param documentClass
* @return TransactionalDocument
* @throws WorkflowException
*/
public static AccountingDocument getDocument(DocumentService documentService, Class<? extends AccountingDocument> documentClass) throws WorkflowException {
return (AccountingDocument) documentService.getNewDocument(documentClass);
}
/**
* @param documentService
* @param documentClass
* @return TransactionalDocument
* @throws WorkflowException
*/
public static AccountingDocument getErrorCorrectionDocument(DocumentService documentService, Class<? extends AccountingDocument> documentClass) throws WorkflowException {
AccountingDocument financialDocument = getDocument(documentService, documentClass);
financialDocument.getFinancialSystemDocumentHeader().setFinancialDocumentInErrorNumber("fakeErrorCorrection");
return financialDocument;
}
private static AccountingLine getAccountingLine(AccountingDocument financialDocument, Class<? extends AccountingLine> lineClass, KualiDecimal amount, String objectCode) {
String unparsedLine = null;
AccountingLine line = null;
if (SourceAccountingLine.class.isAssignableFrom(lineClass)) {
unparsedLine = sourceLines.get(getDocumentTypeCode(financialDocument));
if (unparsedLine == null) {
throw new IllegalArgumentException("no value found in sourceMap for: " + financialDocument.getClass() + ";" + lineClass);
}
unparsedLine = removeChartIfNotNeeded(unparsedLine);
line = financialDocument.getAccountingLineParser().parseSourceAccountingLine(financialDocument, unparsedLine);
}
else if (TargetAccountingLine.class.isAssignableFrom(lineClass)) {
unparsedLine = targetLines.get(getDocumentTypeCode(financialDocument));
if (unparsedLine == null) {
throw new IllegalArgumentException("no value found in targetMap for: " + financialDocument.getClass() + ";" + lineClass);
}
unparsedLine = removeChartIfNotNeeded(unparsedLine);
line = financialDocument.getAccountingLineParser().parseTargetAccountingLine(financialDocument, unparsedLine);
}
else {
throw new IllegalArgumentException("invalid accounting line type (" + lineClass + ")");
}
line.setAmount(amount);
line.setFinancialObjectCode(objectCode);
return line;
}
/**
* Returns the document type name for the given document
* @param financialDocument the document to find a doc type name for
* @return the doc type name
*/
private static String getDocumentTypeCode(AccountingDocument financialDocument) {
final DataDictionaryService dataDictionaryService = SpringContext.getBean(DataDictionaryService.class);
final String docTypeName = dataDictionaryService.getDocumentTypeNameByClass(financialDocument.getClass());
return docTypeName;
}
/**
* Checks if accounts can cross charts; if not, removes chart from accounting line
* @param accountingLine the accounting line to potentially correct
* @return the accounting line, with perhaps the chart removed
*/
private static String removeChartIfNotNeeded(String accountingLine) {
final AccountService accountService = SpringContext.getBean(AccountService.class);
final String updatedAccountingLine = (!accountService.accountsCanCrossCharts()) ?
accountingLine.substring(3) :
accountingLine;
return updatedAccountingLine;
}
/**
* @param financialDocument
* @param lineClass
* @param amount
* @return AccountingLine
*/
public static AccountingLine getExpenseLine(AccountingDocument financialDocument, Class<? extends AccountingLine> lineClass, KualiDecimal amount) {
return getAccountingLine(financialDocument, lineClass, amount, BaChartObjectCodes.EXPENSE);
}
/**
* @param financialDocument
* @param lineClass
* @param amount
* @return AccountingLine
*/
public static AccountingLine getAssetLine(AccountingDocument financialDocument, Class<? extends AccountingLine> lineClass, KualiDecimal amount) {
return getAccountingLine(financialDocument, lineClass, amount, BaChartObjectCodes.ASSET);
}
/**
* @param financialDocument
* @param lineClass
* @param amount
* @return AccountingLine
*/
public static AccountingLine getIncomeLine(AccountingDocument financialDocument, Class<? extends AccountingLine> lineClass, KualiDecimal amount) {
return getAccountingLine(financialDocument, lineClass, amount, BaChartObjectCodes.INCOME);
}
/**
* @param financialDocument
* @param lineClass
* @param amount
* @return AccountingLine
*/
public static AccountingLine getLiabilityLine(AccountingDocument financialDocument, Class<? extends AccountingLine> lineClass, KualiDecimal amount) {
return getAccountingLine(financialDocument, lineClass, amount, BaChartObjectCodes.LIABILITY);
}
/**
* @param dataDictionaryService
* @param dataDicitionaryService
* @param financialDocument
* @param accountingLine
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
public static boolean isDebit(DataDictionaryService dataDictionaryService, DataDictionaryService dataDicitionaryService, AccountingDocument financialDocument, AccountingLine accountingLine) throws InstantiationException, IllegalAccessException {
return financialDocument.isDebit(accountingLine);
}
/**
* @param dataDictionaryService
* @param dataDicitionaryService
* @param financialDocument
* @param accountingLine
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
public static boolean isDebitIllegalStateException(DataDictionaryService dataDictionaryService, DataDictionaryService dataDicitionaryService, AccountingDocument financialDocument, AccountingLine accountingLine) throws InstantiationException, IllegalAccessException {
boolean failedAsExpected = false;
try {
IsDebitTestUtils.isDebit(dataDictionaryService, dataDicitionaryService, financialDocument, accountingLine);
}
catch (IllegalStateException e) {
DebitDeterminerService isDebitUtils = SpringContext.getBean(DebitDeterminerService.class);
failedAsExpected = isDebitUtils.getDebitCalculationIllegalStateExceptionMessage().equals(e.getMessage());
}
return failedAsExpected;
}
/**
* @param dataDictionaryService
* @param dataDicitionaryService
* @param financialDocument
* @param accountingLine
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
public static boolean isErrorCorrectionIllegalStateException(DataDictionaryService dataDictionaryService, DataDictionaryService dataDicitionaryService, AccountingDocument financialDocument, AccountingLine accountingLine) throws InstantiationException, IllegalAccessException {
boolean failedAsExpected = false;
try {
IsDebitTestUtils.isDebit(dataDictionaryService, dataDicitionaryService, financialDocument, accountingLine);
}
catch (IllegalStateException e) {
DebitDeterminerService isDebitUtils = SpringContext.getBean(DebitDeterminerService.class);
failedAsExpected = isDebitUtils.getErrorCorrectionIllegalStateExceptionMessage().equals(e.getMessage());
}
return failedAsExpected;
}
}