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 }