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  
17  package org.kuali.ole.module.purap.businessobject;
18  
19  import org.kuali.ole.module.purap.PurapConstants;
20  import org.kuali.ole.module.purap.PurapPropertyConstants;
21  import org.kuali.ole.module.purap.document.InvoiceDocument;
22  import org.kuali.ole.module.purap.document.PurchaseOrderDocument;
23  import org.kuali.ole.module.purap.document.service.AccountsPayableService;
24  import org.kuali.ole.module.purap.document.service.PurapService;
25  import org.kuali.ole.module.purap.document.service.PurchaseOrderService;
26  import org.kuali.ole.module.purap.exception.PurError;
27  import org.kuali.ole.module.purap.util.ExpiredOrClosedAccountEntry;
28  import org.kuali.ole.module.purap.util.PurApItemUtils;
29  import org.kuali.ole.module.purap.util.PurApObjectUtils;
30  import org.kuali.ole.sys.context.SpringContext;
31  import org.kuali.rice.core.api.util.type.KualiDecimal;
32  import org.kuali.rice.krad.util.ObjectUtils;
33  
34  import java.math.BigDecimal;
35  import java.util.ArrayList;
36  import java.util.HashMap;
37  import java.util.List;
38  
39  /**
40   * Payment Request Item Business Object.
41   */
42  public class InvoiceItem extends AccountsPayableItemBase {
43      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(InvoiceItem.class);
44  
45      private BigDecimal purchaseOrderItemUnitPrice;
46      private KualiDecimal itemOutstandingInvoiceQuantity;
47      private KualiDecimal itemOutstandingInvoiceAmount;
48      private Integer invoiceIdentifier;
49      private Integer purchaseOrderIdentifier;
50      protected Integer accountsPayablePurchasingDocumentLinkIdentifier;
51      protected Integer poLineNumber;
52      protected boolean closePurchaseOrderIndicator;
53      protected boolean reopenPurchaseOrderIndicator;
54      protected Integer postingYear;
55      protected String recurringPaymentTypeCode;
56      protected RecurringPaymentType recurringPaymentType;
57      protected transient PurchaseOrderDocument purchaseOrderDocument;
58  
59      /**
60       * Default constructor.
61       */
62      public InvoiceItem() {
63  
64      }
65  
66      /**
67       * inv item constructor - Delegate
68       *
69       * @param poi - purchase order item
70       * @param inv - payment request document
71       */
72      public InvoiceItem(PurchaseOrderItem poi, InvoiceDocument inv) {
73          this(poi, inv, new HashMap<String, ExpiredOrClosedAccountEntry>());
74      }
75  
76      /**
77       * Constructs a new payment request item, but also merges expired accounts.
78       *
79       * @param poi                        - purchase order item
80       * @param inv                        - payment request document
81       * @param expiredOrClosedAccountList - list of expired or closed accounts to merge
82       */
83      public InvoiceItem(PurchaseOrderItem poi, InvoiceDocument inv, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
84  
85          // copy base attributes w/ extra array of fields not to be copied
86          PurApObjectUtils.populateFromBaseClass(PurApItemBase.class, poi, this, PurapConstants.PREQ_ITEM_UNCOPYABLE_FIELDS);
87  
88          setItemDescription(poi.getItemDescription());
89  
90          //New Source Line should be set for InvoiceItem
91          resetAccount();
92  
93          // set up accounts
94          List accounts = new ArrayList();
95          for (PurApAccountingLine account : poi.getSourceAccountingLines()) {
96              PurchaseOrderAccount poa = (PurchaseOrderAccount) account;
97  
98              // check if this account is expired/closed and replace as needed
99              SpringContext.getBean(AccountsPayableService.class).processExpiredOrClosedAccount(poa, expiredOrClosedAccountList);
100 
101             //KFSMI-4522 copy an accounting line with zero dollar amount if system parameter allows
102             if (poa.getAmount().isZero()) {
103                 if (SpringContext.getBean(AccountsPayableService.class).canCopyAccountingLinesWithZeroAmount()) {
104                     accounts.add(new InvoiceAccount(this, poa));
105                 }
106             } else {
107                 accounts.add(new InvoiceAccount(this, poa));
108             }
109         }
110 
111         this.setSourceAccountingLines(accounts);
112         this.getUseTaxItems().clear();
113         //List<PurApItemUseTax> newUseTaxItems = new ArrayList<PurApItemUseTax>();
114         /// this.setUseTaxItems(newUseTaxItems);
115         //copy use tax items over, and blank out keys (useTaxId and itemIdentifier)
116         /*
117         this.getUseTaxItems().clear();
118         for (PurApItemUseTax useTaxItem : poi.getUseTaxItems()) {
119             InvoiceItemUseTax newItemUseTax = new InvoiceItemUseTax(useTaxItem);
120             this.getUseTaxItems().add(newItemUseTax);
121 
122         }
123         */
124 
125         // clear amount and desc on below the line - we probably don't need that null
126         // itemType check but it's there just in case remove if it causes problems
127         // also do this if of type service
128         if ((ObjectUtils.isNotNull(this.getItemType()) && this.getItemType().isAmountBasedGeneralLedgerIndicator())) {
129             // setting unit price to be null to be more consistent with other below the line
130             this.setItemUnitPrice(null);
131         }
132 
133         // copy custom
134         this.purchaseOrderItemUnitPrice = poi.getItemUnitPrice();
135 //        this.purchaseOrderCommodityCode = poi.getPurchaseOrderCommodityCd();
136 
137         // set doc fields
138         this.setPurapDocumentIdentifier(inv.getPurapDocumentIdentifier());
139         this.setPurapDocument(inv);
140     }
141 
142     /**
143      * Retrieves a purchase order item by inspecting the item type to see if its above the line or below the line and returns the
144      * appropriate type.
145      *
146      * @return - purchase order item
147      */
148     @Override
149     public PurchaseOrderItem getPurchaseOrderItem() {
150         if (ObjectUtils.isNotNull(this.getPurapDocumentIdentifier())) {
151             if (ObjectUtils.isNull(this.getInvoice())) {
152                 this.refreshReferenceObject(PurapPropertyConstants.PURAP_DOC);
153             }
154         }
155         // ideally we should do this a different way - maybe move it all into the service or save this info somehow (make sure and
156         // update though)
157         if (getInvoice() != null) {
158             PurchaseOrderDocument po = this.getInvoice().getPurchaseOrderDocument(this.getPurchaseOrderIdentifier());
159             this.setPostingYear(po.getPostingYear());
160             if (po.getRecurringPaymentType() != null) {
161                 this.setRecurringPaymentType(po.getRecurringPaymentType());
162                 this.setRecurringPaymentTypeCode(po.getRecurringPaymentTypeCode());
163             }
164             PurchaseOrderItem poi = null;
165             if (this.getItemType().isLineItemIndicator()) {
166                 List<PurchaseOrderItem> items = po.getItems();
167                 poi = items.get(this.getItemLineNumber().intValue() - 1);
168                 // throw error if line numbers don't match
169                 // MSU Contribution DTT-3014 OLEMI-8483 OLECNTRB-974
170                 /*
171                  * List items = po.getItems(); if (items != null) { for (Object object : items) { PurchaseOrderItem item =
172                  * (PurchaseOrderItem) object; if (item != null && item.getItemLineNumber().equals(this.getItemLineNumber())) { poi
173                  * = item; break; } } }
174                  */
175             } else {
176                 poi = (PurchaseOrderItem) SpringContext.getBean(PurapService.class).getBelowTheLineByType(po, this.getItemType());
177             }
178             if (poi != null) {
179                 return poi;
180             } else {
181                 if (LOG.isDebugEnabled()) {
182                     LOG.debug("getPurchaseOrderItem() Returning null because PurchaseOrderItem object for line number" + getItemLineNumber() + "or itemType " + getItemTypeCode() + " is null");
183                 }
184                 return null;
185             }
186         } else {
187 
188             LOG.error("getPurchaseOrderItem() Returning null because invoice object is null");
189             throw new PurError("Payment Request Object in Purchase Order item line number " + getItemLineNumber() + "or itemType " + getItemTypeCode() + " is null");
190         }
191     }
192 
193     public KualiDecimal getPoOutstandingAmount() {
194         PurchaseOrderItem poi = getPurchaseOrderItem();
195         if (ObjectUtils.isNull(this.getPurchaseOrderItemUnitPrice()) || KualiDecimal.ZERO.equals(this.getPurchaseOrderItemUnitPrice())) {
196             return null;
197         } else {
198             return this.getPoOutstandingAmount(poi);
199         }
200     }
201 
202     private KualiDecimal getPoOutstandingAmount(PurchaseOrderItem poi) {
203         if (poi == null) {
204             return KualiDecimal.ZERO;
205         } else {
206             return poi.getItemOutstandingEncumberedAmount();
207         }
208     }
209 
210     public KualiDecimal getPoOriginalAmount() {
211         PurchaseOrderItem poi = getPurchaseOrderItem();
212         if (poi == null) {
213             return null;
214         } else {
215             return poi.getExtendedPrice();
216         }
217     }
218 
219     /**
220      * Exists due to a setter requirement by the htmlControlAttribute
221      *
222      * @param amount - po outstanding amount
223      * @deprecated
224      */
225     @Deprecated
226     public void setPoOutstandingAmount(KualiDecimal amount) {
227         // do nothing
228     }
229 
230 
231     public KualiDecimal getPoOutstandingQuantity() {
232         PurchaseOrderItem poi = getPurchaseOrderItem();
233         if (poi == null) {
234             return null;
235         } else {
236             if (PurapConstants.ItemTypeCodes.ITEM_TYPE_SERVICE_CODE.equals(this.getItemTypeCode())) {
237                 return null;
238             } else {
239                 return poi.getOutstandingQuantity();
240             }
241         }
242     }
243 
244     /**
245      * Exists due to a setter requirement by the htmlControlAttribute
246      *
247      * @param qty - po outstanding quantity
248      * @deprecated
249      */
250     @Deprecated
251     public void setPoOutstandingQuantity(KualiDecimal qty) {
252         // do nothing
253     }
254 
255     public BigDecimal getPurchaseOrderItemUnitPrice() {
256         return purchaseOrderItemUnitPrice;
257     }
258 
259     public Integer getAccountsPayablePurchasingDocumentLinkIdentifier() {
260         return accountsPayablePurchasingDocumentLinkIdentifier;
261     }
262 
263     public void setAccountsPayablePurchasingDocumentLinkIdentifier(Integer accountsPayablePurchasingDocumentLinkIdentifier) {
264         this.accountsPayablePurchasingDocumentLinkIdentifier = accountsPayablePurchasingDocumentLinkIdentifier;
265     }
266 
267     public Integer getPoLineNumber() {
268         return poLineNumber;
269     }
270 
271     public void setPoLineNumber(Integer poLineNumber) {
272         this.poLineNumber = poLineNumber;
273     }
274 
275 
276     public Integer getPurchaseOrderIdentifier() {
277         return purchaseOrderIdentifier;
278     }
279 
280     public void setPurchaseOrderIdentifier(Integer purchaseOrderIdentifier) {
281         this.purchaseOrderIdentifier = purchaseOrderIdentifier;
282     }
283 
284     public Integer getInvoiceIdentifier() {
285         return invoiceIdentifier;
286     }
287 
288     public void setInvoiceIdentifier(Integer invoiceIdentifier) {
289         this.invoiceIdentifier = invoiceIdentifier;
290     }
291 
292     public BigDecimal getOriginalAmountfromPO() {
293         return purchaseOrderItemUnitPrice;
294     }
295 
296     public void setOriginalAmountfromPO(BigDecimal purchaseOrderItemUnitPrice) {
297         // Do nothing
298     }
299 
300     public Integer getPostingYear() {
301         return postingYear;
302     }
303 
304     /**
305      * @see org.kuali.ole.sys.document.LedgerPostingDocument#setPostingYear(Integer)
306      */
307     public void setPostingYear(Integer postingYear) {
308         this.postingYear = postingYear;
309     }
310 
311     public void setPurchaseOrderItemUnitPrice(BigDecimal purchaseOrderItemUnitPrice) {
312         this.purchaseOrderItemUnitPrice = purchaseOrderItemUnitPrice;
313     }
314 
315     public KualiDecimal getItemOutstandingInvoiceAmount() {
316         return itemOutstandingInvoiceAmount;
317     }
318 
319     public void setItemOutstandingInvoiceAmount(KualiDecimal itemOutstandingInvoiceAmount) {
320         this.itemOutstandingInvoiceAmount = itemOutstandingInvoiceAmount;
321     }
322 
323     public KualiDecimal getItemOutstandingInvoiceQuantity() {
324         return itemOutstandingInvoiceQuantity;
325     }
326 
327     public void setItemOutstandingInvoiceQuantity(KualiDecimal itemOutstandingInvoiceQuantity) {
328         this.itemOutstandingInvoiceQuantity = itemOutstandingInvoiceQuantity;
329     }
330 
331     public InvoiceDocument getInvoice() {
332         if (ObjectUtils.isNotNull(getPurapDocumentIdentifier())) {
333             if (ObjectUtils.isNull(getPurapDocument())) {
334                 this.refreshReferenceObject(PurapPropertyConstants.PURAP_DOC);
335             }
336         }
337         return super.getPurapDocument();
338     }
339 
340     public void setInvoice(InvoiceDocument invoice) {
341         this.setPurapDocument(invoice);
342     }
343 
344     public boolean isClosePurchaseOrderIndicator() {
345         return closePurchaseOrderIndicator;
346     }
347 
348     public void setClosePurchaseOrderIndicator(boolean closePurchaseOrderIndicator) {
349         this.closePurchaseOrderIndicator = closePurchaseOrderIndicator;
350     }
351 
352     public boolean isReopenPurchaseOrderIndicator() {
353         return reopenPurchaseOrderIndicator;
354     }
355 
356     public void setReopenPurchaseOrderIndicator(boolean reopenPurchaseOrderIndicator) {
357         this.reopenPurchaseOrderIndicator = reopenPurchaseOrderIndicator;
358     }
359 
360     public String getRecurringPaymentTypeCode() {
361         return recurringPaymentTypeCode;
362     }
363 
364     public void setRecurringPaymentTypeCode(String recurringPaymentTypeCode) {
365         this.recurringPaymentTypeCode = recurringPaymentTypeCode;
366     }
367 
368     public RecurringPaymentType getRecurringPaymentType() {
369         if (ObjectUtils.isNull(recurringPaymentType)) {
370             refreshReferenceObject(PurapPropertyConstants.RECURRING_PAYMENT_TYPE);
371         }
372         return recurringPaymentType;
373     }
374 
375     public void setRecurringPaymentType(RecurringPaymentType recurringPaymentType) {
376         this.recurringPaymentType = recurringPaymentType;
377     }
378 
379     public void generateAccountListFromPoItemAccounts(List<PurApAccountingLine> accounts) {
380         for (PurApAccountingLine line : accounts) {
381             PurchaseOrderAccount poa = (PurchaseOrderAccount) line;
382             if (!line.isEmpty()) {
383                 getSourceAccountingLines().add(new InvoiceAccount(this, poa));
384             }
385         }
386     }
387 
388     /**
389      * @see org.kuali.ole.module.purap.businessobject.PurApItem#getAccountingLineClass()
390      */
391     @Override
392     public Class getAccountingLineClass() {
393         return InvoiceAccount.class;
394     }
395 
396     public boolean isDisplayOnPreq() {
397         PurchaseOrderItem poi = getPurchaseOrderItem();
398         if (ObjectUtils.isNull(poi)) {
399             LOG.debug("poi was null");
400             return false;
401         }
402 
403         // if the po item is not active... skip it
404         if (!poi.isItemActiveIndicator()) {
405             if (LOG.isDebugEnabled()) {
406                 LOG.debug("poi was not active: " + poi.toString());
407             }
408             return false;
409         }
410 
411         ItemType poiType = poi.getItemType();
412 
413         if (poiType.isQuantityBasedGeneralLedgerIndicator()) {
414             if (poi.getItemQuantity().isGreaterThan(poi.getItemInvoicedTotalQuantity())) {
415                 return true;
416             } else {
417                 if (ObjectUtils.isNotNull(this.getItemQuantity()) && this.getItemQuantity().isGreaterThan(KualiDecimal.ZERO)) {
418                     return true;
419                 }
420             }
421 
422             return false;
423         } else { // not quantity based
424             if (poi.getItemOutstandingEncumberedAmount().isGreaterThan(KualiDecimal.ZERO)) {
425                 return true;
426             } else {
427                 if (PurApItemUtils.isNonZeroExtended(this)) {
428                     return true;
429                 }
430                 return false;
431             }
432 
433         }
434     }
435 
436     /**
437      * sets account line percentage to zero.
438      *
439      * @see org.kuali.ole.module.purap.businessobject.PurApItem#resetAccount()
440      */
441     @Override
442     public void resetAccount() {
443         super.resetAccount();
444         this.getNewSourceLine().setAmount(null);
445         this.getNewSourceLine().setAccountLinePercent(null);
446     }
447 
448     /**
449      * Added for electronic invoice
450      */
451     public void addToUnitPrice(BigDecimal addThisValue) {
452         if (getItemUnitPrice() == null) {
453             setItemUnitPrice(BigDecimal.ZERO);
454         }
455         BigDecimal addedPrice = getItemUnitPrice().add(addThisValue);
456         setItemUnitPrice(addedPrice);
457     }
458 
459     public void addToExtendedPrice(KualiDecimal addThisValue) {
460         if (getExtendedPrice() == null) {
461             setExtendedPrice(KualiDecimal.ZERO);
462         }
463         KualiDecimal addedPrice = getExtendedPrice().add(addThisValue);
464         setExtendedPrice(addedPrice);
465     }
466 
467     @Override
468     public Class getUseTaxClass() {
469         return InvoiceItemUseTax.class;
470     }
471 
472     /**
473      * @see org.kuali.ole.module.purap.document.AccountsPayableDocument#getPurchaseOrderDocument()
474      */
475     public PurchaseOrderDocument getPurchaseOrderDocument() {
476         if ((ObjectUtils.isNull(purchaseOrderDocument) || ObjectUtils.isNull(purchaseOrderDocument.getPurapDocumentIdentifier())) && (ObjectUtils.isNotNull(getPurchaseOrderIdentifier()))) {
477             setPurchaseOrderDocument(SpringContext.getBean(PurchaseOrderService.class).getCurrentPurchaseOrder(this.getPurchaseOrderIdentifier()));
478         }
479         return purchaseOrderDocument;
480     }
481 
482     /**
483      * @see org.kuali.ole.module.purap.document.AccountsPayableDocument#setPurchaseOrderDocument(org.kuali.ole.module.purap.document.PurchaseOrderDocument)
484      */
485     public void setPurchaseOrderDocument(PurchaseOrderDocument purchaseOrderDocument) {
486         if (ObjectUtils.isNull(purchaseOrderDocument)) {
487             // KUALI-PURAP 1185 PO Id not being set to null, instead throwing error on main screen that value is invalid.
488             // setPurchaseOrderIdentifier(null);
489             this.purchaseOrderDocument = null;
490         } else {
491             if (ObjectUtils.isNotNull(purchaseOrderDocument.getPurapDocumentIdentifier())) {
492                 setPurchaseOrderIdentifier(purchaseOrderDocument.getPurapDocumentIdentifier());
493             }
494             this.purchaseOrderDocument = purchaseOrderDocument;
495         }
496     }
497 
498 
499 }