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.PaymentRequestDocument;
22  import org.kuali.ole.module.purap.document.PurchaseOrderDocument;
23  import org.kuali.ole.module.purap.document.VendorCreditMemoDocument;
24  import org.kuali.ole.module.purap.document.service.AccountsPayableService;
25  import org.kuali.ole.module.purap.document.service.PaymentRequestService;
26  import org.kuali.ole.module.purap.document.service.PurapService;
27  import org.kuali.ole.module.purap.document.service.PurchaseOrderService;
28  import org.kuali.ole.module.purap.exception.PurError;
29  import org.kuali.ole.module.purap.util.ExpiredOrClosedAccountEntry;
30  import org.kuali.ole.module.purap.util.PurApObjectUtils;
31  import org.kuali.ole.select.businessobject.OleInvoiceItem;
32  import org.kuali.ole.select.document.OleVendorCreditMemoDocument;
33  import org.kuali.ole.sys.context.SpringContext;
34  import org.kuali.rice.core.api.util.type.KualiDecimal;
35  import org.kuali.rice.krad.util.ObjectUtils;
36  
37  import java.math.BigDecimal;
38  import java.util.ArrayList;
39  import java.util.HashMap;
40  import java.util.Iterator;
41  import java.util.List;
42  
43  /**
44   * Item line Business Object for Credit Memo Document.
45   */
46  public class CreditMemoItem extends AccountsPayableItemBase {
47      private KualiDecimal poInvoicedTotalQuantity;
48      private BigDecimal poUnitPrice;
49      private KualiDecimal poTotalAmount;
50      private KualiDecimal preqInvoicedTotalQuantity;
51      private BigDecimal preqUnitPrice;
52      private KualiDecimal preqTotalAmount;
53  
54      /**
55       * Default constructor.
56       */
57      public CreditMemoItem() {
58      }
59  
60      /**
61       * Constructs a CreditMemoItem object from an existing Purchase Order Item. - Delegate
62       *
63       * @param cmDocument the Credit Memo Document this item belongs to.
64       * @param poItem     the Purchase Order Item to copy from.
65       */
66      public CreditMemoItem(VendorCreditMemoDocument cmDocument, PurchaseOrderItem poItem) {
67          this(cmDocument, poItem, new HashMap<String, ExpiredOrClosedAccountEntry>());
68      }
69  
70      /**
71       * Constructs a CreditMemoItem object from an existing Purchase Order Item, and check and process expired or closed accounts
72       * item might contain.
73       *
74       * @param cmDocument                 the Credit Memo Document this item belongs to.
75       * @param poItem                     the Purchase Order Item to copy from.
76       * @param expiredOrClosedAccountList the list of expired or closed accounts to check against.
77       */
78      public CreditMemoItem(VendorCreditMemoDocument cmDocument, PurchaseOrderItem poItem, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
79          super();
80  
81          setPurapDocumentIdentifier(cmDocument.getPurapDocumentIdentifier());
82          setPurapDocument(cmDocument);
83          setItemLineNumber(poItem.getItemLineNumber());
84          setPoInvoicedTotalQuantity(poItem.getItemInvoicedTotalQuantity());
85          setPoUnitPrice(poItem.getItemUnitPrice());
86          setPoTotalAmount(poItem.getItemInvoicedTotalAmount());
87          setItemTypeCode(poItem.getItemTypeCode());
88  
89          //recalculate tax
90          SpringContext.getBean(PurapService.class).calculateTax(cmDocument);
91  
92          if ((ObjectUtils.isNotNull(this.getItemType()) && this.getItemType().isAmountBasedGeneralLedgerIndicator())) {
93              // setting unit price to be null to be more consistent with other below the line
94              this.setItemUnitPrice(null);
95          } else {
96              setItemUnitPrice(poItem.getItemUnitPrice());
97          }
98  
99          setItemCatalogNumber(poItem.getItemCatalogNumber());
100 
101         setItemDescription(poItem.getItemDescription());
102 
103         if (getPoInvoicedTotalQuantity() == null) {
104             setPoInvoicedTotalQuantity(KualiDecimal.ZERO);
105         }
106         if (getPoUnitPrice() == null) {
107             setPoUnitPrice(BigDecimal.ZERO);
108         }
109         if (getPoTotalAmount() == null) {
110             setPoTotalAmount(KualiDecimal.ZERO);
111         }
112 
113         for (Iterator iter = poItem.getSourceAccountingLines().iterator(); iter.hasNext(); ) {
114             PurchaseOrderAccount account = (PurchaseOrderAccount) iter.next();
115 
116             // check if this account is expired/closed and replace as needed
117             SpringContext.getBean(AccountsPayableService.class).processExpiredOrClosedAccount(account, expiredOrClosedAccountList);
118 
119             getSourceAccountingLines().add(new CreditMemoAccount(account));
120         }
121     }
122 
123     /**
124      * Constructs a CreditMemoItem object from an existing Payment Request Item, and check and process expired or closed accounts
125      * item might contain.
126      *
127      * @param cmDocument                 the Credit Memo Document this item belongs to.
128      * @param preqItem                   the Payment Request Item to copy from.
129      * @param poItem                     the Purchase Order Item to copy from.
130      * @param expiredOrClosedAccountList the list of expired or closed accounts to check against.
131      */
132     public CreditMemoItem(VendorCreditMemoDocument cmDocument, PaymentRequestItem preqItem, PurchaseOrderItem poItem, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
133         super();
134 
135         setPurapDocumentIdentifier(cmDocument.getPurapDocumentIdentifier());
136         setItemLineNumber(preqItem.getItemLineNumber());
137         this.setPurapDocument(cmDocument);
138 
139         // take invoiced quantities from the lower of the preq and po if different
140         if (poItem.getItemInvoicedTotalQuantity() != null && preqItem.getItemQuantity() != null && poItem.getItemInvoicedTotalQuantity().isLessThan(preqItem.getItemQuantity())) {
141             setPreqInvoicedTotalQuantity(poItem.getItemInvoicedTotalQuantity());
142             setPreqTotalAmount(poItem.getItemInvoicedTotalAmount());
143         } else {
144             setPreqInvoicedTotalQuantity(preqItem.getItemQuantity());
145             setPreqTotalAmount(preqItem.getTotalAmount());
146         }
147 
148         setPreqUnitPrice(preqItem.getItemUnitPrice());
149         setItemTypeCode(preqItem.getItemTypeCode());
150 
151         if ((ObjectUtils.isNotNull(this.getItemType()) && this.getItemType().isAmountBasedGeneralLedgerIndicator())) {
152             // setting unit price to be null to be more consistent with other below the line
153             this.setItemUnitPrice(null);
154         } else {
155             setItemUnitPrice(preqItem.getItemUnitPrice());
156         }
157 
158         setItemCatalogNumber(preqItem.getItemCatalogNumber());
159         setItemDescription(preqItem.getItemDescription());
160 
161         setCapitalAssetTransactionTypeCode(preqItem.getCapitalAssetTransactionTypeCode());
162 
163         if (getPreqInvoicedTotalQuantity() == null) {
164             setPreqInvoicedTotalQuantity(KualiDecimal.ZERO);
165         }
166         if (getPreqUnitPrice() == null) {
167             setPreqUnitPrice(BigDecimal.ZERO);
168         }
169         if (getPreqTotalAmount() == null) {
170             setPreqTotalAmount(KualiDecimal.ZERO);
171         }
172 
173         for (Iterator iter = preqItem.getSourceAccountingLines().iterator(); iter.hasNext(); ) {
174             PaymentRequestAccount account = (PaymentRequestAccount) iter.next();
175 
176             // check if this account is expired/closed and replace as needed
177             SpringContext.getBean(AccountsPayableService.class).processExpiredOrClosedAccount(account, expiredOrClosedAccountList);
178 
179             getSourceAccountingLines().add(new CreditMemoAccount(account));
180         }
181     }
182 
183     /**
184      * @see org.kuali.ole.module.purap.businessobject.PurApItemBase#getAccountingLineClass()
185      */
186     @Override
187     public Class<CreditMemoAccount> getAccountingLineClass() {
188         return CreditMemoAccount.class;
189     }
190 
191     public KualiDecimal getPoTotalAmount() {
192         return poTotalAmount;
193     }
194 
195     public void setPoTotalAmount(KualiDecimal poTotalAmount) {
196         this.poTotalAmount = poTotalAmount;
197     }
198 
199     public KualiDecimal getPoInvoicedTotalQuantity() {
200         return poInvoicedTotalQuantity;
201     }
202 
203     public void setPoInvoicedTotalQuantity(KualiDecimal poInvoicedTotalQuantity) {
204         this.poInvoicedTotalQuantity = poInvoicedTotalQuantity;
205     }
206 
207     public BigDecimal getPoUnitPrice() {
208         return poUnitPrice;
209     }
210 
211     public void setPoUnitPrice(BigDecimal poUnitPrice) {
212         this.poUnitPrice = poUnitPrice;
213     }
214 
215     public KualiDecimal getPreqTotalAmount() {
216         return preqTotalAmount;
217     }
218 
219     public void setPreqTotalAmount(KualiDecimal preqTotalAmount) {
220         this.preqTotalAmount = preqTotalAmount;
221     }
222 
223     public KualiDecimal getPreqInvoicedTotalQuantity() {
224         return preqInvoicedTotalQuantity;
225     }
226 
227     public void setPreqInvoicedTotalQuantity(KualiDecimal preqInvoicedTotalQuantity) {
228         this.preqInvoicedTotalQuantity = preqInvoicedTotalQuantity;
229     }
230 
231     public BigDecimal getPreqUnitPrice() {
232         return preqUnitPrice;
233     }
234 
235     public void setPreqUnitPrice(BigDecimal preqUnitPrice) {
236         this.preqUnitPrice = preqUnitPrice;
237     }
238 
239     @Override
240     public Class getUseTaxClass() {
241         return CreditMemoItemUseTax.class;
242     }
243 
244     public PurchaseOrderItem getPurchaseOrderItem() {
245 
246         PurchaseOrderItem poi = null;
247         //refresh vendor document
248         if (ObjectUtils.isNotNull(this.getPurapDocumentIdentifier())) {
249             if (ObjectUtils.isNull(this.getVendorCreditMemo())) {
250                 this.refreshReferenceObject(PurapPropertyConstants.PURAP_DOC);
251             }
252         }
253 
254         //if vendor document not null, then attempt to pull PO off of it
255         if (ObjectUtils.isNotNull(getVendorCreditMemo())) {
256             PurchaseOrderDocument purchaseOrderDocument = null;
257             Integer purchaseOrderDocumentId = getVendorCreditMemo().getPurchaseOrderIdentifier();
258 
259             if (getVendorCreditMemo().isSourceDocumentPaymentRequest() && ObjectUtils.isNull(purchaseOrderDocumentId)) {
260                 PaymentRequestDocument paymentRequestDocument = SpringContext.getBean(PaymentRequestService.class).getPaymentRequestById(getVendorCreditMemo().getPaymentRequestIdentifier());
261                 purchaseOrderDocumentId = paymentRequestDocument.getPurchaseOrderIdentifier();
262             }
263 
264             // if we found a valid po id number then check it for reopening
265             if (ObjectUtils.isNotNull(purchaseOrderDocumentId)) {
266                 purchaseOrderDocument = SpringContext.getBean(PurchaseOrderService.class).getCurrentPurchaseOrder(purchaseOrderDocumentId);
267             }
268 
269             //if we have a PO document, get po item
270             if (ObjectUtils.isNotNull(purchaseOrderDocument)) {
271                 if (this.getItemType().isLineItemIndicator()) {
272                     List<PurchaseOrderItem> items = purchaseOrderDocument.getItems();
273                     poi = items.get(this.getItemLineNumber().intValue() - 1);
274 
275                 } else {
276                     poi = (PurchaseOrderItem) SpringContext.getBean(PurapService.class).getBelowTheLineByType(purchaseOrderDocument, this.getItemType());
277                 }
278             }
279         } else {
280             throw new PurError("Credit Memo Object in Purchase Order item line number " + getItemLineNumber() + "or itemType " + getItemTypeCode() + " is null");
281         }
282 
283         return poi;
284     }
285 
286     public VendorCreditMemoDocument getVendorCreditMemo() {
287         return super.getPurapDocument();
288     }
289 
290     /**
291      * Constructs a new payment request item, but also merges expired accounts.
292      *
293      * @param poi                        - Ole invoice item
294      * @param vendorCreditMemoDoc        - vendor credit memo document
295      * @param expiredOrClosedAccountList - list of expired or closed accounts to merge
296      */
297     public CreditMemoItem(OleInvoiceItem poi, OleVendorCreditMemoDocument vendorCreditMemoDoc, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
298 
299         // copy base attributes w/ extra array of fields not to be copied
300         PurApObjectUtils.populateFromBaseClass(PurApItemBase.class, poi, this, PurapConstants.PREQ_ITEM_UNCOPYABLE_FIELDS);
301 
302         setItemDescription(poi.getItemDescription());
303 
304         //New Source Line should be set for PaymentRequestItem
305         resetAccount();
306 
307         // set up accounts
308         List accounts = new ArrayList();
309         for (PurApAccountingLine account : poi.getSourceAccountingLines()) {
310             InvoiceAccount invoiceAccount = (InvoiceAccount) account;
311             KualiDecimal amount = invoiceAccount.getAmount();
312             invoiceAccount.setAmount(invoiceAccount.getAmount().abs());
313             // check if this account is expired/closed and replace as needed
314             SpringContext.getBean(AccountsPayableService.class).processExpiredOrClosedAccount(invoiceAccount, expiredOrClosedAccountList);
315             if (invoiceAccount.getAmount().isZero()) {
316                 if (SpringContext.getBean(AccountsPayableService.class).canCopyAccountingLinesWithZeroAmount()) {
317                     accounts.add(new CreditMemoAccount(this, invoiceAccount));
318                 }
319             } else {
320                 accounts.add(new CreditMemoAccount(this, invoiceAccount));
321             }
322             invoiceAccount.setAmount(amount);
323         }
324         this.poInvoicedTotalQuantity = poi.getPoOutstandingQuantity();
325         if (poi.getPurchaseOrderItemUnitPrice() != null) {
326             this.poUnitPrice = poi.getPurchaseOrderItemUnitPrice().abs();
327         }
328         this.setSourceAccountingLines(accounts);
329         this.getUseTaxItems().clear();
330         //List<PurApItemUseTax> newUseTaxItems = new ArrayList<PurApItemUseTax>();
331         /// this.setUseTaxItems(newUseTaxItems);
332         //copy use tax items over, and blank out keys (useTaxId and itemIdentifier)
333         /*
334         this.getUseTaxItems().clear();
335         for (PurApItemUseTax useTaxItem : poi.getUseTaxItems()) {
336             PaymentRequestItemUseTax newItemUseTax = new PaymentRequestItemUseTax(useTaxItem);
337             this.getUseTaxItems().add(newItemUseTax);
338 
339         }
340         */
341 
342         // clear amount and desc on below the line - we probably don't need that null
343         // itemType check but it's there just in case remove if it causes problems
344         // also do this if of type service
345         if ((ObjectUtils.isNotNull(this.getItemType()) && this.getItemType().isAmountBasedGeneralLedgerIndicator())) {
346             // setting unit price to be null to be more consistent with other below the line
347             this.setItemUnitPrice(null);
348         }
349 
350         // copy custom
351 
352 
353         // set doc fields
354         // this.setPurapDocumentIdentifier(preq.getPurapDocumentIdentifier());
355         // this.setPurapDocument(preq);
356     }
357 }