/*
* 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.fp.document;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.fp.businessobject.ProcurementCardHolder;
import org.kuali.kfs.fp.businessobject.ProcurementCardSourceAccountingLine;
import org.kuali.kfs.fp.businessobject.ProcurementCardTargetAccountingLine;
import org.kuali.kfs.fp.businessobject.ProcurementCardTransactionDetail;
import org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.businessobject.AccountingLine;
import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
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.AmountTotaling;
import org.kuali.kfs.sys.document.service.DebitDeterminerService;
import org.kuali.rice.kew.api.KewApiConstants;
import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange;
import org.kuali.rice.kns.service.DataDictionaryService;
import org.kuali.rice.krad.rules.rule.event.KualiDocumentEvent;
import org.kuali.rice.krad.rules.rule.event.SaveDocumentEvent;
/**
* This is the Procurement Card Document Class. The procurement cards distributes expenses from clearing accounts. It is a two-sided
* document, but only target lines are displayed because source lines cannot be changed. Transaction, Card, and Vendor information
* are associated with the document to help better distribute the expense.
*/
public class ProcurementCardDocument extends CapitalAccountingLinesDocumentBase implements AmountTotaling, CapitalAssetEditable {
protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ProcurementCardDocument.class);
protected ProcurementCardHolder procurementCardHolder;
protected List transactionEntries;
protected ProcurementCardTargetAccountingLine newTargetLine;
protected transient CapitalAssetManagementModuleService capitalAssetManagementModuleService;
protected boolean autoApprovedIndicator;
/**
* Default constructor.
*/
public ProcurementCardDocument() {
super();
transactionEntries = new ArrayList<ProcurementCardTransactionDetail>();
}
/**
* @return Returns the transactionEntries.
*/
public List getTransactionEntries() {
return transactionEntries;
}
/**
* @param transactionEntries The transactionEntries to set.
*/
public void setTransactionEntries(List transactionEntries) {
this.transactionEntries = transactionEntries;
}
/**
* Gets the procurementCardHolder attribute.
*
* @return Returns the procurementCardHolder.
*/
public ProcurementCardHolder getProcurementCardHolder() {
return procurementCardHolder;
}
/**
* Sets the procurementCardHolder attribute value.
*
* @param procurementCardHolder The procurementCardHolder to set.
*/
public void setProcurementCardHolder(ProcurementCardHolder procurementCardHolder) {
this.procurementCardHolder = procurementCardHolder;
}
/**
* Removes the target accounting line at the given index from the transaction detail entry.
*
* @param index
*/
public void removeTargetAccountingLine(int index) {
ProcurementCardTargetAccountingLine line = (ProcurementCardTargetAccountingLine) getTargetAccountingLines().get(index);
for (Iterator iter = transactionEntries.iterator(); iter.hasNext();) {
ProcurementCardTransactionDetail transactionEntry = (ProcurementCardTransactionDetail) iter.next();
if (transactionEntry.getFinancialDocumentTransactionLineNumber().equals(line.getFinancialDocumentTransactionLineNumber())) {
transactionEntry.getTargetAccountingLines().remove(line);
}
}
}
/**
* Override to set the accounting line in the transaction detail object.
*
* @see org.kuali.kfs.sys.document.AccountingDocument#addSourceAccountingLine(SourceAccountingLine)
*/
@Override
public void addSourceAccountingLine(SourceAccountingLine sourceLine) {
ProcurementCardSourceAccountingLine line = (ProcurementCardSourceAccountingLine) sourceLine;
line.setSequenceNumber(this.getNextSourceLineNumber());
for (Iterator iter = transactionEntries.iterator(); iter.hasNext();) {
ProcurementCardTransactionDetail transactionEntry = (ProcurementCardTransactionDetail) iter.next();
if (transactionEntry.getFinancialDocumentTransactionLineNumber().equals(line.getFinancialDocumentTransactionLineNumber())) {
transactionEntry.getSourceAccountingLines().add(line);
}
}
this.nextSourceLineNumber = new Integer(this.getNextSourceLineNumber().intValue() + 1);
}
/**
* Override to set the accounting line in the transaction detail object.
*
* @see org.kuali.kfs.sys.document.AccountingDocument#addTargetAccountingLine(TargetAccountingLine)
*/
@Override
public void addTargetAccountingLine(TargetAccountingLine targetLine) {
ProcurementCardTargetAccountingLine line = (ProcurementCardTargetAccountingLine) targetLine;
line.setSequenceNumber(this.getNextTargetLineNumber());
for (Iterator iter = transactionEntries.iterator(); iter.hasNext();) {
ProcurementCardTransactionDetail transactionEntry = (ProcurementCardTransactionDetail) iter.next();
if (transactionEntry.getFinancialDocumentTransactionLineNumber().equals(line.getFinancialDocumentTransactionLineNumber())) {
transactionEntry.getTargetAccountingLines().add(line);
}
}
this.nextTargetLineNumber = new Integer(this.getNextTargetLineNumber().intValue() + 1);
}
/**
* Override to get source accounting lines out of transactions
*
* @see org.kuali.kfs.sys.document.AccountingDocument#getSourceAccountingLines()
*/
@Override
public List getSourceAccountingLines() {
List sourceAccountingLines = new ArrayList();
for (Iterator iter = transactionEntries.iterator(); iter.hasNext();) {
ProcurementCardTransactionDetail transactionEntry = (ProcurementCardTransactionDetail) iter.next();
for (Iterator iterator = transactionEntry.getSourceAccountingLines().iterator(); iterator.hasNext();) {
SourceAccountingLine sourceLine = (SourceAccountingLine) iterator.next();
sourceAccountingLines.add(sourceLine);
}
}
return sourceAccountingLines;
}
/**
* Override to get target accounting lines out of transactions
*
* @see org.kuali.kfs.sys.document.AccountingDocument#getTargetAccountingLines()
*/
@Override
public List getTargetAccountingLines() {
List targetAccountingLines = new ArrayList();
for (Iterator iter = transactionEntries.iterator(); iter.hasNext();) {
ProcurementCardTransactionDetail transactionEntry = (ProcurementCardTransactionDetail) iter.next();
for (Iterator iterator = transactionEntry.getTargetAccountingLines().iterator(); iterator.hasNext();) {
TargetAccountingLine targetLine = (TargetAccountingLine) iterator.next();
targetAccountingLines.add(targetLine);
}
}
return targetAccountingLines;
}
/**
* @see org.kuali.kfs.sys.document.AccountingDocumentBase#getSourceAccountingLineClass()
*/
@Override
public Class getSourceAccountingLineClass() {
return ProcurementCardSourceAccountingLine.class;
}
/**
* @see org.kuali.kfs.sys.document.AccountingDocumentBase#getTargetAccountingLineClass()
*/
@Override
public Class getTargetAccountingLineClass() {
return ProcurementCardTargetAccountingLine.class;
}
@Override
public void doRouteStatusChange(DocumentRouteStatusChange statusChangeEvent) {
super.doRouteStatusChange(statusChangeEvent);
// Updating for rice-1.0.0 api changes. doRouteStatusChange() went away, so
// that functionality needs to be a part of doRouteStatusChange now.
// handleRouteStatusChange did not happen on a save
if (!KewApiConstants.ACTION_TAKEN_SAVED_CD.equals(statusChangeEvent.getDocumentEventCode())) {
this.getCapitalAssetManagementModuleService().deleteDocumentAssetLocks(this);
}
}
/**
* On procurement card documents, positive source amounts are credits, negative source amounts are debits.
*
* @param transactionalDocument The document the accounting line being checked is located in.
* @param accountingLine The accounting line being analyzed.
* @return True if the accounting line given is a debit accounting line, false otherwise.
* @throws Throws an IllegalStateException if one of the following rules are violated: the accounting line amount is zero or the
* accounting line is not an expense or income accounting line.
* @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#isDebit(FinancialDocument,
* org.kuali.rice.krad.bo.AccountingLine)
* @see org.kuali.kfs.sys.document.validation.impl.AccountingDocumentRuleBase.IsDebitUtils#isDebitConsideringSection(AccountingDocumentRuleBase,
* AccountingDocument, AccountingLine)
*/
@Override
public boolean isDebit(GeneralLedgerPendingEntrySourceDetail postable) throws IllegalStateException {
// disallow error correction
DebitDeterminerService isDebitUtils = SpringContext.getBean(DebitDeterminerService.class);
isDebitUtils.disallowErrorCorrectionDocumentCheck(this);
return isDebitUtils.isDebitConsideringSection(this, (AccountingLine) postable);
}
/**
* @see org.kuali.rice.krad.document.DocumentBase#postProcessSave(org.kuali.rice.krad.rule.event.KualiDocumentEvent)
*/
@Override
public void postProcessSave(KualiDocumentEvent event) {
super.postProcessSave(event);
if (!(event instanceof SaveDocumentEvent)) { // don't lock until they route
String documentTypeName = SpringContext.getBean(DataDictionaryService.class).getDocumentTypeNameByClass(this.getClass());
this.getCapitalAssetManagementModuleService().generateCapitalAssetLock(this, documentTypeName);
}
}
/**
* @return CapitalAssetManagementModuleService
*/
protected CapitalAssetManagementModuleService getCapitalAssetManagementModuleService() {
if (capitalAssetManagementModuleService == null) {
capitalAssetManagementModuleService = SpringContext.getBean(CapitalAssetManagementModuleService.class);
}
return capitalAssetManagementModuleService;
}
/**
* Provides answers to the following splits: IsDocumentAutoApproved
*
* @see org.kuali.kfs.sys.document.FinancialSystemTransactionalDocumentBase#answerSplitNodeQuestion(java.lang.String)
*/
@Override
public boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException {
if (StringUtils.equals(nodeName, KFSConstants.FinancialProcessingWorkflowConstants.IS_DOCUMENT_AUTO_APPROVED)){
return isAutoApprovedIndicator();
}
throw new UnsupportedOperationException("Cannot answer split question for this node you call \"" + nodeName + "\"");
}
/**
* set the autoApprovedIndicator
*
* @param value- the new value to set
*/
public void setAutoApprovedIndicator(boolean value)
{
autoApprovedIndicator = value;
}
/**
* get the AutoApprovedIndicator
*
* @return the value of autoApprovedIndicator
*/
public boolean isAutoApprovedIndicator()
{
return autoApprovedIndicator;
}
}