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 package org.kuali.kfs.module.purap.document; 017 018 import java.math.BigDecimal; 019 import java.text.MessageFormat; 020 import java.util.ArrayList; 021 import java.util.Arrays; 022 import java.util.Iterator; 023 import java.util.LinkedHashMap; 024 import java.util.List; 025 026 import org.apache.commons.lang.ArrayUtils; 027 import org.apache.commons.lang.StringUtils; 028 import org.kuali.kfs.module.purap.PurapConstants; 029 import org.kuali.kfs.module.purap.PurapParameterConstants; 030 import org.kuali.kfs.module.purap.PurapPropertyConstants; 031 import org.kuali.kfs.module.purap.PurapWorkflowConstants.NodeDetails; 032 import org.kuali.kfs.module.purap.businessobject.ItemType; 033 import org.kuali.kfs.module.purap.businessobject.PurApAccountingLine; 034 import org.kuali.kfs.module.purap.businessobject.PurApItem; 035 import org.kuali.kfs.module.purap.businessobject.PurApItemBase; 036 import org.kuali.kfs.module.purap.businessobject.PurchaseOrderView; 037 import org.kuali.kfs.module.purap.businessobject.SensitiveData; 038 import org.kuali.kfs.module.purap.businessobject.Status; 039 import org.kuali.kfs.module.purap.document.service.PurapService; 040 import org.kuali.kfs.module.purap.document.service.impl.PurapServiceImpl; 041 import org.kuali.kfs.module.purap.service.PurapAccountingService; 042 import org.kuali.kfs.module.purap.service.SensitiveDataService; 043 import org.kuali.kfs.module.purap.util.PurApRelatedViews; 044 import org.kuali.kfs.sys.KFSConstants.AdHocPaymentIndicator; 045 import org.kuali.kfs.sys.businessobject.AccountingLine; 046 import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry; 047 import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail; 048 import org.kuali.kfs.sys.businessobject.SourceAccountingLine; 049 import org.kuali.kfs.sys.context.SpringContext; 050 import org.kuali.kfs.sys.document.AccountingDocumentBase; 051 import org.kuali.kfs.sys.document.AmountTotaling; 052 import org.kuali.kfs.sys.service.UniversityDateService; 053 import org.kuali.kfs.vnd.businessobject.VendorAddress; 054 import org.kuali.kfs.vnd.businessobject.VendorDetail; 055 import org.kuali.kfs.vnd.document.service.VendorService; 056 import org.kuali.rice.kew.exception.WorkflowException; 057 import org.kuali.rice.kns.bo.Country; 058 import org.kuali.rice.kns.rule.event.ApproveDocumentEvent; 059 import org.kuali.rice.kns.rule.event.KualiDocumentEvent; 060 import org.kuali.rice.kns.rule.event.RouteDocumentEvent; 061 import org.kuali.rice.kns.service.CountryService; 062 import org.kuali.rice.kns.service.ParameterService; 063 import org.kuali.rice.kns.util.KualiDecimal; 064 import org.kuali.rice.kns.util.ObjectUtils; 065 import org.kuali.rice.kns.util.TypedArrayList; 066 import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument; 067 068 /** 069 * Base class for Purchasing-Accounts Payable Documents. 070 */ 071 public abstract class PurchasingAccountsPayableDocumentBase extends AccountingDocumentBase implements PurchasingAccountsPayableDocument, AmountTotaling { 072 073 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PurchasingAccountsPayableDocumentBase.class); 074 075 // SHARED FIELDS BETWEEN REQUISITION, PURCHASE ORDER, PAYMENT REQUEST, AND CREDIT MEMO 076 protected Integer purapDocumentIdentifier; 077 protected String statusCode; 078 protected Integer vendorHeaderGeneratedIdentifier; 079 protected Integer vendorDetailAssignedIdentifier; 080 protected String vendorCustomerNumber; 081 protected String vendorName; 082 protected String vendorLine1Address; 083 protected String vendorLine2Address; 084 protected String vendorCityName; 085 protected String vendorStateCode; 086 protected String vendorAddressInternationalProvinceName; 087 protected String vendorPostalCode; 088 protected String vendorCountryCode; 089 protected Integer accountsPayablePurchasingDocumentLinkIdentifier; 090 protected boolean useTaxIndicator; 091 protected String vendorAttentionName; 092 093 // NOT PERSISTED IN DB 094 protected String vendorNumber; 095 protected Integer vendorAddressGeneratedIdentifier; 096 protected Boolean overrideWorkflowButtons = null; 097 protected transient PurApRelatedViews relatedViews; 098 protected boolean sensitive; 099 100 // COLLECTIONS 101 protected List<PurApItem> items; 102 protected List<SourceAccountingLine> accountsForRouting; // don't use me for anything else!! 103 104 // REFERENCE OBJECTS 105 protected Status status; 106 protected VendorDetail vendorDetail; 107 protected Country vendorCountry; 108 109 // STATIC 110 public transient String[] belowTheLineTypes; 111 112 // workaround for purapOjbCollectionHelper - remove when merged into rice 113 public boolean allowDeleteAwareCollection = true; 114 115 116 /** 117 * Default constructor to be overridden. 118 */ 119 public PurchasingAccountsPayableDocumentBase() { 120 items = new TypedArrayList(getItemClass()); 121 } 122 123 protected GeneralLedgerPendingEntry getFirstPendingGLEntry() { 124 if (ObjectUtils.isNotNull(getGeneralLedgerPendingEntries()) && !getGeneralLedgerPendingEntries().isEmpty()) { 125 return (GeneralLedgerPendingEntry)getGeneralLedgerPendingEntries().get(0); 126 } 127 return null; 128 } 129 130 public Integer getPostingYearFromPendingGLEntries() { 131 GeneralLedgerPendingEntry glpe = getFirstPendingGLEntry(); 132 if (ObjectUtils.isNotNull(glpe)) { 133 return glpe.getUniversityFiscalYear(); 134 } 135 return null; 136 } 137 138 public String getPostingPeriodCodeFromPendingGLEntries() { 139 GeneralLedgerPendingEntry glpe = getFirstPendingGLEntry(); 140 if (ObjectUtils.isNotNull(glpe)) { 141 return glpe.getUniversityFiscalPeriodCode(); 142 } 143 return null; 144 } 145 146 public List<SourceAccountingLine> getAccountsForRouting() { 147 if (accountsForRouting == null) { 148 populateAccountsForRouting(); 149 } 150 return accountsForRouting; 151 } 152 153 public void setAccountsForRouting(List<SourceAccountingLine> accountsForRouting) { 154 this.accountsForRouting = accountsForRouting; 155 } 156 157 /** 158 * Makes sure that accounts for routing has been generated, so that other information can be retrieved from that 159 */ 160 protected void populateAccountsForRouting() { 161 SpringContext.getBean(PurapAccountingService.class).updateAccountAmounts(this); 162 setAccountsForRouting(SpringContext.getBean(PurapAccountingService.class).generateSummary(getItems())); 163 // need to refresh to get the references for the searchable attributes (ie status) and for invoking route levels (ie account 164 // objects) -hjs 165 refreshNonUpdateableReferences(); 166 for (SourceAccountingLine sourceLine : getAccountsForRouting()) { 167 sourceLine.refreshNonUpdateableReferences(); 168 } 169 } 170 171 public boolean isSensitive() { 172 List<SensitiveData> sensitiveData = SpringContext.getBean(SensitiveDataService.class).getSensitiveDatasAssignedByRelatedDocId(getAccountsPayablePurchasingDocumentLinkIdentifier()); 173 if (ObjectUtils.isNotNull(sensitiveData) && !sensitiveData.isEmpty()) { 174 return true; 175 } 176 return false; 177 } 178 179 /** 180 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#isInquiryRendered() 181 */ 182 public boolean isInquiryRendered() { 183 return isPostingYearPrior(); 184 } 185 186 /** 187 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#isPostingYearNext() 188 */ 189 public boolean isPostingYearNext() { 190 Integer currentFY = SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear(); 191 return (getPostingYear().compareTo(currentFY) > 0); 192 } 193 194 /** 195 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#isPostingYearPrior() 196 */ 197 public boolean isPostingYearPrior() { 198 Integer currentFY = SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear(); 199 return (getPostingYear().compareTo(currentFY) < 0); 200 } 201 202 203 /** 204 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#getPostingYearNextOrCurrent() 205 */ 206 public Integer getPostingYearNextOrCurrent() { 207 if (isPostingYearNext()) { 208 //FY is set to next; use it 209 return getPostingYear(); 210 } 211 //FY is NOT set to next; use CURRENT 212 return SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear(); 213 } 214 215 /** 216 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#getItemClass() 217 */ 218 @SuppressWarnings("rawtypes") 219 public abstract Class getItemClass(); 220 221 @SuppressWarnings("rawtypes") 222 public abstract Class getItemUseTaxClass(); 223 224 /** 225 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#getPurApSourceDocumentIfPossible() 226 */ 227 public abstract PurchasingAccountsPayableDocument getPurApSourceDocumentIfPossible(); 228 229 /** 230 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#getPurApSourceDocumentLabelIfPossible() 231 */ 232 public abstract String getPurApSourceDocumentLabelIfPossible(); 233 234 /** 235 * @see org.kuali.rice.kns.document.DocumentBase#prepareForSave() 236 */ 237 @Override 238 public void prepareForSave(KualiDocumentEvent event) { 239 customPrepareForSave(event); 240 super.prepareForSave(event); 241 fixItemReferences(); 242 } 243 244 /** 245 * PURAP documents are all overriding this method to return false because sufficient funds checking should not be performed on 246 * route of any PURAP documents. Only the Purchase Order performs a sufficient funds check and it is manually forced during 247 * routing. 248 * 249 * @see org.kuali.kfs.sys.document.GeneralLedgerPostingDocumentBase#documentPerformsSufficientFundsCheck() 250 */ 251 @Override 252 public boolean documentPerformsSufficientFundsCheck() { 253 return false; 254 } 255 256 /** 257 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#isDocumentStoppedInRouteNode(NodeDetails nodeDetails) 258 */ 259 public boolean isDocumentStoppedInRouteNode(NodeDetails nodeDetails) { 260 List<String> currentRouteLevels = new ArrayList<String>(); 261 try { 262 KualiWorkflowDocument workflowDoc = getDocumentHeader().getWorkflowDocument(); 263 currentRouteLevels = Arrays.asList(getDocumentHeader().getWorkflowDocument().getNodeNames()); 264 if (currentRouteLevels.contains(nodeDetails.getName()) && workflowDoc.isApprovalRequested()) { 265 return true; 266 } 267 return false; 268 } 269 catch (WorkflowException e) { 270 throw new RuntimeException(e); 271 } 272 } 273 274 /** 275 * Records the specified error message into the Log file and throws a runtime exception. 276 * 277 * @param errorMessage the error message to be logged. 278 */ 279 protected void logAndThrowRuntimeException(String errorMessage) { 280 this.logAndThrowRuntimeException(errorMessage, null); 281 } 282 283 /** 284 * Records the specified error message into the Log file and throws the specified runtime exception. 285 * 286 * @param errorMessage the specified error message. 287 * @param e the specified runtime exception. 288 */ 289 protected void logAndThrowRuntimeException(String errorMessage, Exception e) { 290 if (ObjectUtils.isNotNull(e)) { 291 LOG.error(errorMessage, e); 292 throw new RuntimeException(errorMessage, e); 293 } 294 else { 295 LOG.error(errorMessage); 296 throw new RuntimeException(errorMessage); 297 } 298 } 299 300 /** 301 * Allows child PO classes to customize the prepareForSave method. Most of the subclasses need to call the super's method to get 302 * the GL entry creation, but they each need to do different things to prepare for those entries to be created. This is only for 303 * PO since it has children classes that need different prep work for GL creation. 304 * 305 * @param event the event involved in this action. 306 */ 307 public void customPrepareForSave(KualiDocumentEvent event) { 308 // Need this here so that it happens before the GL work is done 309 SpringContext.getBean(PurapAccountingService.class).updateAccountAmounts(this); 310 311 if (event instanceof RouteDocumentEvent || event instanceof ApproveDocumentEvent) { 312 if (this instanceof VendorCreditMemoDocument && ((VendorCreditMemoDocument)this).isSourceVendor()){ 313 return; 314 } 315 SpringContext.getBean(PurapServiceImpl.class).calculateTax(this); 316 } 317 // These next 5 lines are temporary changes so that we can use PurApOjbCollectionHelper for release 2. 318 // But these 5 lines will not be necessary anymore if the changes in PurApOjbCollectionHelper is 319 // merge into Rice. 320 // this.allowDeleteAwareCollection = true; 321 // DocumentDaoOjb docDao = SpringContext.getBean(DocumentDaoOjb.class); 322 // PurchasingAccountsPayableDocumentBase retrievedDocument = (PurchasingAccountsPayableDocumentBase) docDao.findByDocumentHeaderId(this.getClass(), this.getDocumentNumber()); 323 // if (retrievedDocument != null) { 324 // retrievedDocument.allowDeleteAwareCollection = true; 325 // } 326 // 327 // SpringContext.getBean(PurApOjbCollectionHelper.class).processCollections(docDao, this, retrievedDocument); 328 // this.allowDeleteAwareCollection = false; 329 // if (retrievedDocument != null) { 330 // retrievedDocument.allowDeleteAwareCollection = false; 331 // } 332 } 333 334 /** 335 * @see org.kuali.kfs.sys.document.AccountingDocumentBase#buildListOfDeletionAwareLists() 336 */ 337 @SuppressWarnings("rawtypes") 338 @Override 339 public List buildListOfDeletionAwareLists() { 340 List managedLists = new ArrayList<List>(); 341 managedLists.add(getDeletionAwareAccountingLines()); 342 if (allowDeleteAwareCollection) { 343 //From now on, the list of accounting lines would have been added when the 344 //super.buildListOfDeletionAwareLists() is executed when it calls getSourceAccountingLines(). 345 //So we can remove the old codes that used to exist here to add the accounts to the 346 //managedLists and just use the one from the super.buildListOfDeletionAwareLists() 347 List<PurApItemBase> subManageList = this.getItems(); 348 List useTaxItems = new ArrayList(); 349 for (PurApItemBase subManage : subManageList) { 350 useTaxItems.addAll(subManage.getUseTaxItems()); 351 } 352 353 managedLists.add(this.getItems()); 354 managedLists.add(useTaxItems); 355 } 356 return managedLists; 357 } 358 359 /** 360 * Build deletion list of accounting lines for PurAp generic use. 361 * 362 * @return 363 */ 364 @SuppressWarnings("rawtypes") 365 protected List getDeletionAwareAccountingLines() { 366 List<PurApAccountingLine> deletionAwareAccountingLines = new ArrayList<PurApAccountingLine>(); 367 for (Object itemAsObject : this.getItems()) { 368 final PurApItem item = (PurApItem)itemAsObject; 369 for (PurApAccountingLine accountingLine : item.getSourceAccountingLines()) { 370 deletionAwareAccountingLines.add(accountingLine); 371 } 372 } 373 return deletionAwareAccountingLines; 374 } 375 376 /** 377 * @see org.kuali.kfs.sys.document.AccountingDocumentBase#buildListOfDeletionAwareLists() 378 * 379 @Override 380 public List buildListOfDeletionAwareLists() { 381 List managedLists = new ArrayList(); 382 if (allowDeleteAwareCollection) { 383 List<PurApAccountingLine> purapAccountsList = new ArrayList<PurApAccountingLine>(); 384 for (Object itemAsObject : this.getItems()) { 385 final PurApItem item = (PurApItem)itemAsObject; 386 purapAccountsList.addAll(item.getSourceAccountingLines()); 387 } 388 managedLists.add(purapAccountsList); 389 managedLists.add(this.getItems()); 390 } 391 return managedLists; 392 } 393 */ 394 395 /** 396 * @see org.kuali.rice.kns.bo.BusinessObjectBase#toStringMapper() 397 */ 398 @SuppressWarnings("rawtypes") 399 @Override 400 protected LinkedHashMap toStringMapper() { 401 LinkedHashMap m = new LinkedHashMap(); 402 m.put("purapDocumentIdentifier", this.purapDocumentIdentifier); 403 return m; 404 } 405 406 @Override 407 public void processAfterRetrieve() { 408 super.processAfterRetrieve(); 409 410 refreshNonUpdateableReferences(); 411 } 412 413 /** 414 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#addItem(PurApItem item) 415 */ 416 public void addItem(PurApItem item) { 417 int itemLinePosition = getItemLinePosition(); 418 if (ObjectUtils.isNotNull(item.getItemLineNumber()) && (item.getItemLineNumber() > 0) && (item.getItemLineNumber() <= itemLinePosition)) { 419 itemLinePosition = item.getItemLineNumber().intValue() - 1; 420 } 421 422 item.setPurapDocumentIdentifier(this.purapDocumentIdentifier); 423 item.setPurapDocument(this); 424 425 items.add(itemLinePosition, item); 426 renumberItems(itemLinePosition); 427 } 428 429 /** 430 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#deleteItem(int lineNum) 431 */ 432 public void deleteItem(int lineNum) { 433 if (items.remove(lineNum) == null) { 434 // throw error here 435 } 436 renumberItems(lineNum); 437 } 438 439 /** 440 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#renumberItems(int start) 441 */ 442 public void renumberItems(int start) { 443 for (int i = start; i < items.size(); i++) { 444 PurApItem item = (PurApItem) items.get(i); 445 // only set the item line number for above the line items 446 if (item.getItemType().isLineItemIndicator()) { 447 item.setItemLineNumber(new Integer(i + 1)); 448 } 449 } 450 } 451 452 /** 453 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#itemSwap(int positionFrom, int positionTo) 454 */ 455 public void itemSwap(int positionFrom, int positionTo) { 456 // if out of range do nothing 457 if ((positionTo < 0) || (positionTo >= getItemLinePosition())) { 458 return; 459 } 460 PurApItem item1 = this.getItem(positionFrom); 461 PurApItem item2 = this.getItem(positionTo); 462 Integer oldFirstPos = item1.getItemLineNumber(); 463 // swap line numbers 464 item1.setItemLineNumber(item2.getItemLineNumber()); 465 item2.setItemLineNumber(oldFirstPos); 466 // fix ordering in list 467 items.remove(positionFrom); 468 items.add(positionTo, item1); 469 } 470 471 /** 472 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#getItemLinePosition() 473 */ 474 public int getItemLinePosition() { 475 int belowTheLineCount = 0; 476 for (PurApItem item : items) { 477 if (item.getItemType().isAdditionalChargeIndicator()) { 478 belowTheLineCount++; 479 } 480 } 481 return items.size() - belowTheLineCount; 482 } 483 484 /** 485 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#getItem(int pos) 486 */ 487 public PurApItem getItem(int pos) { 488 return (PurApItem) items.get(pos); 489 } 490 491 /** 492 * Iterates through the items of the document and returns the item with the line number equal to the number given, or null if a 493 * match is not found. 494 * 495 * @param lineNumber line number to match on. 496 * @return the PurchasingAp Item if a match is found, else null. 497 */ 498 @SuppressWarnings("rawtypes") 499 public PurApItem getItemByLineNumber(int lineNumber) { 500 for (Iterator iter = items.iterator(); iter.hasNext();) { 501 PurApItem item = (PurApItem) iter.next(); 502 if (item.getItemLineNumber().intValue() == lineNumber) { 503 return item; 504 } 505 } 506 return null; 507 } 508 509 /** 510 * Find the item in the document via its string identifier. 511 * @param itemStrID the string identifier of the item being searched for 512 * @return the item being searched for 513 */ 514 @SuppressWarnings("rawtypes") 515 public PurApItem getItemByStringIdentifier(String itemStrID) { 516 for (Iterator iter = items.iterator(); iter.hasNext();) { 517 PurApItem item = (PurApItem) iter.next(); 518 if (StringUtils.equalsIgnoreCase(item.getItemIdentifierString(), itemStrID)) { 519 return item; 520 } 521 } 522 return null; 523 } 524 525 /** 526 * Find the item in the document via its identifier. 527 * @param itemID the string identifier of the item being searched for 528 * @return the item being searched for 529 */ 530 @SuppressWarnings("rawtypes") 531 public PurApItem getItemByItemIdentifier(Integer itemID) { 532 for (Iterator iter = items.iterator(); iter.hasNext();) { 533 PurApItem item = (PurApItem) iter.next(); 534 if (item.getItemIdentifier() == itemID) { 535 return item; 536 } 537 } 538 return null; 539 } 540 541 /** 542 * Overriding the parent method so that we can just set the posting year without the other stuff that the parent does to the 543 * accounting period. We only store the posting year on the doc and don't want the other stuff. 544 * 545 * @see org.kuali.kfs.sys.document.LedgerPostingDocumentBase#setPostingYear(java.lang.Integer) 546 */ 547 @Override 548 public void setPostingYear(Integer postingYear) { 549 this.postingYear = postingYear; 550 } 551 552 /** 553 * @see org.kuali.kfs.sys.document.AccountingDocumentBase#getTotalDollarAmount() 554 */ 555 @Override 556 public KualiDecimal getTotalDollarAmount() { 557 return getTotalDollarAmountAllItems(null); 558 } 559 560 /** 561 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#setTotalDollarAmount(KualiDecimal amount) 562 */ 563 public void setTotalDollarAmount(KualiDecimal amount) { 564 // do nothing, this is so that the jsp won't complain about totalDollarAmount have no setter method. 565 } 566 567 /** 568 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#getTotalDollarAmountAllItems(String[] excludedTypes) 569 */ 570 public KualiDecimal getTotalDollarAmountAllItems(String[] excludedTypes) { 571 return getTotalDollarAmountWithExclusions(excludedTypes, true); 572 } 573 574 /** 575 * Computes the total dollar amount of all above the line items. 576 * 577 * @return the total dollar amount of all above the line items. 578 */ 579 public KualiDecimal getTotalDollarAmountAboveLineItems() { 580 return getTotalDollarAmountAboveLineItems(null); 581 } 582 583 /** 584 * Computes the total dollar amount of all above the line items with the specified item types excluded. 585 * 586 * @param excludedTypes the types of items to be excluded. 587 * @return the total dollar amount of all above the line items with the specified item types excluded.. 588 */ 589 public KualiDecimal getTotalDollarAmountAboveLineItems(String[] excludedTypes) { 590 return getTotalDollarAmountWithExclusions(excludedTypes, false); 591 } 592 593 /** 594 * Computes the total dollar amount with the specified item types and possibly below the line items excluded. 595 * 596 * @param excludedTypes the types of items to be excluded. 597 * @param includeBelowTheLine indicates whether below the line items shall be included. 598 * @return the total dollar amount with the specified item types excluded. 599 */ 600 public KualiDecimal getTotalDollarAmountWithExclusions(String[] excludedTypes, boolean includeBelowTheLine) { 601 List<PurApItem> itemsForTotal = (List<PurApItem>) getItems(); 602 603 return getTotalDollarAmountWithExclusionsSubsetItems(excludedTypes, includeBelowTheLine, itemsForTotal); 604 } 605 606 /** 607 * This method... 608 * @param excludedTypes 609 * @param includeBelowTheLine 610 * @param itemsForTotal 611 * @return 612 */ 613 protected KualiDecimal getTotalDollarAmountWithExclusionsSubsetItems(String[] excludedTypes, boolean includeBelowTheLine, List<PurApItem> itemsForTotal) { 614 if (excludedTypes == null) { 615 excludedTypes = new String[] {}; 616 } 617 618 KualiDecimal total = new KualiDecimal(BigDecimal.ZERO); 619 for (PurApItem item : itemsForTotal) { 620 item.refreshReferenceObject(PurapPropertyConstants.ITEM_TYPE); 621 ItemType it = item.getItemType(); 622 if ((includeBelowTheLine || it.isLineItemIndicator()) && !ArrayUtils.contains(excludedTypes, it.getItemTypeCode())) { 623 KualiDecimal totalAmount = item.getTotalAmount(); 624 KualiDecimal itemTotal = (totalAmount != null) ? totalAmount : KualiDecimal.ZERO; 625 total = total.add(itemTotal); 626 } 627 } 628 return total; 629 } 630 631 public KualiDecimal getTotalDollarAmountForTradeIn() { 632 List<PurApItem> tradeInItems = getTradeInItems(); 633 return getTotalDollarAmountWithExclusionsSubsetItems(null,false,tradeInItems); 634 } 635 636 /** 637 * This method... 638 * @param tradeInItems 639 */ 640 public List<PurApItem> getTradeInItems() { 641 List<PurApItem> tradeInItems = new ArrayList<PurApItem>(); 642 for (PurApItem purApItem : (List<PurApItem>)getItems()) { 643 if(purApItem.getItemAssignedToTradeInIndicator()) { 644 tradeInItems.add(purApItem); 645 } 646 } 647 return tradeInItems; 648 } 649 650 /** 651 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#getTotalPreTaxDollarAmount() 652 */ 653 public KualiDecimal getTotalPreTaxDollarAmount() { 654 return getTotalPreTaxDollarAmountAllItems(null); 655 } 656 657 /** 658 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#setTotalPreTaxDollarAmount(org.kuali.rice.kns.util.KualiDecimal) 659 */ 660 public void setTotalPreTaxDollarAmount(KualiDecimal amount) { 661 // do nothing, this is so that the jsp won't complain about totalDollarAmount have no setter method. 662 } 663 664 /** 665 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#getTotalPreTaxDollarAmountAllItems(java.lang.String[]) 666 */ 667 public KualiDecimal getTotalPreTaxDollarAmountAllItems(String[] excludedTypes) { 668 return getTotalPreTaxDollarAmountWithExclusions(excludedTypes, true); 669 } 670 671 /** 672 * Computes the total dollar amount of all above the line items. 673 * 674 * @return the total dollar amount of all above the line items. 675 */ 676 public KualiDecimal getTotalPreTaxDollarAmountAboveLineItems() { 677 return getTotalPreTaxDollarAmountAboveLineItems(null); 678 } 679 680 /** 681 * Computes the total dollar amount of all above the line items with the specified item types excluded. 682 * 683 * @param excludedTypes the types of items to be excluded. 684 * @return the total dollar amount of all above the line items with the specified item types excluded.. 685 */ 686 public KualiDecimal getTotalPreTaxDollarAmountAboveLineItems(String[] excludedTypes) { 687 return getTotalPreTaxDollarAmountWithExclusions(excludedTypes, false); 688 } 689 690 /** 691 * Computes the total dollar amount with the specified item types and possibly below the line items excluded. 692 * 693 * @param excludedTypes the types of items to be excluded. 694 * @param includeBelowTheLine indicates whether below the line items shall be included. 695 * @return the total dollar amount with the specified item types excluded. 696 */ 697 public KualiDecimal getTotalPreTaxDollarAmountWithExclusions(String[] excludedTypes, boolean includeBelowTheLine) { 698 if (excludedTypes == null) { 699 excludedTypes = new String[] {}; 700 } 701 702 KualiDecimal total = new KualiDecimal(BigDecimal.ZERO); 703 for (PurApItem item : (List<PurApItem>) getItems()) { 704 item.refreshReferenceObject(PurapPropertyConstants.ITEM_TYPE); 705 ItemType it = item.getItemType(); 706 if ((includeBelowTheLine || it.isLineItemIndicator()) && !ArrayUtils.contains(excludedTypes, it.getItemTypeCode())) { 707 KualiDecimal extendedPrice = item.getExtendedPrice(); 708 KualiDecimal itemTotal = (extendedPrice != null) ? extendedPrice : KualiDecimal.ZERO; 709 total = total.add(itemTotal); 710 } 711 } 712 return total; 713 } 714 715 public KualiDecimal getTotalTaxAmount() { 716 return getTotalTaxAmountAllItems(null); 717 } 718 719 public void setTotalTaxAmount(KualiDecimal amount) { 720 // do nothing, this is so that the jsp won't complain about totalTaxAmount have no setter method. 721 } 722 723 public KualiDecimal getTotalTaxAmountAllItems(String[] excludedTypes) { 724 return getTotalTaxAmountWithExclusions(excludedTypes, true); 725 } 726 727 public KualiDecimal getTotalTaxAmountAboveLineItems() { 728 return getTotalTaxAmountAboveLineItems(null); 729 } 730 731 public KualiDecimal getTotalTaxAmountAboveLineItems(String[] excludedTypes) { 732 return getTotalTaxAmountWithExclusions(excludedTypes, false); 733 } 734 735 public KualiDecimal getTotalTaxAmountWithExclusions(String[] excludedTypes, boolean includeBelowTheLine) { 736 if (excludedTypes == null) { 737 excludedTypes = new String[] {}; 738 } 739 740 KualiDecimal total = new KualiDecimal(BigDecimal.ZERO); 741 for (PurApItem item : (List<PurApItem>) getItems()) { 742 item.refreshReferenceObject(PurapPropertyConstants.ITEM_TYPE); 743 ItemType it = item.getItemType(); 744 if ((includeBelowTheLine || it.isLineItemIndicator()) && !ArrayUtils.contains(excludedTypes, it.getItemTypeCode())) { 745 KualiDecimal taxAmount = item.getItemTaxAmount(); 746 KualiDecimal itemTotal = (taxAmount != null) ? taxAmount : KualiDecimal.ZERO; 747 total = total.add(itemTotal); 748 } 749 } 750 return total; 751 } 752 753 public boolean isUseTaxIndicator() { 754 return useTaxIndicator; 755 } 756 757 public void setUseTaxIndicator(boolean useTaxIndicator) { 758 this.useTaxIndicator = useTaxIndicator; 759 } 760 761 /** 762 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#templateVendorAddress(VendorAddress) 763 */ 764 public void templateVendorAddress(VendorAddress vendorAddress) { 765 if (vendorAddress == null) { 766 return; 767 } 768 this.setVendorLine1Address(vendorAddress.getVendorLine1Address()); 769 this.setVendorLine2Address(vendorAddress.getVendorLine2Address()); 770 this.setVendorCityName(vendorAddress.getVendorCityName()); 771 this.setVendorStateCode(vendorAddress.getVendorStateCode()); 772 this.setVendorPostalCode(vendorAddress.getVendorZipCode()); 773 this.setVendorCountryCode(vendorAddress.getVendorCountryCode()); 774 } 775 776 /** 777 * Returns the vendor number for this document. 778 * 779 * @return the vendor number for this document. 780 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument#getVendorNumber() 781 */ 782 public String getVendorNumber() { 783 if (StringUtils.isNotEmpty(vendorNumber)) { 784 return vendorNumber; 785 } 786 else if (ObjectUtils.isNotNull(vendorDetail)) { 787 return vendorDetail.getVendorNumber(); 788 } 789 else 790 return ""; 791 } 792 793 public void setVendorNumber(String vendorNumber) { 794 this.vendorNumber = vendorNumber; 795 } 796 797 public Boolean getOverrideWorkflowButtons() { 798 return overrideWorkflowButtons; 799 } 800 801 public void setOverrideWorkflowButtons(Boolean overrideWorkflowButtons) { 802 this.overrideWorkflowButtons = overrideWorkflowButtons; 803 } 804 805 public Integer getVendorHeaderGeneratedIdentifier() { 806 return vendorHeaderGeneratedIdentifier; 807 } 808 809 public void setVendorHeaderGeneratedIdentifier(Integer vendorHeaderGeneratedIdentifier) { 810 this.vendorHeaderGeneratedIdentifier = vendorHeaderGeneratedIdentifier; 811 } 812 813 public Integer getVendorDetailAssignedIdentifier() { 814 return vendorDetailAssignedIdentifier; 815 } 816 817 public void setVendorDetailAssignedIdentifier(Integer vendorDetailAssignedIdentifier) { 818 this.vendorDetailAssignedIdentifier = vendorDetailAssignedIdentifier; 819 } 820 821 public String getVendorCustomerNumber() { 822 return vendorCustomerNumber; 823 } 824 825 public void setVendorCustomerNumber(String vendorCustomerNumber) { 826 this.vendorCustomerNumber = vendorCustomerNumber; 827 } 828 829 public Integer getPurapDocumentIdentifier() { 830 return purapDocumentIdentifier; 831 } 832 833 public void setPurapDocumentIdentifier(Integer identifier) { 834 this.purapDocumentIdentifier = identifier; 835 } 836 837 public Status getStatus() { 838 if (ObjectUtils.isNull(this.status) && StringUtils.isNotEmpty(this.getStatusCode())) { 839 this.refreshReferenceObject(PurapPropertyConstants.STATUS); 840 } 841 else if (ObjectUtils.isNotNull(status) && StringUtils.isNotEmpty(getStatusCode()) && !status.getStatusCode().equals(getStatusCode())) { 842 this.refreshReferenceObject(PurapPropertyConstants.STATUS); 843 } 844 return status; 845 } 846 847 public void setStatus(Status status) { 848 this.status = status; 849 } 850 851 public String getStatusCode() { 852 return statusCode; 853 } 854 855 public void setStatusCode(String statusCode) { 856 this.statusCode = statusCode; 857 } 858 859 public VendorDetail getVendorDetail() { 860 return vendorDetail; 861 } 862 863 public void setVendorDetail(VendorDetail vendorDetail) { 864 this.vendorDetail = vendorDetail; 865 } 866 867 @SuppressWarnings("rawtypes") 868 public List getItems() { 869 return items; 870 } 871 872 @SuppressWarnings("rawtypes") 873 public void setItems(List items) { 874 this.items = items; 875 } 876 877 public String getVendorCityName() { 878 return vendorCityName; 879 } 880 881 public void setVendorCityName(String vendorCityName) { 882 this.vendorCityName = vendorCityName; 883 } 884 885 public String getVendorCountryCode() { 886 return vendorCountryCode; 887 } 888 889 public void setVendorCountryCode(String vendorCountryCode) { 890 this.vendorCountryCode = vendorCountryCode; 891 } 892 893 public String getVendorLine1Address() { 894 return vendorLine1Address; 895 } 896 897 public void setVendorLine1Address(String vendorLine1Address) { 898 this.vendorLine1Address = vendorLine1Address; 899 } 900 901 public String getVendorLine2Address() { 902 return vendorLine2Address; 903 } 904 905 public void setVendorLine2Address(String vendorLine2Address) { 906 this.vendorLine2Address = vendorLine2Address; 907 } 908 909 public String getVendorName() { 910 return vendorName; 911 } 912 913 public void setVendorName(String vendorName) { 914 this.vendorName = vendorName; 915 } 916 917 public String getVendorPostalCode() { 918 return vendorPostalCode; 919 } 920 921 public void setVendorPostalCode(String vendorPostalCode) { 922 this.vendorPostalCode = vendorPostalCode; 923 } 924 925 public String getVendorStateCode() { 926 return vendorStateCode; 927 } 928 929 public void setVendorStateCode(String vendorStateCode) { 930 this.vendorStateCode = vendorStateCode; 931 } 932 933 public String getVendorAddressInternationalProvinceName() { 934 return vendorAddressInternationalProvinceName; 935 } 936 937 public void setVendorAddressInternationalProvinceName(String vendorAddressInternationalProvinceName) { 938 this.vendorAddressInternationalProvinceName = vendorAddressInternationalProvinceName; 939 } 940 941 public Integer getVendorAddressGeneratedIdentifier() { 942 return vendorAddressGeneratedIdentifier; 943 } 944 945 public void setVendorAddressGeneratedIdentifier(Integer vendorAddressGeneratedIdentifier) { 946 this.vendorAddressGeneratedIdentifier = vendorAddressGeneratedIdentifier; 947 } 948 949 public Integer getAccountsPayablePurchasingDocumentLinkIdentifier() { 950 return accountsPayablePurchasingDocumentLinkIdentifier; 951 } 952 953 public void setAccountsPayablePurchasingDocumentLinkIdentifier(Integer accountsPayablePurchasingDocumentLinkIdentifier) { 954 this.accountsPayablePurchasingDocumentLinkIdentifier = accountsPayablePurchasingDocumentLinkIdentifier; 955 } 956 957 public String[] getBelowTheLineTypes() { 958 if (this.belowTheLineTypes == null) { 959 this.belowTheLineTypes = SpringContext.getBean(PurapService.class).getBelowTheLineForDocument(this); 960 } 961 return belowTheLineTypes; 962 } 963 964 public Country getVendorCountry() { 965 vendorCountry = SpringContext.getBean(CountryService.class).getByPrimaryIdIfNecessary(vendorCountryCode, vendorCountry); 966 return vendorCountry; 967 } 968 969 /** 970 * Added only to allow for {@link org.kuali.kfs.module.purap.util.PurApObjectUtils} class to work correctly. 971 * 972 * @deprecated 973 */ 974 public void setVendorCountry(Country vendorCountry) { 975 this.vendorCountry = vendorCountry; 976 } 977 978 public String getVendorAttentionName() { 979 return vendorAttentionName; 980 } 981 982 public void setVendorAttentionName(String vendorAttentionName) { 983 this.vendorAttentionName = vendorAttentionName; 984 } 985 986 /** 987 * Determines whether the account is debit. It always returns false. 988 * 989 * @param financialDocument The document containing the account to be validated. 990 * @param accountingLine The account to be validated. 991 * @return boolean false. 992 * @see org.kuali.kfs.sys.document.validation.AccountingLineRule#isDebit(org.kuali.kfs.sys.document.AccountingDocument, 993 * org.kuali.kfs.sys.businessobject.AccountingLine) 994 */ 995 public boolean isDebit(GeneralLedgerPendingEntrySourceDetail postable) { 996 return false; 997 } 998 999 public PurApRelatedViews getRelatedViews() { 1000 if (relatedViews == null) { 1001 relatedViews = new PurApRelatedViews(this.documentNumber, this.accountsPayablePurchasingDocumentLinkIdentifier); 1002 } 1003 return relatedViews; 1004 } 1005 1006 public void setRelatedViews(PurApRelatedViews relatedViews) { 1007 this.relatedViews = relatedViews; 1008 } 1009 1010 public String getStatusCodeForMultiboxSearching() { 1011 return statusCode; 1012 } 1013 1014 @Override 1015 public void refreshNonUpdateableReferences() { 1016 1017 super.refreshNonUpdateableReferences(); 1018 fixItemReferences(); 1019 } 1020 1021 /** 1022 * This method fixes the item references in this document if it's new 1023 */ 1024 public void fixItemReferences() { 1025 //fix item and account references in case this is a new doc (since they will be lost) 1026 if(ObjectUtils.isNull(this.purapDocumentIdentifier)) { 1027 for (PurApItem item : (List<PurApItem>)this.getItems()) { 1028 item.setPurapDocument(this); 1029 item.fixAccountReferences(); 1030 } 1031 } 1032 } 1033 1034 /** 1035 * Returns the trade in item of the document. 1036 * 1037 * @return 1038 */ 1039 public PurApItem getTradeInItem() { 1040 for (PurApItem item : (List<PurApItem>)getItems()) { 1041 if (item.getItemTypeCode().equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_TRADE_IN_CODE)) { 1042 return item; 1043 } 1044 } 1045 return null; 1046 } 1047 1048 /** 1049 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument.getIsATypeOfPurAPRecDoc(). 1050 */ 1051 public boolean getIsATypeOfPurAPRecDoc() { 1052 return true; 1053 } 1054 1055 /** 1056 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument.getIsATypeOfPurDoc(). 1057 */ 1058 public boolean getIsATypeOfPurDoc() { 1059 if (this instanceof PurchasingDocumentBase) 1060 return true; 1061 else 1062 return false; 1063 } 1064 1065 /** 1066 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument.getIsATypeOfPODoc(). 1067 */ 1068 public boolean getIsATypeOfPODoc() { 1069 if (this instanceof PurchaseOrderDocument) 1070 return true; 1071 else 1072 return false; 1073 } 1074 1075 /** 1076 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument.getIsPODoc(). 1077 */ 1078 public boolean getIsPODoc() { 1079 if ( (this instanceof PurchaseOrderDocument) && 1080 !(this instanceof PurchaseOrderAmendmentDocument) && 1081 !(this instanceof PurchaseOrderCloseDocument) && 1082 !(this instanceof PurchaseOrderPaymentHoldDocument) && 1083 !(this instanceof PurchaseOrderRemoveHoldDocument) && 1084 !(this instanceof PurchaseOrderReopenDocument) && 1085 !(this instanceof PurchaseOrderRetransmitDocument) && 1086 !(this instanceof PurchaseOrderSplitDocument) && 1087 !(this instanceof PurchaseOrderVoidDocument)) 1088 return true; 1089 else 1090 return false; 1091 } 1092 1093 /** 1094 * @see org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument.getIsATypeOfREQSDoc(). 1095 */ 1096 public boolean getIsReqsDoc() { 1097 if (this instanceof RequisitionDocument) 1098 return true; 1099 else 1100 return false; 1101 } 1102 1103 /** 1104 * build document title based on the properties of current document 1105 * 1106 * @param the default document title 1107 * @return the combine information of the given title and additional payment indicators 1108 */ 1109 protected String buildDocumentTitle(String title) { 1110 if(this.getVendorDetail() == null) { 1111 return title; 1112 } 1113 1114 Integer vendorHeaderGeneratedIdentifier = this.getVendorDetail().getVendorHeaderGeneratedIdentifier(); 1115 VendorService vendorService = SpringContext.getBean(VendorService.class); 1116 1117 Object[] indicators = new String[2]; 1118 1119 boolean isEmployeeVendor = vendorService.isVendorInstitutionEmployee(vendorHeaderGeneratedIdentifier); 1120 indicators[0] = isEmployeeVendor ? AdHocPaymentIndicator.EMPLOYEE_VENDOR : AdHocPaymentIndicator.OTHER; 1121 1122 boolean isVendorForeign = vendorService.isVendorForeign(vendorHeaderGeneratedIdentifier); 1123 indicators[1] = isVendorForeign ? AdHocPaymentIndicator.ALIEN_VENDOR : AdHocPaymentIndicator.OTHER; 1124 1125 for(Object indicator : indicators) { 1126 if(!AdHocPaymentIndicator.OTHER.equals(indicator)) { 1127 String titlePattern = title + " [{0}:{1}]"; 1128 return MessageFormat.format(titlePattern, indicators); 1129 } 1130 } 1131 1132 return title; 1133 } 1134 1135 /** 1136 * Overridden to return the source lines of all of the items 1137 * @see org.kuali.kfs.sys.document.AccountingDocumentBase#getSourceAccountingLines() 1138 */ 1139 @SuppressWarnings("rawtypes") 1140 @Override 1141 public List getSourceAccountingLines() { 1142 if (ObjectUtils.isNotNull(sourceAccountingLines) && !sourceAccountingLines.isEmpty()) { 1143 // do nothing because acct lines have already been set 1144 return sourceAccountingLines; 1145 } 1146 else { 1147 /* 1148 SpringContext.getBean(PurapAccountingService.class).updateAccountAmounts(this); 1149 return SpringContext.getBean(PurapAccountingService.class).generateSummary(getItems()); 1150 */ 1151 List<AccountingLine> sourceAccountingLines = new ArrayList<AccountingLine>(); 1152 for (Object itemAsObject : this.getItems()) { 1153 final PurApItem item = (PurApItem)itemAsObject; 1154 for (PurApAccountingLine accountingLine : item.getSourceAccountingLines()) { 1155 sourceAccountingLines.add(accountingLine); 1156 } 1157 } 1158 return sourceAccountingLines; 1159 } 1160 } 1161 1162 /** 1163 * Checks whether the related purchase order views need a warning to be displayed, 1164 * i.e. if at least one of the purchase orders has never been opened. 1165 * @return true if at least one related purchase order needs a warning; false otherwise 1166 */ 1167 public boolean getNeedWarningRelatedPOs() { 1168 List<PurchaseOrderView> poViews = getRelatedViews().getRelatedPurchaseOrderViews(); 1169 for (PurchaseOrderView poView : poViews) { 1170 if (poView.getNeedWarning()) 1171 return true; 1172 } 1173 return false; 1174 } 1175 1176 /** 1177 * Accounting lines that are read-only should skip validation 1178 * @see org.kuali.kfs.sys.document.AccountingDocumentBase#getPersistedSourceAccountingLinesForComparison() 1179 */ 1180 @SuppressWarnings("rawtypes") 1181 @Override 1182 protected List getPersistedSourceAccountingLinesForComparison() { 1183 LOG.info("Checking persisted source accounting lines for read-only fields"); 1184 List<String> restrictedItemTypesList = new ArrayList<String>(); 1185 try { 1186 restrictedItemTypesList = SpringContext.getBean(ParameterService.class).getParameterValues(this.getClass(), PurapParameterConstants.PURAP_ITEM_TYPES_RESTRICTING_ACCOUNT_EDIT); 1187 } catch (IllegalArgumentException iae) { 1188 // do nothing, not a problem if no restricted types are defined 1189 } 1190 1191 PurapAccountingService purApAccountingService = SpringContext.getBean(PurapAccountingService.class); 1192 List persistedSourceLines = new ArrayList(); 1193 1194 for (PurApItem item : (List<PurApItem>) this.getItems()) { 1195 // only check items that already have been persisted since last save 1196 if (ObjectUtils.isNotNull(item.getItemIdentifier())) { 1197 // Disable validation if the item is read-only 1198 final boolean isNotReadOnly = !((restrictedItemTypesList != null) && restrictedItemTypesList.contains(item.getItemTypeCode())); 1199 if (isNotReadOnly) { 1200 persistedSourceLines.addAll(purApAccountingService.getAccountsFromItem(item)); 1201 } 1202 } 1203 } 1204 return persistedSourceLines; 1205 } 1206 1207 /** 1208 * Accounting lines that are read-only should skip validation 1209 * @see org.kuali.kfs.sys.document.AccountingDocumentBase#getSourceAccountingLinesForComparison() 1210 */ 1211 @SuppressWarnings("rawtypes") 1212 @Override 1213 protected List getSourceAccountingLinesForComparison() { 1214 LOG.info("Checking source accounting lines for read-only fields"); 1215 List<String> restrictedItemTypesList = new ArrayList<String>(); 1216 try { 1217 restrictedItemTypesList = SpringContext.getBean(ParameterService.class).getParameterValues(this.getClass(), PurapParameterConstants.PURAP_ITEM_TYPES_RESTRICTING_ACCOUNT_EDIT); 1218 } catch (IllegalArgumentException iae) { 1219 // do nothing, not a problem if no restricted types are defined 1220 } 1221 PurapAccountingService purApAccountingService = SpringContext.getBean(PurapAccountingService.class); 1222 List currentSourceLines = new ArrayList(); 1223 for (PurApItem item : (List<PurApItem>) this.getItems()) { 1224 // Disable validation if the item is read-only 1225 final boolean isNotReadOnly = !((restrictedItemTypesList != null) && restrictedItemTypesList.contains(item.getItemTypeCode())); 1226 if (isNotReadOnly) { 1227 currentSourceLines.addAll(item.getSourceAccountingLines()); 1228 } 1229 } 1230 return currentSourceLines; 1231 } 1232 1233 }