001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.kuali.kfs.fp.document; 018 019 import java.util.ArrayList; 020 import java.util.Iterator; 021 import java.util.LinkedHashMap; 022 import java.util.List; 023 024 import org.kuali.kfs.fp.businessobject.CapitalAssetInformation; 025 import org.kuali.kfs.fp.businessobject.ProcurementCardHolder; 026 import org.kuali.kfs.fp.businessobject.ProcurementCardSourceAccountingLine; 027 import org.kuali.kfs.fp.businessobject.ProcurementCardTargetAccountingLine; 028 import org.kuali.kfs.fp.businessobject.ProcurementCardTransactionDetail; 029 import org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService; 030 import org.kuali.kfs.sys.KFSPropertyConstants; 031 import org.kuali.kfs.sys.businessobject.AccountingLine; 032 import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail; 033 import org.kuali.kfs.sys.businessobject.SourceAccountingLine; 034 import org.kuali.kfs.sys.businessobject.TargetAccountingLine; 035 import org.kuali.kfs.sys.context.SpringContext; 036 import org.kuali.kfs.sys.document.AccountingDocumentBase; 037 import org.kuali.kfs.sys.document.AmountTotaling; 038 import org.kuali.kfs.sys.document.service.DebitDeterminerService; 039 import org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO; 040 import org.kuali.rice.kew.util.KEWConstants; 041 import org.kuali.rice.kns.rule.event.KualiDocumentEvent; 042 import org.kuali.rice.kns.rule.event.SaveDocumentEvent; 043 import org.kuali.rice.kns.service.DataDictionaryService; 044 import org.kuali.rice.kns.util.ObjectUtils; 045 import org.kuali.rice.kns.util.TypedArrayList; 046 047 /** 048 * This is the Procurement Card Document Class. The procurement cards distributes expenses from clearing accounts. It is a two-sided 049 * document, but only target lines are displayed because source lines cannot be changed. Transaction, Card, and Vendor information 050 * are associated with the document to help better distribute the expense. 051 */ 052 public class ProcurementCardDocument extends AccountingDocumentBase implements AmountTotaling, CapitalAssetEditable { 053 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ProcurementCardDocument.class); 054 055 protected ProcurementCardHolder procurementCardHolder; 056 057 protected List transactionEntries; 058 059 protected transient CapitalAssetInformation capitalAssetInformation; 060 protected transient CapitalAssetManagementModuleService capitalAssetManagementModuleService; 061 062 /** 063 * Default constructor. 064 */ 065 public ProcurementCardDocument() { 066 super(); 067 transactionEntries = new TypedArrayList(ProcurementCardTransactionDetail.class); 068 // Save Capital Asset Information for PCard document when created. 069 this.capitalAssetInformation = new CapitalAssetInformation(); 070 } 071 072 /** 073 * @see org.kuali.kfs.sys.document.AccountingDocumentBase#buildListOfDeletionAwareLists() 074 */ 075 @Override 076 public List buildListOfDeletionAwareLists() { 077 List<List> managedLists = super.buildListOfDeletionAwareLists(); 078 if (ObjectUtils.isNotNull(capitalAssetInformation) && ObjectUtils.isNotNull(capitalAssetInformation.getCapitalAssetInformationDetails())) { 079 managedLists.add(capitalAssetInformation.getCapitalAssetInformationDetails()); 080 } 081 return managedLists; 082 } 083 084 /** 085 * @return Returns the transactionEntries. 086 */ 087 public List getTransactionEntries() { 088 return transactionEntries; 089 } 090 091 /** 092 * @param transactionEntries The transactionEntries to set. 093 */ 094 public void setTransactionEntries(List transactionEntries) { 095 this.transactionEntries = transactionEntries; 096 } 097 098 /** 099 * Gets the procurementCardHolder attribute. 100 * 101 * @return Returns the procurementCardHolder. 102 */ 103 public ProcurementCardHolder getProcurementCardHolder() { 104 return procurementCardHolder; 105 } 106 107 /** 108 * Sets the procurementCardHolder attribute value. 109 * 110 * @param procurementCardHolder The procurementCardHolder to set. 111 */ 112 public void setProcurementCardHolder(ProcurementCardHolder procurementCardHolder) { 113 this.procurementCardHolder = procurementCardHolder; 114 } 115 116 /** 117 * Removes the target accounting line at the given index from the transaction detail entry. 118 * 119 * @param index 120 */ 121 public void removeTargetAccountingLine(int index) { 122 ProcurementCardTargetAccountingLine line = (ProcurementCardTargetAccountingLine) getTargetAccountingLines().get(index); 123 124 for (Iterator iter = transactionEntries.iterator(); iter.hasNext();) { 125 ProcurementCardTransactionDetail transactionEntry = (ProcurementCardTransactionDetail) iter.next(); 126 if (transactionEntry.getFinancialDocumentTransactionLineNumber().equals(line.getFinancialDocumentTransactionLineNumber())) { 127 transactionEntry.getTargetAccountingLines().remove(line); 128 } 129 } 130 } 131 132 /** 133 * Override to set the accounting line in the transaction detail object. 134 * 135 * @see org.kuali.kfs.sys.document.AccountingDocument#addSourceAccountingLine(SourceAccountingLine) 136 */ 137 @Override 138 public void addSourceAccountingLine(SourceAccountingLine sourceLine) { 139 ProcurementCardSourceAccountingLine line = (ProcurementCardSourceAccountingLine) sourceLine; 140 141 line.setSequenceNumber(this.getNextSourceLineNumber()); 142 143 for (Iterator iter = transactionEntries.iterator(); iter.hasNext();) { 144 ProcurementCardTransactionDetail transactionEntry = (ProcurementCardTransactionDetail) iter.next(); 145 if (transactionEntry.getFinancialDocumentTransactionLineNumber().equals(line.getFinancialDocumentTransactionLineNumber())) { 146 transactionEntry.getSourceAccountingLines().add(line); 147 } 148 } 149 150 this.nextSourceLineNumber = new Integer(this.getNextSourceLineNumber().intValue() + 1); 151 } 152 153 /** 154 * Override to set the accounting line in the transaction detail object. 155 * 156 * @see org.kuali.kfs.sys.document.AccountingDocument#addTargetAccountingLine(TargetAccountingLine) 157 */ 158 @Override 159 public void addTargetAccountingLine(TargetAccountingLine targetLine) { 160 ProcurementCardTargetAccountingLine line = (ProcurementCardTargetAccountingLine) targetLine; 161 162 line.setSequenceNumber(this.getNextTargetLineNumber()); 163 164 for (Iterator iter = transactionEntries.iterator(); iter.hasNext();) { 165 ProcurementCardTransactionDetail transactionEntry = (ProcurementCardTransactionDetail) iter.next(); 166 if (transactionEntry.getFinancialDocumentTransactionLineNumber().equals(line.getFinancialDocumentTransactionLineNumber())) { 167 transactionEntry.getTargetAccountingLines().add(line); 168 } 169 } 170 171 this.nextTargetLineNumber = new Integer(this.getNextTargetLineNumber().intValue() + 1); 172 } 173 174 /** 175 * Override to get source accounting lines out of transactions 176 * 177 * @see org.kuali.kfs.sys.document.AccountingDocument#getSourceAccountingLines() 178 */ 179 @Override 180 public List getSourceAccountingLines() { 181 List sourceAccountingLines = new ArrayList(); 182 183 for (Iterator iter = transactionEntries.iterator(); iter.hasNext();) { 184 ProcurementCardTransactionDetail transactionEntry = (ProcurementCardTransactionDetail) iter.next(); 185 for (Iterator iterator = transactionEntry.getSourceAccountingLines().iterator(); iterator.hasNext();) { 186 SourceAccountingLine sourceLine = (SourceAccountingLine) iterator.next(); 187 sourceAccountingLines.add(sourceLine); 188 } 189 } 190 191 return sourceAccountingLines; 192 } 193 194 /** 195 * Override to get target accounting lines out of transactions 196 * 197 * @see org.kuali.kfs.sys.document.AccountingDocument#getTargetAccountingLines() 198 */ 199 @Override 200 public List getTargetAccountingLines() { 201 List targetAccountingLines = new ArrayList(); 202 203 for (Iterator iter = transactionEntries.iterator(); iter.hasNext();) { 204 ProcurementCardTransactionDetail transactionEntry = (ProcurementCardTransactionDetail) iter.next(); 205 for (Iterator iterator = transactionEntry.getTargetAccountingLines().iterator(); iterator.hasNext();) { 206 TargetAccountingLine targetLine = (TargetAccountingLine) iterator.next(); 207 targetAccountingLines.add(targetLine); 208 } 209 } 210 211 return targetAccountingLines; 212 } 213 214 /** 215 * @see org.kuali.kfs.sys.document.AccountingDocumentBase#getSourceAccountingLineClass() 216 */ 217 @Override 218 public Class getSourceAccountingLineClass() { 219 return ProcurementCardSourceAccountingLine.class; 220 } 221 222 /** 223 * @see org.kuali.kfs.sys.document.AccountingDocumentBase#getTargetAccountingLineClass() 224 */ 225 @Override 226 public Class getTargetAccountingLineClass() { 227 return ProcurementCardTargetAccountingLine.class; 228 } 229 230 /** 231 * @see org.kuali.rice.kns.bo.BusinessObjectBase#toStringMapper() 232 */ 233 @Override 234 protected LinkedHashMap toStringMapper() { 235 LinkedHashMap m = new LinkedHashMap(); 236 m.put(KFSPropertyConstants.DOCUMENT_NUMBER, this.documentNumber); 237 return m; 238 } 239 240 @Override 241 public void doRouteStatusChange(DocumentRouteStatusChangeDTO statusChangeEvent) { 242 super.doRouteStatusChange(statusChangeEvent); 243 244 // Updating for rice-1.0.0 api changes. doRouteStatusChange() went away, so 245 // that functionality needs to be a part of doRouteStatusChange now. 246 // handleRouteStatusChange did not happen on a save 247 if (!KEWConstants.ACTION_TAKEN_SAVED_CD.equals(statusChangeEvent.getDocumentEventCode())) { 248 this.getCapitalAssetManagementModuleService().deleteDocumentAssetLocks(this); 249 } 250 } 251 252 /** 253 * On procurement card documents, positive source amounts are credits, negative source amounts are debits. 254 * 255 * @param transactionalDocument The document the accounting line being checked is located in. 256 * @param accountingLine The accounting line being analyzed. 257 * @return True if the accounting line given is a debit accounting line, false otherwise. 258 * @throws Throws an IllegalStateException if one of the following rules are violated: the accounting line amount is zero or the 259 * accounting line is not an expense or income accounting line. 260 * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#isDebit(FinancialDocument, 261 * org.kuali.rice.kns.bo.AccountingLine) 262 * @see org.kuali.kfs.sys.document.validation.impl.AccountingDocumentRuleBase.IsDebitUtils#isDebitConsideringSection(AccountingDocumentRuleBase, 263 * AccountingDocument, AccountingLine) 264 */ 265 public boolean isDebit(GeneralLedgerPendingEntrySourceDetail postable) throws IllegalStateException { 266 // disallow error correction 267 DebitDeterminerService isDebitUtils = SpringContext.getBean(DebitDeterminerService.class); 268 isDebitUtils.disallowErrorCorrectionDocumentCheck(this); 269 return isDebitUtils.isDebitConsideringSection(this, (AccountingLine) postable); 270 } 271 272 /** 273 * Gets the capitalAssetInformation attribute. 274 * 275 * @return Returns the capitalAssetInformation. 276 */ 277 public CapitalAssetInformation getCapitalAssetInformation() { 278 return ObjectUtils.isNull(capitalAssetInformation) ? null : capitalAssetInformation; 279 } 280 281 /** 282 * Sets the capitalAssetInformation attribute value. 283 * 284 * @param capitalAssetInformation The capitalAssetInformation to set. 285 */ 286 @Deprecated 287 public void setCapitalAssetInformation(CapitalAssetInformation capitalAssetInformation) { 288 this.capitalAssetInformation = capitalAssetInformation; 289 } 290 291 /** 292 * @see org.kuali.rice.kns.document.DocumentBase#postProcessSave(org.kuali.rice.kns.rule.event.KualiDocumentEvent) 293 */ 294 @Override 295 public void postProcessSave(KualiDocumentEvent event) { 296 super.postProcessSave(event); 297 if (!(event instanceof SaveDocumentEvent)) { // don't lock until they route 298 String documentTypeName = SpringContext.getBean(DataDictionaryService.class).getDocumentTypeNameByClass(this.getClass()); 299 this.getCapitalAssetManagementModuleService().generateCapitalAssetLock(this, documentTypeName); 300 } 301 } 302 303 /** 304 * @return CapitalAssetManagementModuleService 305 */ 306 protected CapitalAssetManagementModuleService getCapitalAssetManagementModuleService() { 307 if (capitalAssetManagementModuleService == null) { 308 capitalAssetManagementModuleService = SpringContext.getBean(CapitalAssetManagementModuleService.class); 309 } 310 return capitalAssetManagementModuleService; 311 } 312 313 }