View Javadoc
1   /*
2    * Copyright 2006 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.module.purap.document;
17  
18  import org.apache.commons.lang.ArrayUtils;
19  import org.apache.commons.lang.StringUtils;
20  import org.kuali.ole.module.purap.PurapConstants;
21  import org.kuali.ole.module.purap.PurapParameterConstants;
22  import org.kuali.ole.module.purap.PurapPropertyConstants;
23  import org.kuali.ole.module.purap.businessobject.*;
24  import org.kuali.ole.module.purap.document.service.PurapService;
25  import org.kuali.ole.module.purap.service.PurapAccountingService;
26  import org.kuali.ole.module.purap.service.SensitiveDataService;
27  import org.kuali.ole.module.purap.util.PurApRelatedViews;
28  import org.kuali.ole.select.businessobject.OleLicensingRequirement;
29  import org.kuali.ole.select.document.OleInvoiceDocument;
30  import org.kuali.ole.select.service.OleUrlResolver;
31  import org.kuali.ole.sys.OLEConstants.AdHocPaymentIndicator;
32  import org.kuali.ole.sys.businessobject.AccountingLine;
33  import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntry;
34  import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
35  import org.kuali.ole.sys.businessobject.SourceAccountingLine;
36  import org.kuali.ole.sys.context.SpringContext;
37  import org.kuali.ole.sys.document.AccountingDocumentBase;
38  import org.kuali.ole.sys.document.AmountTotaling;
39  import org.kuali.ole.sys.service.UniversityDateService;
40  import org.kuali.ole.vnd.businessobject.VendorAddress;
41  import org.kuali.ole.vnd.businessobject.VendorDetail;
42  import org.kuali.ole.vnd.document.service.VendorService;
43  import org.kuali.rice.core.api.config.property.ConfigContext;
44  import org.kuali.rice.core.api.util.type.KualiDecimal;
45  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
46  import org.kuali.rice.kew.api.WorkflowDocument;
47  import org.kuali.rice.krad.rules.rule.event.ApproveDocumentEvent;
48  import org.kuali.rice.krad.rules.rule.event.KualiDocumentEvent;
49  import org.kuali.rice.krad.rules.rule.event.RouteDocumentEvent;
50  import org.kuali.rice.krad.service.KualiModuleService;
51  import org.kuali.rice.krad.service.ModuleService;
52  import org.kuali.rice.krad.util.NoteType;
53  import org.kuali.rice.krad.util.ObjectUtils;
54  import org.kuali.rice.location.api.LocationConstants;
55  import org.kuali.rice.location.framework.country.CountryEbo;
56  
57  import java.math.BigDecimal;
58  import java.text.MessageFormat;
59  import java.util.*;
60  
61  /**
62   * Base class for Purchasing-Accounts Payable Documents.
63   */
64  public abstract class PurchasingAccountsPayableDocumentBase extends AccountingDocumentBase implements PurchasingAccountsPayableDocument, AmountTotaling {
65  
66      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PurchasingAccountsPayableDocumentBase.class);
67  
68      // SHARED FIELDS BETWEEN REQUISITION, PURCHASE ORDER, PAYMENT REQUEST, AND CREDIT MEMO
69      protected Integer purapDocumentIdentifier;
70      protected Integer vendorHeaderGeneratedIdentifier;
71      protected Integer vendorDetailAssignedIdentifier;
72      protected String vendorCustomerNumber;
73      protected String vendorName;
74      protected String vendorLine1Address;
75      protected String vendorLine2Address;
76      protected String vendorCityName;
77      protected String vendorStateCode;
78      protected String vendorAddressInternationalProvinceName;
79      protected String vendorPostalCode;
80      protected String vendorCountryCode;
81      protected Integer accountsPayablePurchasingDocumentLinkIdentifier;
82      protected boolean useTaxIndicator;
83      protected String vendorAttentionName;
84      protected String accountDistributionMethod;  //code for account distribution method
85      /**
86       * Variable purchaseOrderTypeId added to store order type
87       */
88      protected BigDecimal purchaseOrderTypeId;
89     /* protected boolean licensingRequirementIndicator;*/
90      /*protected String licensingRequirementCode;*/
91  
92      protected String statusCode;
93  
94      // NOT PERSISTED IN DB
95      protected String vendorNumber;
96      protected Integer vendorAddressGeneratedIdentifier;
97      protected Boolean overrideWorkflowButtons = null;
98      protected transient PurApRelatedViews relatedViews;
99      protected boolean sensitive;
100 
101     protected boolean calculated;
102 
103     // COLLECTIONS
104     protected List<PurApItem> items;
105     protected List<SourceAccountingLine> accountsForRouting; // don't use me for anything else!!
106 
107     // REFERENCE OBJECTS
108     protected VendorDetail vendorDetail;
109     protected CountryEbo vendorCountry;
110     protected PurchaseOrderType orderType;
111     protected OleLicensingRequirement licenseReqmt;
112 
113     // STATIC
114     public transient String[] belowTheLineTypes;
115 
116     // workaround for purapOjbCollectionHelper - remove when merged into rice
117     public boolean allowDeleteAwareCollection = true;
118 
119     //For Default Collapsing the tabs when initiating the document
120     private boolean overviewFlag;
121     private boolean deliveryFlag;
122     private boolean vendorFlag;
123     private boolean titlesFlag;
124     private boolean paymentInfoFlag;
125     private boolean additionalInstitutionalInfoFlag;
126     private boolean accountSummaryFlag;
127     private boolean relatedDocumentsFlag;
128     private boolean paymentHistoryFlag;
129     private boolean notesAndAttachmentFlag;
130     private boolean adHocRecipientsFlag;
131     private boolean routeLogFlag;
132 
133     private boolean invoiceInfoFlag;
134     private boolean processItemsFlag;
135     private boolean generalEntriesFlag;
136     private boolean creditMemoInfoFlag;
137 
138     // license request document number
139     /*public transient String licenseRequestDocNum = null;*/
140     /*private transient OleLicenseRequestView licenseRequestViews = new OleLicenseRequestView();*/
141     private transient OleUrlResolver oleUrlResolver;
142 
143 
144     /*public OleLicenseRequestView getLicenseRequestViews() {
145         return licenseRequestViews;
146     }
147 
148     public void setLicenseRequestViews(OleLicenseRequestView licenseRequestViews) {
149         this.licenseRequestViews = licenseRequestViews;
150     }*/
151 
152     /**
153      * Default constructor to be overridden.
154      */
155     public PurchasingAccountsPayableDocumentBase() {
156         items = new ArrayList();
157     }
158 
159     protected GeneralLedgerPendingEntry getFirstPendingGLEntry() {
160         if (ObjectUtils.isNotNull(getGeneralLedgerPendingEntries()) && !getGeneralLedgerPendingEntries().isEmpty()) {
161             return getGeneralLedgerPendingEntries().get(0);
162         }
163         return null;
164     }
165 
166     public Integer getPostingYearFromPendingGLEntries() {
167         GeneralLedgerPendingEntry glpe = getFirstPendingGLEntry();
168         if (ObjectUtils.isNotNull(glpe)) {
169             return glpe.getUniversityFiscalYear();
170         }
171         return null;
172     }
173 
174     public String getPostingPeriodCodeFromPendingGLEntries() {
175         GeneralLedgerPendingEntry glpe = getFirstPendingGLEntry();
176         if (ObjectUtils.isNotNull(glpe)) {
177             return glpe.getUniversityFiscalPeriodCode();
178         }
179         return null;
180     }
181 
182     public List<SourceAccountingLine> getAccountsForRouting() {
183         if (accountsForRouting == null) {
184             populateAccountsForRouting();
185         }
186         return accountsForRouting;
187     }
188 
189     public void setAccountsForRouting(List<SourceAccountingLine> accountsForRouting) {
190         this.accountsForRouting = accountsForRouting;
191     }
192 
193     /**
194      * Makes sure that accounts for routing has been generated, so that other information can be retrieved from that
195      */
196     protected void populateAccountsForRouting() {
197         SpringContext.getBean(PurapAccountingService.class).updateAccountAmounts(this);
198         setAccountsForRouting(SpringContext.getBean(PurapAccountingService.class).generateSummary(getItems()));
199         // need to refresh to get the references for the searchable attributes (ie status) and for invoking route levels (ie account
200         // objects) -hjs
201         refreshNonUpdateableReferences();
202         for (SourceAccountingLine sourceLine : getAccountsForRouting()) {
203             sourceLine.refreshNonUpdateableReferences();
204         }
205     }
206 
207     public boolean isSensitive() {
208         List<SensitiveData> sensitiveData = SpringContext.getBean(SensitiveDataService.class).getSensitiveDatasAssignedByRelatedDocId(getAccountsPayablePurchasingDocumentLinkIdentifier());
209         if (ObjectUtils.isNotNull(sensitiveData) && !sensitiveData.isEmpty()) {
210             return true;
211         }
212         return false;
213     }
214 
215     /**
216      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#isInquiryRendered()
217      */
218     @Override
219     public boolean isInquiryRendered() {
220         return isPostingYearPrior();
221     }
222 
223     /**
224      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#isPostingYearNext()
225      */
226     @Override
227     public boolean isPostingYearNext() {
228         Integer currentFY = SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear();
229         return (getPostingYear().compareTo(currentFY) > 0);
230     }
231 
232     /**
233      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#isPostingYearPrior()
234      */
235     @Override
236     public boolean isPostingYearPrior() {
237         Integer currentFY = SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear();
238         return (getPostingYear().compareTo(currentFY) < 0);
239     }
240 
241     /**
242      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#getPostingYearNextOrCurrent()
243      */
244     @Override
245     public Integer getPostingYearNextOrCurrent() {
246         if (isPostingYearNext()) {
247             //FY is set to next; use it
248             return getPostingYear();
249         }
250         //FY is NOT set to next; use CURRENT
251         return SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear();
252     }
253 
254     /**
255      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#getItemClass()
256      */
257     @Override
258     @SuppressWarnings("rawtypes")
259     public abstract Class getItemClass();
260 
261     @SuppressWarnings("rawtypes")
262     public abstract Class getItemUseTaxClass();
263 
264     /**
265      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#getPurApSourceDocumentIfPossible()
266      */
267     @Override
268     public abstract PurchasingAccountsPayableDocument getPurApSourceDocumentIfPossible();
269 
270     /**
271      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#getPurApSourceDocumentLabelIfPossible()
272      */
273     @Override
274     public abstract String getPurApSourceDocumentLabelIfPossible();
275 
276     /**
277      * @see org.kuali.rice.krad.document.DocumentBase#prepareForSave()
278      */
279     @Override
280     public void prepareForSave(KualiDocumentEvent event) {
281         customPrepareForSave(event);
282         super.prepareForSave(event);
283         fixItemReferences();
284     }
285 
286     /**
287      * PURAP documents are all overriding this method to return false because sufficient funds checking should not be performed on
288      * route of any PURAP documents. Only the Purchase Order performs a sufficient funds check and it is manually forced during
289      * routing.
290      *
291      * @see org.kuali.ole.sys.document.GeneralLedgerPostingDocumentBase#documentPerformsSufficientFundsCheck()
292      */
293     @Override
294     public boolean documentPerformsSufficientFundsCheck() {
295         return false;
296     }
297 
298     // for app doc status
299     @Override
300     public boolean isDocumentStoppedInRouteNode(String nodeName) {
301         WorkflowDocument workflowDocument = this.getFinancialSystemDocumentHeader().getWorkflowDocument();
302 
303         Set<String> names = workflowDocument.getCurrentNodeNames();
304         List<String> currentRouteLevels = new ArrayList<String>(names);
305         if (currentRouteLevels.contains(nodeName) && workflowDocument.isApprovalRequested()) {
306             return true;
307         }
308         return false;
309     }
310 
311     /**
312      * Records the specified error message into the Log file and throws a runtime exception.
313      *
314      * @param errorMessage the error message to be logged.
315      */
316     protected void logAndThrowRuntimeException(String errorMessage) {
317         this.logAndThrowRuntimeException(errorMessage, null);
318     }
319 
320     /**
321      * Records the specified error message into the Log file and throws the specified runtime exception.
322      *
323      * @param errorMessage the specified error message.
324      * @param e            the specified runtime exception.
325      */
326     protected void logAndThrowRuntimeException(String errorMessage, Exception e) {
327         if (ObjectUtils.isNotNull(e)) {
328             LOG.error(errorMessage, e);
329             throw new RuntimeException(errorMessage, e);
330         } else {
331             LOG.error(errorMessage);
332             throw new RuntimeException(errorMessage);
333         }
334     }
335 
336     /**
337      * Allows child PO classes to customize the prepareForSave method. Most of the subclasses need to call the super's method to get
338      * the GL entry creation, but they each need to do different things to prepare for those entries to be created. This is only for
339      * PO since it has children classes that need different prep work for GL creation.
340      *
341      * @param event the event involved in this action.
342      */
343     public void customPrepareForSave(KualiDocumentEvent event) {
344         // Need this here so that it happens before the GL work is done
345         SpringContext.getBean(PurapAccountingService.class).updateAccountAmounts(this);
346 
347         if (event instanceof RouteDocumentEvent || event instanceof ApproveDocumentEvent) {
348             if (this instanceof VendorCreditMemoDocument && ((VendorCreditMemoDocument) this).isSourceVendor()) {
349                 return;
350             }
351             if (this instanceof OleInvoiceDocument || this instanceof InvoiceDocument) {
352                 return;
353             }
354             SpringContext.getBean(PurapService.class).calculateTax(this);
355         }
356         // These next 5 lines are temporary changes so that we can use PurApOjbCollectionHelper for release 2.
357         // But these 5 lines will not be necessary anymore if the changes in PurApOjbCollectionHelper is
358         // merge into Rice.
359 //        this.allowDeleteAwareCollection = true;
360 //        DocumentDaoOjb docDao = SpringContext.getBean(DocumentDaoOjb.class);
361         // PurchasingAccountsPayableDocumentBase retrievedDocument = (PurchasingAccountsPayableDocumentBase)
362         // docDao.findByDocumentHeaderId(this.getClass(), this.getDocumentNumber());
363 //        if (retrievedDocument != null) {
364 //            retrievedDocument.allowDeleteAwareCollection = true;
365 //        }
366 //
367 //        SpringContext.getBean(PurApOjbCollectionHelper.class).processCollections(docDao, this, retrievedDocument);
368 //        this.allowDeleteAwareCollection = false;
369 //        if (retrievedDocument != null) {
370 //            retrievedDocument.allowDeleteAwareCollection = false;
371 //        }
372     }
373 
374     /**
375      * @see org.kuali.ole.sys.document.AccountingDocumentBase#buildListOfDeletionAwareLists()
376      */
377     @Override
378     public List buildListOfDeletionAwareLists() {
379         List managedLists = new ArrayList<List>();
380         managedLists.add(getDeletionAwareAccountingLines());
381         if (allowDeleteAwareCollection) {
382             //From now on, the list of accounting lines would have been added when the
383             //super.buildListOfDeletionAwareLists() is executed when it calls getSourceAccountingLines().
384             //So we can remove the old codes that used to exist here to add the accounts to the
385             //managedLists and just use the one from the super.buildListOfDeletionAwareLists()
386             List<PurApItemBase> subManageList = this.getItems();
387             List useTaxItems = new ArrayList();
388             for (PurApItemBase subManage : subManageList) {
389                 useTaxItems.addAll(subManage.getUseTaxItems());
390             }
391 
392             managedLists.add(this.getItems());
393             managedLists.add(useTaxItems);
394         }
395         return managedLists;
396     }
397 
398     /**
399      * Build deletion list of accounting lines for PurAp generic use.
400      *
401      * @return
402      */
403     @SuppressWarnings("rawtypes")
404     protected List getDeletionAwareAccountingLines() {
405         List<PurApAccountingLine> deletionAwareAccountingLines = new ArrayList<PurApAccountingLine>();
406         for (Object itemAsObject : this.getItems()) {
407             final PurApItem item = (PurApItem) itemAsObject;
408             for (PurApAccountingLine accountingLine : item.getSourceAccountingLines()) {
409                 deletionAwareAccountingLines.add(accountingLine);
410             }
411         }
412         return deletionAwareAccountingLines;
413     }
414 
415     /**
416      * @Override public List buildListOfDeletionAwareLists() { List managedLists = new ArrayList(); if (allowDeleteAwareCollection) {
417      * List<PurApAccountingLine> purapAccountsList = new ArrayList<PurApAccountingLine>(); for (Object itemAsObject :
418      * this.getItems()) { final PurApItem item = (PurApItem)itemAsObject;
419      * purapAccountsList.addAll(item.getSourceAccountingLines()); } managedLists.add(purapAccountsList);
420      * managedLists.add(this.getItems()); } return managedLists; }
421      * @see org.kuali.ole.sys.document.AccountingDocumentBase#buildListOfDeletionAwareLists()
422      */
423 
424     @Override
425     public void processAfterRetrieve() {
426         super.processAfterRetrieve();
427 
428         refreshNonUpdateableReferences();
429     }
430 
431     /**
432      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#addItem(PurApItem item)
433      */
434     @Override
435     public void addItem(PurApItem item) {
436         int itemLinePosition = getItemLinePosition();
437         if (ObjectUtils.isNotNull(item.getItemLineNumber()) && (item.getItemLineNumber() > 0) && (item.getItemLineNumber() <= itemLinePosition)) {
438             itemLinePosition = item.getItemLineNumber().intValue() - 1;
439         }
440 
441         item.setPurapDocumentIdentifier(this.purapDocumentIdentifier);
442         item.setPurapDocument(this);
443 
444         items.add(itemLinePosition, item);
445         renumberItems(itemLinePosition);
446     }
447 
448     /**
449      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#deleteItem(int lineNum)
450      */
451     @Override
452     public void deleteItem(int lineNum) {
453         if (items.remove(lineNum) == null) {
454             // throw error here
455         }
456         renumberItems(lineNum);
457     }
458 
459     /**
460      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#renumberItems(int start)
461      */
462     @Override
463     public void renumberItems(int start) {
464         for (int i = start; i < items.size(); i++) {
465             PurApItem item = items.get(i);
466             // only set the item line number for above the line items
467             if (item.getItemType().isLineItemIndicator()) {
468                 item.setItemLineNumber(new Integer(i + 1));
469             }
470         }
471     }
472 
473     /**
474      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#itemSwap(int positionFrom, int positionTo)
475      */
476     @Override
477     public void itemSwap(int positionFrom, int positionTo) {
478         // if out of range do nothing
479         if ((positionTo < 0) || (positionTo >= getItemLinePosition())) {
480             return;
481         }
482         PurApItem item1 = this.getItem(positionFrom);
483         PurApItem item2 = this.getItem(positionTo);
484         Integer oldFirstPos = item1.getItemLineNumber();
485         // swap line numbers
486         item1.setItemLineNumber(item2.getItemLineNumber());
487         item2.setItemLineNumber(oldFirstPos);
488         // fix ordering in list
489         items.remove(positionFrom);
490         items.add(positionTo, item1);
491     }
492 
493     /**
494      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#getItemLinePosition()
495      */
496     @Override
497     public int getItemLinePosition() {
498         int belowTheLineCount = 0;
499         for (PurApItem item : items) {
500             if (item.getItemType().isAdditionalChargeIndicator()) {
501                 belowTheLineCount++;
502             }
503         }
504         return items.size() - belowTheLineCount;
505     }
506 
507     /**
508      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#getItem(int pos)
509      */
510     @Override
511     public PurApItem getItem(int pos) {
512         return items.get(pos);
513     }
514 
515     /**
516      * Iterates through the items of the document and returns the item with the line number equal to the number given, or null if a
517      * match is not found.
518      *
519      * @param lineNumber line number to match on.
520      * @return the PurchasingAp Item if a match is found, else null.
521      */
522     @SuppressWarnings("rawtypes")
523     public PurApItem getItemByLineNumber(int lineNumber) {
524         for (Object element : items) {
525             PurApItem item = (PurApItem) element;
526             if (item.getItemLineNumber().intValue() == lineNumber) {
527                 return item;
528             }
529         }
530         return null;
531     }
532 
533     /**
534      * Find the item in the document via its string identifier.
535      *
536      * @param itemStrID the string identifier of the item being searched for
537      * @return the item being searched for
538      */
539     @SuppressWarnings("rawtypes")
540     public PurApItem getItemByStringIdentifier(String itemStrID) {
541         for (Object element : items) {
542             PurApItem item = (PurApItem) element;
543             if (StringUtils.equalsIgnoreCase(item.getItemIdentifierString(), itemStrID)) {
544                 return item;
545             }
546         }
547         return null;
548     }
549 
550     /**
551      * Find the item in the document via its identifier.
552      *
553      * @param itemID the string identifier of the item being searched for
554      * @return the item being searched for
555      */
556     @SuppressWarnings("rawtypes")
557     public PurApItem getItemByItemIdentifier(Integer itemID) {
558         for (Object element : items) {
559             PurApItem item = (PurApItem) element;
560             if (item.getItemIdentifier() == itemID) {
561                 return item;
562             }
563         }
564         return null;
565     }
566 
567     /**
568      * Overriding the parent method so that we can just set the posting year without the other stuff that the parent does to the
569      * accounting period. We only store the posting year on the doc and don't want the other stuff.
570      *
571      * @see org.kuali.ole.sys.document.LedgerPostingDocumentBase#setPostingYear(java.lang.Integer)
572      */
573     @Override
574     public void setPostingYear(Integer postingYear) {
575         this.postingYear = postingYear;
576     }
577 
578     /**
579      * @see org.kuali.ole.sys.document.AccountingDocumentBase#getTotalDollarAmount()
580      */
581     @Override
582     public KualiDecimal getTotalDollarAmount() {
583         return getTotalDollarAmountAllItems(null);
584     }
585 
586     /**
587      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#setTotalDollarAmount(KualiDecimal amount)
588      */
589     @Override
590     public void setTotalDollarAmount(KualiDecimal amount) {
591         // do nothing, this is so that the jsp won't complain about totalDollarAmount have no setter method.
592     }
593 
594     /**
595      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#getTotalDollarAmountAllItems(String[]
596      *      excludedTypes)
597      */
598     @Override
599     public KualiDecimal getTotalDollarAmountAllItems(String[] excludedTypes) {
600         return getTotalDollarAmountWithExclusions(excludedTypes, true);
601     }
602 
603     /**
604      * Computes the total dollar amount of all above the line items.
605      *
606      * @return the total dollar amount of all above the line items.
607      */
608     @Override
609     public KualiDecimal getTotalDollarAmountAboveLineItems() {
610         return getTotalDollarAmountAboveLineItems(null);
611     }
612 
613     /**
614      * Computes the total dollar amount of all above the line items with the specified item types excluded.
615      *
616      * @param excludedTypes the types of items to be excluded.
617      * @return the total dollar amount of all above the line items with the specified item types excluded..
618      */
619     public KualiDecimal getTotalDollarAmountAboveLineItems(String[] excludedTypes) {
620         return getTotalDollarAmountWithExclusions(excludedTypes, false);
621     }
622 
623     /**
624      * Computes the total dollar amount with the specified item types and possibly below the line items excluded.
625      *
626      * @param excludedTypes       the types of items to be excluded.
627      * @param includeBelowTheLine indicates whether below the line items shall be included.
628      * @return the total dollar amount with the specified item types excluded.
629      */
630     public KualiDecimal getTotalDollarAmountWithExclusions(String[] excludedTypes, boolean includeBelowTheLine) {
631         List<PurApItem> itemsForTotal = getItems();
632 
633         return getTotalDollarAmountWithExclusionsSubsetItems(excludedTypes, includeBelowTheLine, itemsForTotal);
634     }
635 
636     /**
637      * This method...
638      *
639      * @param excludedTypes
640      * @param includeBelowTheLine
641      * @param itemsForTotal
642      * @return
643      */
644     protected KualiDecimal getTotalDollarAmountWithExclusionsSubsetItems(String[] excludedTypes, boolean includeBelowTheLine, List<PurApItem> itemsForTotal) {
645         if (excludedTypes == null) {
646             excludedTypes = new String[]{};
647         }
648 
649         KualiDecimal total = new KualiDecimal(BigDecimal.ZERO);
650         for (PurApItem item : itemsForTotal) {
651             item.refreshReferenceObject(PurapPropertyConstants.ITEM_TYPE);
652             ItemType it = item.getItemType();
653             if ((includeBelowTheLine || it.isLineItemIndicator()) && !ArrayUtils.contains(excludedTypes, it.getItemTypeCode())) {
654                 KualiDecimal totalAmount = item.getTotalAmount();
655                 KualiDecimal itemTotal = (totalAmount != null) ? totalAmount : KualiDecimal.ZERO;
656                 total = total.add(itemTotal);
657             }
658         }
659         return total;
660     }
661 
662     @Override
663     public KualiDecimal getTotalDollarAmountForTradeIn() {
664         List<PurApItem> tradeInItems = getTradeInItems();
665         return getTotalDollarAmountWithExclusionsSubsetItems(null, false, tradeInItems);
666     }
667 
668     /**
669      * This method...
670      *
671      * @param tradeInItems
672      */
673     @Override
674     public List<PurApItem> getTradeInItems() {
675         List<PurApItem> tradeInItems = new ArrayList<PurApItem>();
676         for (PurApItem purApItem : (List<PurApItem>) getItems()) {
677             if (purApItem.getItemAssignedToTradeInIndicator()) {
678                 tradeInItems.add(purApItem);
679             }
680         }
681         return tradeInItems;
682     }
683 
684     /**
685      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#getTotalPreTaxDollarAmount()
686      */
687     @Override
688     public KualiDecimal getTotalPreTaxDollarAmount() {
689         return getTotalPreTaxDollarAmountAllItems(null);
690     }
691 
692     /**
693      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#setTotalPreTaxDollarAmount(org.kuali.rice.kns.util.KualiDecimal)
694      */
695     @Override
696     public void setTotalPreTaxDollarAmount(KualiDecimal amount) {
697         // do nothing, this is so that the jsp won't complain about totalDollarAmount have no setter method.
698     }
699 
700     /**
701      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#getTotalPreTaxDollarAmountAllItems(java.lang.String[])
702      */
703     @Override
704     public KualiDecimal getTotalPreTaxDollarAmountAllItems(String[] excludedTypes) {
705         return getTotalPreTaxDollarAmountWithExclusions(excludedTypes, true);
706     }
707 
708     /**
709      * Computes the total dollar amount of all above the line items.
710      *
711      * @return the total dollar amount of all above the line items.
712      */
713     public KualiDecimal getTotalPreTaxDollarAmountAboveLineItems() {
714         return getTotalPreTaxDollarAmountAboveLineItems(null);
715     }
716 
717     /**
718      * Computes the total dollar amount of all above the line items with the specified item types excluded.
719      *
720      * @param excludedTypes the types of items to be excluded.
721      * @return the total dollar amount of all above the line items with the specified item types excluded..
722      */
723     public KualiDecimal getTotalPreTaxDollarAmountAboveLineItems(String[] excludedTypes) {
724         return getTotalPreTaxDollarAmountWithExclusions(excludedTypes, false);
725     }
726 
727     /**
728      * Computes the total dollar amount with the specified item types and possibly below the line items excluded.
729      *
730      * @param excludedTypes       the types of items to be excluded.
731      * @param includeBelowTheLine indicates whether below the line items shall be included.
732      * @return the total dollar amount with the specified item types excluded.
733      */
734     public KualiDecimal getTotalPreTaxDollarAmountWithExclusions(String[] excludedTypes, boolean includeBelowTheLine) {
735         if (excludedTypes == null) {
736             excludedTypes = new String[]{};
737         }
738 
739         KualiDecimal total = new KualiDecimal(BigDecimal.ZERO);
740         for (PurApItem item : (List<PurApItem>) getItems()) {
741             item.refreshReferenceObject(PurapPropertyConstants.ITEM_TYPE);
742             ItemType it = item.getItemType();
743             if ((includeBelowTheLine || it.isLineItemIndicator()) && !ArrayUtils.contains(excludedTypes, it.getItemTypeCode())) {
744                 KualiDecimal extendedPrice = item.getExtendedPrice();
745                 KualiDecimal itemTotal = (extendedPrice != null) ? extendedPrice : KualiDecimal.ZERO;
746                 total = total.add(itemTotal);
747             }
748         }
749         return total;
750     }
751 
752     @Override
753     public KualiDecimal getTotalTaxAmount() {
754         return getTotalTaxAmountAllItems(null);
755     }
756 
757     @Override
758     public void setTotalTaxAmount(KualiDecimal amount) {
759         // do nothing, this is so that the jsp won't complain about totalTaxAmount have no setter method.
760     }
761 
762     @Override
763     public KualiDecimal getTotalTaxAmountAllItems(String[] excludedTypes) {
764         return getTotalTaxAmountWithExclusions(excludedTypes, true);
765     }
766 
767     @Override
768     public KualiDecimal getTotalTaxAmountAboveLineItems() {
769         return getTotalTaxAmountAboveLineItems(null);
770     }
771 
772     @Override
773     public KualiDecimal getTotalTaxAmountAboveLineItems(String[] excludedTypes) {
774         return getTotalTaxAmountWithExclusions(excludedTypes, false);
775     }
776 
777     @Override
778     public KualiDecimal getTotalTaxAmountWithExclusions(String[] excludedTypes, boolean includeBelowTheLine) {
779         if (excludedTypes == null) {
780             excludedTypes = new String[]{};
781         }
782 
783         KualiDecimal total = new KualiDecimal(BigDecimal.ZERO);
784         for (PurApItem item : (List<PurApItem>) getItems()) {
785             item.refreshReferenceObject(PurapPropertyConstants.ITEM_TYPE);
786             ItemType it = item.getItemType();
787             if ((includeBelowTheLine || it.isLineItemIndicator()) && !ArrayUtils.contains(excludedTypes, it.getItemTypeCode())) {
788                 KualiDecimal taxAmount = item.getItemTaxAmount();
789                 KualiDecimal itemTotal = (taxAmount != null) ? taxAmount : KualiDecimal.ZERO;
790                 total = total.add(itemTotal);
791             }
792         }
793         return total;
794     }
795 
796     @Override
797     public boolean isUseTaxIndicator() {
798         return useTaxIndicator;
799     }
800 
801     @Override
802     public void setUseTaxIndicator(boolean useTaxIndicator) {
803         this.useTaxIndicator = useTaxIndicator;
804     }
805 
806     /**
807      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#templateVendorAddress(VendorAddress)
808      */
809     @Override
810     public void templateVendorAddress(VendorAddress vendorAddress) {
811         if (vendorAddress == null) {
812             return;
813         }
814         this.setVendorLine1Address(vendorAddress.getVendorLine1Address());
815         this.setVendorLine2Address(vendorAddress.getVendorLine2Address());
816         this.setVendorCityName(vendorAddress.getVendorCityName());
817         this.setVendorStateCode(vendorAddress.getVendorStateCode());
818         this.setVendorPostalCode(vendorAddress.getVendorZipCode());
819         this.setVendorCountryCode(vendorAddress.getVendorCountryCode());
820     }
821 
822     /**
823      * Returns the vendor number for this document.
824      *
825      * @return the vendor number for this document.
826      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#getVendorNumber()
827      */
828     @Override
829     public String getVendorNumber() {
830         if (StringUtils.isNotEmpty(vendorNumber)) {
831             return vendorNumber;
832         } else if (ObjectUtils.isNotNull(vendorDetail)) {
833             return vendorDetail.getVendorNumber();
834         } else {
835             return "";
836         }
837     }
838 
839     @Override
840     public void setVendorNumber(String vendorNumber) {
841         this.vendorNumber = vendorNumber;
842     }
843 
844     public Boolean getOverrideWorkflowButtons() {
845         return overrideWorkflowButtons;
846     }
847 
848     public void setOverrideWorkflowButtons(Boolean overrideWorkflowButtons) {
849         this.overrideWorkflowButtons = overrideWorkflowButtons;
850     }
851 
852     @Override
853     public Integer getVendorHeaderGeneratedIdentifier() {
854         return vendorHeaderGeneratedIdentifier;
855     }
856 
857     @Override
858     public void setVendorHeaderGeneratedIdentifier(Integer vendorHeaderGeneratedIdentifier) {
859         this.vendorHeaderGeneratedIdentifier = vendorHeaderGeneratedIdentifier;
860     }
861 
862     @Override
863     public Integer getVendorDetailAssignedIdentifier() {
864         return vendorDetailAssignedIdentifier;
865     }
866 
867     @Override
868     public void setVendorDetailAssignedIdentifier(Integer vendorDetailAssignedIdentifier) {
869         this.vendorDetailAssignedIdentifier = vendorDetailAssignedIdentifier;
870     }
871 
872     @Override
873     public String getVendorCustomerNumber() {
874         return vendorCustomerNumber;
875     }
876 
877     @Override
878     public void setVendorCustomerNumber(String vendorCustomerNumber) {
879         this.vendorCustomerNumber = vendorCustomerNumber;
880     }
881 
882     @Override
883     public Integer getPurapDocumentIdentifier() {
884         return purapDocumentIdentifier;
885     }
886 
887     @Override
888     public void setPurapDocumentIdentifier(Integer identifier) {
889         this.purapDocumentIdentifier = identifier;
890     }
891 
892     @Override
893     public VendorDetail getVendorDetail() {
894         return vendorDetail;
895     }
896 
897     public void setVendorDetail(VendorDetail vendorDetail) {
898         this.vendorDetail = vendorDetail;
899     }
900 
901     @Override
902     @SuppressWarnings("rawtypes")
903     public List getItems() {
904         return items;
905     }
906 
907     @Override
908     @SuppressWarnings("rawtypes")
909     public void setItems(List items) {
910         this.items = items;
911     }
912 
913     @Override
914     public String getVendorCityName() {
915         return vendorCityName;
916     }
917 
918     @Override
919     public void setVendorCityName(String vendorCityName) {
920         this.vendorCityName = vendorCityName;
921     }
922 
923     @Override
924     public String getVendorCountryCode() {
925         return vendorCountryCode;
926     }
927 
928     @Override
929     public void setVendorCountryCode(String vendorCountryCode) {
930         this.vendorCountryCode = vendorCountryCode;
931     }
932 
933     @Override
934     public String getVendorLine1Address() {
935         return vendorLine1Address;
936     }
937 
938     @Override
939     public void setVendorLine1Address(String vendorLine1Address) {
940         this.vendorLine1Address = vendorLine1Address;
941     }
942 
943     @Override
944     public String getVendorLine2Address() {
945         return vendorLine2Address;
946     }
947 
948     @Override
949     public void setVendorLine2Address(String vendorLine2Address) {
950         this.vendorLine2Address = vendorLine2Address;
951     }
952 
953     @Override
954     public String getVendorName() {
955         return vendorName;
956     }
957 
958     @Override
959     public void setVendorName(String vendorName) {
960         this.vendorName = vendorName;
961     }
962 
963     @Override
964     public String getVendorPostalCode() {
965         return vendorPostalCode;
966     }
967 
968     @Override
969     public void setVendorPostalCode(String vendorPostalCode) {
970         this.vendorPostalCode = vendorPostalCode;
971     }
972 
973     @Override
974     public String getVendorStateCode() {
975         return vendorStateCode;
976     }
977 
978     @Override
979     public void setVendorStateCode(String vendorStateCode) {
980         this.vendorStateCode = vendorStateCode;
981     }
982 
983     @Override
984     public String getVendorAddressInternationalProvinceName() {
985         return vendorAddressInternationalProvinceName;
986     }
987 
988     @Override
989     public void setVendorAddressInternationalProvinceName(String vendorAddressInternationalProvinceName) {
990         this.vendorAddressInternationalProvinceName = vendorAddressInternationalProvinceName;
991     }
992 
993     @Override
994     public Integer getVendorAddressGeneratedIdentifier() {
995         return vendorAddressGeneratedIdentifier;
996     }
997 
998     @Override
999     public void setVendorAddressGeneratedIdentifier(Integer vendorAddressGeneratedIdentifier) {
1000         this.vendorAddressGeneratedIdentifier = vendorAddressGeneratedIdentifier;
1001     }
1002 
1003     @Override
1004     public Integer getAccountsPayablePurchasingDocumentLinkIdentifier() {
1005         return accountsPayablePurchasingDocumentLinkIdentifier;
1006     }
1007 
1008     @Override
1009     public void setAccountsPayablePurchasingDocumentLinkIdentifier(Integer accountsPayablePurchasingDocumentLinkIdentifier) {
1010         this.accountsPayablePurchasingDocumentLinkIdentifier = accountsPayablePurchasingDocumentLinkIdentifier;
1011     }
1012 
1013     @Override
1014     public String[] getBelowTheLineTypes() {
1015         if (this.belowTheLineTypes == null) {
1016             this.belowTheLineTypes = SpringContext.getBean(PurapService.class).getBelowTheLineForDocument(this);
1017         }
1018         return belowTheLineTypes;
1019     }
1020 
1021     @Override
1022     public CountryEbo getVendorCountry() {
1023         if (StringUtils.isBlank(vendorCountryCode)) {
1024             vendorCountry = null;
1025         } else {
1026             if (vendorCountry == null || !StringUtils.equals(vendorCountry.getCode(), vendorCountryCode)) {
1027                 ModuleService moduleService = SpringContext.getBean(KualiModuleService.class).getResponsibleModuleService(CountryEbo.class);
1028                 if (moduleService != null) {
1029                     Map<String, Object> keys = new HashMap<String, Object>(1);
1030                     keys.put(LocationConstants.PrimaryKeyConstants.CODE, vendorCountryCode);
1031                     vendorCountry = moduleService.getExternalizableBusinessObject(CountryEbo.class, keys);
1032                 } else {
1033                     throw new RuntimeException("CONFIGURATION ERROR: No responsible module found for EBO class.  Unable to proceed.");
1034                 }
1035             }
1036         }
1037         return vendorCountry;
1038     }
1039 
1040     /**
1041      * Added only to allow for {@link org.kuali.ole.module.purap.util.PurApObjectUtils} class to work correctly.
1042      *
1043      * @deprecated
1044      */
1045     @Deprecated
1046     public void setVendorCountry(CountryEbo vendorCountry) {
1047         this.vendorCountry = vendorCountry;
1048     }
1049 
1050     public String getVendorAttentionName() {
1051         return vendorAttentionName;
1052     }
1053 
1054     public void setVendorAttentionName(String vendorAttentionName) {
1055         this.vendorAttentionName = vendorAttentionName;
1056     }
1057 
1058     /**
1059      * Gets the accountDistributionMethod attribute.
1060      *
1061      * @return Returns the accountDistributionMethod
1062      */
1063 
1064     public String getAccountDistributionMethod() {
1065         return accountDistributionMethod;
1066     }
1067 
1068     /**
1069      * Sets the accountDistributionMethod attribute.
1070      *
1071      * @param accountDistributionMethod The accountDistributionMethod to set.
1072      */
1073     public void setAccountDistributionMethod(String accountDistributionMethod) {
1074         this.accountDistributionMethod = accountDistributionMethod;
1075     }
1076 
1077     /**
1078      * Determines whether the account is debit. It always returns false.
1079      *
1080      * @param financialDocument The document containing the account to be validated.
1081      * @param accountingLine    The account to be validated.
1082      * @return boolean false.
1083      * @see org.kuali.ole.sys.document.validation.AccountingLineRule#isDebit(org.kuali.ole.sys.document.AccountingDocument,
1084      *      org.kuali.ole.sys.businessobject.AccountingLine)
1085      */
1086     @Override
1087     public boolean isDebit(GeneralLedgerPendingEntrySourceDetail postable) {
1088         return false;
1089     }
1090 
1091     public PurApRelatedViews getRelatedViews() {
1092         if (relatedViews == null) {
1093             relatedViews = new PurApRelatedViews(this.documentNumber, this.getAccountsPayablePurchasingDocumentLinkIdentifier());
1094         }
1095         return relatedViews;
1096     }
1097 
1098     public void setRelatedViews(PurApRelatedViews relatedViews) {
1099         this.relatedViews = relatedViews;
1100     }
1101 
1102     @Override
1103     public void refreshNonUpdateableReferences() {
1104         super.refreshNonUpdateableReferences();
1105 
1106         for (PurApItem item : (List<PurApItem>) this.getItems()) {
1107             //refresh the accounts if they do exist...
1108             for (PurApAccountingLine account : item.getSourceAccountingLines()) {
1109                 account.refreshNonUpdateableReferences();
1110             }
1111         }
1112 
1113         fixItemReferences();
1114     }
1115 
1116     /**
1117      * This method fixes the item references in this document if it's new
1118      */
1119     @Override
1120     public void fixItemReferences() {
1121         //fix item and account references in case this is a new doc (since they will be lost)
1122         if (ObjectUtils.isNull(this.purapDocumentIdentifier)) {
1123             for (PurApItem item : (List<PurApItem>) this.getItems()) {
1124                 item.setPurapDocument(this);
1125                 item.fixAccountReferences();
1126             }
1127         }
1128     }
1129 
1130     /**
1131      * Returns the trade in item of the document.
1132      *
1133      * @return
1134      */
1135     @Override
1136     public PurApItem getTradeInItem() {
1137         for (PurApItem item : (List<PurApItem>) getItems()) {
1138             if (item.getItemTypeCode().equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_TRADE_IN_CODE)) {
1139                 return item;
1140             }
1141         }
1142         return null;
1143     }
1144 
1145     /**
1146      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument.getIsATypeOfPurAPRecDoc().
1147      */
1148     @Override
1149     public boolean getIsATypeOfPurAPRecDoc() {
1150         return true;
1151     }
1152 
1153     /**
1154      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument.getIsATypeOfPurDoc().
1155      */
1156     @Override
1157     public boolean getIsATypeOfPurDoc() {
1158         if (this instanceof PurchasingDocumentBase) {
1159             return true;
1160         } else {
1161             return false;
1162         }
1163     }
1164 
1165     /**
1166      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument.getIsATypeOfPODoc().
1167      */
1168     @Override
1169     public boolean getIsATypeOfPODoc() {
1170         if (this instanceof PurchaseOrderDocument) {
1171             return true;
1172         } else {
1173             return false;
1174         }
1175     }
1176 
1177     /**
1178      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument.getIsPODoc().
1179      */
1180     @Override
1181     public boolean getIsPODoc() {
1182         if ((this instanceof PurchaseOrderDocument) &&
1183                 !(this instanceof PurchaseOrderAmendmentDocument) &&
1184                 !(this instanceof PurchaseOrderCloseDocument) &&
1185                 !(this instanceof PurchaseOrderPaymentHoldDocument) &&
1186                 !(this instanceof PurchaseOrderRemoveHoldDocument) &&
1187                 !(this instanceof PurchaseOrderReopenDocument) &&
1188                 !(this instanceof PurchaseOrderRetransmitDocument) &&
1189                 !(this instanceof PurchaseOrderSplitDocument) &&
1190                 !(this instanceof PurchaseOrderVoidDocument)) {
1191             return true;
1192         } else {
1193             return false;
1194         }
1195     }
1196 
1197     /**
1198      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument.getIsATypeOfREQSDoc().
1199      */
1200     @Override
1201     public boolean getIsReqsDoc() {
1202         if (this instanceof RequisitionDocument) {
1203             return true;
1204         } else {
1205             return false;
1206         }
1207     }
1208 
1209     /**
1210      * build document title based on the properties of current document
1211      *
1212      * @param the default document title
1213      * @return the combine information of the given title and additional payment indicators
1214      */
1215     protected String buildDocumentTitle(String title) {
1216         if (this.getVendorDetail() == null) {
1217             return title;
1218         }
1219 
1220         Integer vendorHeaderGeneratedIdentifier = this.getVendorDetail().getVendorHeaderGeneratedIdentifier();
1221         VendorService vendorService = SpringContext.getBean(VendorService.class);
1222 
1223         Object[] indicators = new String[2];
1224 
1225         boolean isEmployeeVendor = vendorService.isVendorInstitutionEmployee(vendorHeaderGeneratedIdentifier);
1226         indicators[0] = isEmployeeVendor ? AdHocPaymentIndicator.EMPLOYEE_VENDOR : AdHocPaymentIndicator.OTHER;
1227 
1228         boolean isVendorForeign = vendorService.isVendorForeign(vendorHeaderGeneratedIdentifier);
1229         indicators[1] = isVendorForeign ? AdHocPaymentIndicator.ALIEN_VENDOR : AdHocPaymentIndicator.OTHER;
1230 
1231         for (Object indicator : indicators) {
1232             if (!AdHocPaymentIndicator.OTHER.equals(indicator)) {
1233                 String titlePattern = title + " [{0}:{1}]";
1234                 return MessageFormat.format(titlePattern, indicators);
1235             }
1236         }
1237 
1238         return title;
1239     }
1240 
1241     /**
1242      * Overridden to return the source lines of all of the items
1243      *
1244      * @see org.kuali.ole.sys.document.AccountingDocumentBase#getSourceAccountingLines()
1245      */
1246     @SuppressWarnings("rawtypes")
1247     @Override
1248     public List getSourceAccountingLines() {
1249         if (ObjectUtils.isNotNull(sourceAccountingLines) && !sourceAccountingLines.isEmpty()) {
1250             // do nothing because acct lines have already been set
1251             return sourceAccountingLines;
1252         } else {
1253             /*
1254              * SpringContext.getBean(PurapAccountingService.class).updateAccountAmounts(this); return
1255              * SpringContext.getBean(PurapAccountingService.class).generateSummary(getItems());
1256             */
1257             List<AccountingLine> sourceAccountingLines = new ArrayList<AccountingLine>();
1258             for (Object itemAsObject : this.getItems()) {
1259                 final PurApItem item = (PurApItem) itemAsObject;
1260                 for (PurApAccountingLine accountingLine : item.getSourceAccountingLines()) {
1261                     // OLEMI-9053: check if the accounting line does not already exist in the list
1262                     // and if so then add to the list. Preventing duplicates
1263                     if (!isDuplicateAccountingLine(sourceAccountingLines, accountingLine)) {
1264                         sourceAccountingLines.add(accountingLine);
1265                     }
1266                 }
1267             }
1268             return sourceAccountingLines;
1269         }
1270     }
1271 
1272     /**
1273      * Helper method to check if the source accounting line is already in the list and if so return true
1274      *
1275      * @param sourceAccountingLines
1276      * @param accountingLine
1277      * @return true if it is a duplicate else return false.
1278      */
1279     protected boolean isDuplicateAccountingLine(List<AccountingLine> sourceAccountingLines,
1280                                                 PurApAccountingLine accountingLine) {
1281         for (AccountingLine sourceLine : sourceAccountingLines) {
1282             PurApAccountingLine purapAccountLine = (PurApAccountingLine) sourceLine;
1283 
1284             if (purapAccountLine.accountStringsAreEqual(accountingLine)) {
1285                 return true;
1286             }
1287         }
1288         return false;
1289     }
1290 
1291     /**
1292      * Helper method to find the matching accountingLines in the list of sourceAccountingLines and sum up the lines amounts.
1293      *
1294      * @param accountingLine
1295      * @return accountTotalGLEntryAmount
1296      */
1297     protected KualiDecimal getAccountTotalGLEntryAmount(AccountingLine matchingAccountingLine) {
1298         KualiDecimal accountTotalGLEntryAmount = KualiDecimal.ZERO;
1299 
1300         for (Object itemAsObject : this.getItems()) {
1301             final PurApItem item = (PurApItem) itemAsObject;
1302             for (PurApAccountingLine accountingLine : item.getSourceAccountingLines()) {
1303                 // OLEMI-9053: check if the accounting line is a duplicate then add the total
1304                 if (accountingLine.accountStringsAreEqual((SourceAccountingLine) matchingAccountingLine)) {
1305                     accountTotalGLEntryAmount = accountTotalGLEntryAmount.add(accountingLine.getAmount());
1306                 }
1307             }
1308         }
1309 
1310         return accountTotalGLEntryAmount;
1311     }
1312 
1313     /**
1314      * Checks whether the related purchase order views need a warning to be displayed, i.e. if at least one of the purchase orders
1315      * has never been opened.
1316      *
1317      * @return true if at least one related purchase order needs a warning; false otherwise
1318      */
1319     public boolean getNeedWarningRelatedPOs() {
1320         List<PurchaseOrderView> poViews = getRelatedViews().getRelatedPurchaseOrderViews();
1321         for (PurchaseOrderView poView : poViews) {
1322             if (poView.getNeedWarning()) {
1323                 return true;
1324             }
1325         }
1326         return false;
1327     }
1328 
1329     /**
1330      * Accounting lines that are read-only should skip validation
1331      *
1332      * @see org.kuali.ole.sys.document.AccountingDocumentBase#getPersistedSourceAccountingLinesForComparison()
1333      */
1334     @SuppressWarnings("rawtypes")
1335     @Override
1336     protected List getPersistedSourceAccountingLinesForComparison() {
1337         LOG.debug("Checking persisted source accounting lines for read-only fields");
1338         List<String> restrictedItemTypesList = new ArrayList<String>();
1339         try {
1340             restrictedItemTypesList = new ArrayList<String>(SpringContext.getBean(ParameterService.class).getParameterValuesAsString(this.getClass(), PurapParameterConstants.PURAP_ITEM_TYPES_RESTRICTING_ACCOUNT_EDIT));
1341         } catch (IllegalArgumentException iae) {
1342             // do nothing, not a problem if no restricted types are defined
1343         }
1344 
1345         PurapAccountingService purApAccountingService = SpringContext.getBean(PurapAccountingService.class);
1346         List persistedSourceLines = new ArrayList();
1347 
1348         for (PurApItem item : (List<PurApItem>) this.getItems()) {
1349             // only check items that already have been persisted since last save
1350             if (ObjectUtils.isNotNull(item.getItemIdentifier())) {
1351                 // Disable validation if the item is read-only
1352                 final boolean isNotReadOnly = !((restrictedItemTypesList != null) && restrictedItemTypesList.contains(item.getItemTypeCode()));
1353                 if (isNotReadOnly) {
1354                     persistedSourceLines.addAll(purApAccountingService.getAccountsFromItem(item));
1355                 }
1356             }
1357         }
1358         return persistedSourceLines;
1359     }
1360 
1361     /**
1362      * Accounting lines that are read-only should skip validation
1363      *
1364      * @see org.kuali.ole.sys.document.AccountingDocumentBase#getSourceAccountingLinesForComparison()
1365      */
1366     @SuppressWarnings("rawtypes")
1367     @Override
1368     protected List getSourceAccountingLinesForComparison() {
1369         LOG.debug("Checking source accounting lines for read-only fields");
1370         List<String> restrictedItemTypesList = new ArrayList<String>();
1371         try {
1372             restrictedItemTypesList = new ArrayList<String>(SpringContext.getBean(ParameterService.class).getParameterValuesAsString(this.getClass(), PurapParameterConstants.PURAP_ITEM_TYPES_RESTRICTING_ACCOUNT_EDIT));
1373         } catch (IllegalArgumentException iae) {
1374             // do nothing, not a problem if no restricted types are defined
1375         }
1376         PurapAccountingService purApAccountingService = SpringContext.getBean(PurapAccountingService.class);
1377         List currentSourceLines = new ArrayList();
1378         for (PurApItem item : (List<PurApItem>) this.getItems()) {
1379             // Disable validation if the item is read-only
1380             final boolean isNotReadOnly = !((restrictedItemTypesList != null) && restrictedItemTypesList.contains(item.getItemTypeCode()));
1381             if (isNotReadOnly) {
1382                 currentSourceLines.addAll(item.getSourceAccountingLines());
1383             }
1384         }
1385         return currentSourceLines;
1386     }
1387 
1388     /**
1389      * Gets the statusCode attribute.
1390      *
1391      * @return Returns the statusCode
1392      */
1393 
1394     public String getStatusCode() {
1395         return statusCode;
1396     }
1397 
1398     /**
1399      * Sets the statusCode attribute.
1400      *
1401      * @param statusCode The statusCode to set.
1402      */
1403     public void setStatusCode(String statusCode) {
1404         this.statusCode = statusCode;
1405     }
1406 
1407     /**
1408      * Gets the calculated attribute.
1409      *
1410      * @return Returns the calculated
1411      */
1412 
1413     @Override
1414     public boolean isCalculated() {
1415         return calculated;
1416     }
1417 
1418     /**
1419      * Sets the calculated attribute.
1420      *
1421      * @param calculated The calculated to set.
1422      */
1423     @Override
1424     public void setCalculated(boolean calculated) {
1425         this.calculated = calculated;
1426     }
1427 
1428     /**
1429      * @return
1430      */
1431     public BigDecimal getPurchaseOrderTypeId() {
1432         return purchaseOrderTypeId;
1433     }
1434 
1435     public void setPurchaseOrderTypeId(BigDecimal purchaseOrderTypeId) {
1436         this.purchaseOrderTypeId = purchaseOrderTypeId;
1437     }
1438 
1439     public void setPurchaseOrderTypeId(String purchaseOrderType) {
1440         Map orderTypeMap = new HashMap();
1441         String orderType = null;
1442         if (purchaseOrderType.equalsIgnoreCase("firm_fixed_ybp")) {
1443             orderType = PurapConstants.ORDER_TYPE_FIRM;
1444         } else if (purchaseOrderType.equalsIgnoreCase("standing")) {
1445             orderType = PurapConstants.ORDER_TYPE_STANDING;
1446             ;
1447         } else if (purchaseOrderType.equalsIgnoreCase("approval")) {
1448             orderType = PurapConstants.ORDER_TYPE_APPROVAL;
1449             ;
1450         } else if (purchaseOrderType.equalsIgnoreCase("subscription")) {
1451             orderType = PurapConstants.ORDER_TYPE_SUBSCRIPTION;
1452             ;
1453         }
1454 
1455         if (orderType != null) {
1456             orderTypeMap.put("purchaseOrderType", orderType);
1457             Collection<PurchaseOrderType> purchaseOrderTypeCollection = getBusinessObjectService().findMatching(PurchaseOrderType.class, orderTypeMap);
1458             for (PurchaseOrderType purchaseOrderTypeValue : purchaseOrderTypeCollection) {
1459                 BigDecimal id = purchaseOrderTypeValue.getPurchaseOrderTypeId();
1460                 this.purchaseOrderTypeId = id;
1461             }
1462         } else {
1463             this.purchaseOrderTypeId = new BigDecimal(purchaseOrderType);
1464         }
1465 
1466     }
1467 
1468 
1469     public PurchaseOrderType getOrderType() {
1470         return orderType;
1471     }
1472 
1473     public void setOrderType(PurchaseOrderType orderType) {
1474         this.orderType = orderType;
1475     }
1476 
1477     /*public boolean isLicensingRequirementIndicator() {
1478         return licensingRequirementIndicator;
1479     }
1480 
1481     public void setLicensingRequirementIndicator(boolean licensingRequirementIndicator) {
1482         this.licensingRequirementIndicator = licensingRequirementIndicator;
1483     }*/
1484 
1485    /* public String getLicensingRequirementCode() {
1486         return licensingRequirementCode;
1487     }
1488 
1489     public void setLicensingRequirementCode(String licensingRequirementCode) {
1490         this.licensingRequirementCode = licensingRequirementCode;
1491     }*/
1492 
1493 
1494    /* public OleLicensingRequirement getLicenseReqmt() {
1495         return licenseReqmt;
1496     }
1497 
1498     public void setLicenseReqmt(OleLicensingRequirement licenseReqmt) {
1499         this.licenseReqmt = licenseReqmt;
1500     }*/
1501 
1502     /*@Override
1503     public void setLicenseRequestDocNum(String licenseRequestDocNum) {
1504         this.licenseRequestDocNum = licenseRequestDocNum;
1505     }*/
1506 
1507     /**
1508      * This method gets the licenseRequest document number for the corresponding requisition document
1509      *
1510      * @see org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument#getLicenseRequestDocnum()
1511      * @return licenseRequestDocNum
1512      */
1513     /*@Override
1514     public String getLicenseRequestDocNum() {
1515         String reqDocNum = "";
1516         String licenseRequestDocNum = "";
1517         if(this instanceof RequisitionDocument) {
1518             reqDocNum = this.getDocumentNumber();
1519         }
1520         try {
1521             *//*
1522              * OleWebServiceProvider oleWebServiceProvider = (OleWebServiceProvider)
1523              * GlobalResourceLoader.getService(OLEConstants.OLE_WEB_SERVICE_PROVIDER); OleLicenseRequestWebService
1524              * oleLicenseRequestWebService = (OleLicenseRequestWebService) oleWebServiceProvider.
1525              * getService("org.kuali.ole.select.document.service.OleLicenseRequestWebService", "oleLicenseRequestWebService",
1526              * getLicenseURL());
1527              *//*
1528             // String licenseRequestDocNum = oleLicenseRequestWebService.getLicenseRequestDocNumber(reqDocNum);
1529 
1530             // Modified for Jira OLE -3991
1531             if (reqDocNum != null || !reqDocNum.isEmpty()) {
1532                 Map docNum = new HashMap();
1533                 docNum.put(OLEConstants.LicenseRequest.REQUISITIONS_DOC_NUMBER, reqDocNum);
1534                 OleLicenseRequestDetails oleLicenseRequestDetails = new OleLicenseRequestDetails();
1535                 List<OleLicenseRequestDetails> oleLicenseRequestDetailsList = (List<OleLicenseRequestDetails>) getBusinessObjectService()
1536                         .findMatching(OleLicenseRequestDetails.class, docNum);
1537                 if (oleLicenseRequestDetailsList.size() > 0) {
1538                     oleLicenseRequestDetails = oleLicenseRequestDetailsList.get(0);
1539                     licenseRequestDocNum = oleLicenseRequestDetails.getLicenseRequestDocNumber() != null
1540                             && !oleLicenseRequestDetails.getLicenseRequestDocNumber().isEmpty() ? oleLicenseRequestDetails
1541                             .getLicenseRequestDocNumber() : "";
1542                 }
1543 
1544             }
1545             return licenseRequestDocNum;
1546         } catch ( Exception ex ) {
1547             LOG.error( "Unable to access OleLicenseRequestWebService @ URL: " + getLicenseURL() + " for document # " + reqDocNum, ex );
1548             return "";
1549         }
1550     }*/
1551 
1552     /**
1553      * This method returns the licenserequest web service url
1554      *
1555      * @return url
1556      */
1557     public String getLicenseURL() {
1558         return ConfigContext.getCurrentContextConfig().getProperty("license.web.service.url");
1559 
1560         //	String environment = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(OLEConstants.ENVIRONMENT_KEY);
1561         //    String url  = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(environment + "."+OLEConstants.LICENSE_WEB_SERVICE_URL);
1562         //    return url;
1563     }
1564 
1565     public void setOleUrlResolver(OleUrlResolver oleUrlResolver) {
1566         this.oleUrlResolver = oleUrlResolver;
1567     }
1568 
1569 
1570     @Override
1571     public NoteType getNoteType() {
1572         return NoteType.BUSINESS_OBJECT;
1573     }
1574 
1575     /**
1576      * This method returns the overview Flag indicator
1577      * @return boolean
1578      */
1579     public boolean isOverviewFlag() {
1580         return overviewFlag;
1581     }
1582 
1583     /**
1584      * This method sets the overviewFlag
1585      * @param overviewFlag
1586      */
1587     public void setOverviewFlag(boolean overviewFlag) {
1588         this.overviewFlag = overviewFlag;
1589     }
1590 
1591     /**
1592      * This method returns the deliveryFlag
1593      * @return boolean
1594      */
1595     public boolean isDeliveryFlag() {
1596         return deliveryFlag;
1597     }
1598 
1599     /**
1600      * This method sets the deliveryFlag
1601      * @param deliveryFlag
1602      */
1603     public void setDeliveryFlag(boolean deliveryFlag) {
1604         this.deliveryFlag = deliveryFlag;
1605     }
1606 
1607     /**
1608      * This method returns the vendorFlag indicator
1609      * @return boolean
1610      */
1611     public boolean isVendorFlag() {
1612         return vendorFlag;
1613     }
1614 
1615     /**
1616      * This method sets the vendorFlag
1617      * @param vendorFlag
1618      */
1619     public void setVendorFlag(boolean vendorFlag) {
1620         this.vendorFlag = vendorFlag;
1621     }
1622 
1623     /**
1624      * This method returns the titlesFlag indicator
1625      * @return booelan
1626      */
1627     public boolean isTitlesFlag() {
1628         return titlesFlag;
1629     }
1630 
1631     /**
1632      * This methos sets the titlesFlag
1633      * @param titlesFlag
1634      */
1635     public void setTitlesFlag(boolean titlesFlag) {
1636         this.titlesFlag = titlesFlag;
1637     }
1638 
1639     /**
1640      * This method returns the paymentInfoFlag indicator
1641      * @return boolean
1642      */
1643     public boolean isPaymentInfoFlag() {
1644         return paymentInfoFlag;
1645     }
1646 
1647     /**
1648      * This method sets the paymentInfoFlag
1649      * @param paymentInfoFlag
1650      */
1651     public void setPaymentInfoFlag(boolean paymentInfoFlag) {
1652         this.paymentInfoFlag = paymentInfoFlag;
1653     }
1654 
1655     /**
1656      * This method returns the additionalInstitutionalInfoFlag indicator
1657      * @return boolean
1658      */
1659     public boolean isAdditionalInstitutionalInfoFlag() {
1660         return additionalInstitutionalInfoFlag;
1661     }
1662 
1663     /**
1664      * This method sets the additionalInstitutionalInfoFlag
1665      * @param additionalInstitutionalInfoFlag
1666      */
1667     public void setAdditionalInstitutionalInfoFlag(boolean additionalInstitutionalInfoFlag) {
1668         this.additionalInstitutionalInfoFlag = additionalInstitutionalInfoFlag;
1669     }
1670 
1671     /**
1672      * This method returns the accountSummaryFlag indicator
1673      * @return booelan
1674      */
1675     public boolean isAccountSummaryFlag() {
1676         return accountSummaryFlag;
1677     }
1678 
1679     /**
1680      * This method sets the accountSummaryFlag
1681      * @param accountSummaryFlag
1682      */
1683     public void setAccountSummaryFlag(boolean accountSummaryFlag) {
1684         this.accountSummaryFlag = accountSummaryFlag;
1685     }
1686 
1687     /**
1688      * This method returns the relatedDocumentFlag indicato
1689      * @return boolean
1690      */
1691     public boolean isRelatedDocumentsFlag() {
1692         return relatedDocumentsFlag;
1693     }
1694 
1695     /**
1696      * This method sets the relatedDocumentFlag
1697      * @param relatedDocumentsFlag
1698      */
1699     public void setRelatedDocumentsFlag(boolean relatedDocumentsFlag) {
1700         this.relatedDocumentsFlag = relatedDocumentsFlag;
1701     }
1702 
1703     /**
1704      * This method returns the paymentHistoryFlag indicator
1705      * @return boolean
1706      */
1707     public boolean isPaymentHistoryFlag() {
1708         return paymentHistoryFlag;
1709     }
1710 
1711     /**
1712      * This method sets the paymentHistoryFlag
1713      * @param paymentHistoryFlag
1714      */
1715     public void setPaymentHistoryFlag(boolean paymentHistoryFlag) {
1716         this.paymentHistoryFlag = paymentHistoryFlag;
1717     }
1718 
1719     /**
1720      * This method returns the notesAndAttachmentFlag indicator
1721      * @return boolean
1722      */
1723     public boolean isNotesAndAttachmentFlag() {
1724         return notesAndAttachmentFlag;
1725     }
1726 
1727     /**
1728      * This method sets the notesAndAttachmentFlag
1729      * @param notesAndAttachmentFlag
1730      */
1731     public void setNotesAndAttachmentFlag(boolean notesAndAttachmentFlag) {
1732         this.notesAndAttachmentFlag = notesAndAttachmentFlag;
1733     }
1734 
1735     /**
1736      * This method returns the adHocRecipientsFlag indicator
1737      * @return boolean
1738      */
1739     public boolean isAdHocRecipientsFlag() {
1740         return adHocRecipientsFlag;
1741     }
1742 
1743     /**
1744      * This method sets the adHocRecipientsFlag
1745      * @param adHocRecipientsFlag
1746      */
1747     public void setAdHocRecipientsFlag(boolean adHocRecipientsFlag) {
1748         this.adHocRecipientsFlag = adHocRecipientsFlag;
1749     }
1750 
1751     /**
1752      * This method returns the routeLogFlag indicator
1753      * @return boolean
1754      */
1755     public boolean isRouteLogFlag() {
1756         return routeLogFlag;
1757     }
1758 
1759     /**
1760      * This method sets the routeLogFlag
1761      * @param routeLogFlag
1762      */
1763     public void setRouteLogFlag(boolean routeLogFlag) {
1764         this.routeLogFlag = routeLogFlag;
1765     }
1766 
1767     /**
1768      * This method returns the invoiceInfoFlag
1769      * @return boolean
1770      */
1771     public boolean isInvoiceInfoFlag() {
1772         return invoiceInfoFlag;
1773     }
1774 
1775     /**
1776      * This method sets the invoiceInfoFlag
1777      * @param invoiceInfoFlag
1778      */
1779     public void setInvoiceInfoFlag(boolean invoiceInfoFlag) {
1780         this.invoiceInfoFlag = invoiceInfoFlag;
1781     }
1782 
1783     /**
1784      * This method returns the processItemFlag
1785      * @return boolean
1786      */
1787     public boolean isProcessItemsFlag() {
1788         return processItemsFlag;
1789     }
1790 
1791     /**
1792      * This method sets the processItemsFlag
1793      * @param processItemsFlag
1794      */
1795     public void setProcessItemsFlag(boolean processItemsFlag) {
1796         this.processItemsFlag = processItemsFlag;
1797     }
1798 
1799     /**
1800      * This method returns the generalEntriesFlag
1801      * @return boolean
1802      */
1803     public boolean isGeneralEntriesFlag() {
1804         return generalEntriesFlag;
1805     }
1806 
1807     /**
1808      * This method sets the generalEntriesFlag
1809       * @param generalEntriesFlag
1810      */
1811     public void setGeneralEntriesFlag(boolean generalEntriesFlag) {
1812         this.generalEntriesFlag = generalEntriesFlag;
1813     }
1814 
1815     /**
1816      * This method returns the creditMemoInfoFlag
1817      * @return boolean
1818      */
1819     public boolean isCreditMemoInfoFlag() {
1820         return creditMemoInfoFlag;
1821     }
1822 
1823     /**
1824      * This method sets the creditMemoInfoFlag
1825      * @param creditMemoInfoFlag
1826      */
1827     public void setCreditMemoInfoFlag(boolean creditMemoInfoFlag) {
1828         this.creditMemoInfoFlag = creditMemoInfoFlag;
1829     }
1830 }