001    /*
002     * Copyright 2011 The Kuali Foundation.
003     * 
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     * http://www.opensource.org/licenses/ecl2.php
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.kuali.kfs.module.purap.businessobject;
018    
019    import java.math.BigDecimal;
020    import java.util.HashMap;
021    import java.util.Iterator;
022    
023    import org.kuali.kfs.module.purap.PurapPropertyConstants;
024    import org.kuali.kfs.module.purap.document.PaymentRequestDocument;
025    import org.kuali.kfs.module.purap.document.PurchaseOrderDocument;
026    import org.kuali.kfs.module.purap.document.VendorCreditMemoDocument;
027    import org.kuali.kfs.module.purap.document.service.AccountsPayableService;
028    import org.kuali.kfs.module.purap.document.service.PaymentRequestService;
029    import org.kuali.kfs.module.purap.document.service.PurapService;
030    import org.kuali.kfs.module.purap.document.service.PurchaseOrderService;
031    import org.kuali.kfs.module.purap.exception.PurError;
032    import org.kuali.kfs.module.purap.util.ExpiredOrClosedAccountEntry;
033    import org.kuali.kfs.sys.context.SpringContext;
034    import org.kuali.rice.kns.util.KualiDecimal;
035    import org.kuali.rice.kns.util.ObjectUtils;
036    
037    /**
038     * Item line Business Object for Credit Memo Document.
039     */
040    public class CreditMemoItem extends AccountsPayableItemBase {
041        private KualiDecimal poInvoicedTotalQuantity;
042        private BigDecimal poUnitPrice;
043        private KualiDecimal poTotalAmount;
044        private KualiDecimal preqInvoicedTotalQuantity;
045        private BigDecimal preqUnitPrice;
046        private KualiDecimal preqTotalAmount;
047    
048        /**
049         * Default constructor.
050         */
051        public CreditMemoItem() {
052        }
053    
054        /**
055         * Constructs a CreditMemoItem object from an existing Purchase Order Item. - Delegate
056         * 
057         * @param cmDocument the Credit Memo Document this item belongs to.
058         * @param poItem the Purchase Order Item to copy from.
059         */
060        public CreditMemoItem(VendorCreditMemoDocument cmDocument, PurchaseOrderItem poItem) {
061            this(cmDocument, poItem, new HashMap<String, ExpiredOrClosedAccountEntry>());
062        }
063    
064        /**
065         * Constructs a CreditMemoItem object from an existing Purchase Order Item, and check and process expired or closed accounts
066         * item might contain.
067         * 
068         * @param cmDocument the Credit Memo Document this item belongs to.
069         * @param poItem the Purchase Order Item to copy from.
070         * @param expiredOrClosedAccountList the list of expired or closed accounts to check against.
071         */
072        public CreditMemoItem(VendorCreditMemoDocument cmDocument, PurchaseOrderItem poItem, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
073            super();
074    
075            setPurapDocumentIdentifier(cmDocument.getPurapDocumentIdentifier());
076            setPurapDocument(cmDocument);
077            setItemLineNumber(poItem.getItemLineNumber());
078            setPoInvoicedTotalQuantity(poItem.getItemInvoicedTotalQuantity());
079            setPoUnitPrice(poItem.getItemUnitPrice());
080            setPoTotalAmount(poItem.getItemInvoicedTotalAmount());
081            setItemTypeCode(poItem.getItemTypeCode());
082            
083            //recalculate tax
084            SpringContext.getBean(PurapService.class).calculateTax(cmDocument);
085            
086            if ((ObjectUtils.isNotNull(this.getItemType()) && this.getItemType().isAmountBasedGeneralLedgerIndicator())) {
087                // setting unit price to be null to be more consistent with other below the line
088                this.setItemUnitPrice(null);
089            }
090            else {
091                setItemUnitPrice(poItem.getItemUnitPrice());
092            }
093    
094            setItemCatalogNumber(poItem.getItemCatalogNumber());
095            
096            setItemDescription(poItem.getItemDescription());
097                     
098            if (getPoInvoicedTotalQuantity() == null) {
099                setPoInvoicedTotalQuantity(KualiDecimal.ZERO);
100            }
101            if (getPoUnitPrice() == null) {
102                setPoUnitPrice(BigDecimal.ZERO);
103            }
104            if (getPoTotalAmount() == null) {
105                setPoTotalAmount(KualiDecimal.ZERO);
106            }
107            
108            for (Iterator iter = poItem.getSourceAccountingLines().iterator(); iter.hasNext();) {
109                PurchaseOrderAccount account = (PurchaseOrderAccount) iter.next();
110    
111                // check if this account is expired/closed and replace as needed
112                SpringContext.getBean(AccountsPayableService.class).processExpiredOrClosedAccount(account, expiredOrClosedAccountList);
113    
114                getSourceAccountingLines().add(new CreditMemoAccount(account));
115            }
116        }
117    
118        /**
119         * Constructs a CreditMemoItem object from an existing Payment Request Item, and check and process expired or closed accounts
120         * item might contain.
121         * 
122         * @param cmDocument the Credit Memo Document this item belongs to.
123         * @param preqItem the Payment Request Item to copy from.
124         * @param poItem the Purchase Order Item to copy from.
125         * @param expiredOrClosedAccountList the list of expired or closed accounts to check against.
126         */
127        public CreditMemoItem(VendorCreditMemoDocument cmDocument, PaymentRequestItem preqItem, PurchaseOrderItem poItem, HashMap<String, ExpiredOrClosedAccountEntry> expiredOrClosedAccountList) {
128            super();
129    
130            setPurapDocumentIdentifier(cmDocument.getPurapDocumentIdentifier());
131            setItemLineNumber(preqItem.getItemLineNumber());
132            this.setPurapDocument(cmDocument);
133            
134            // take invoiced quantities from the lower of the preq and po if different
135            if (poItem.getItemInvoicedTotalQuantity() != null && preqItem.getItemQuantity() != null && poItem.getItemInvoicedTotalQuantity().isLessThan(preqItem.getItemQuantity())) {
136                setPreqInvoicedTotalQuantity(poItem.getItemInvoicedTotalQuantity());
137                setPreqTotalAmount(poItem.getItemInvoicedTotalAmount());
138            }
139            else {
140                setPreqInvoicedTotalQuantity(preqItem.getItemQuantity());
141                setPreqTotalAmount(preqItem.getTotalAmount());
142            }
143    
144            setPreqUnitPrice(preqItem.getItemUnitPrice());
145            setItemTypeCode(preqItem.getItemTypeCode());
146    
147            if ((ObjectUtils.isNotNull(this.getItemType()) && this.getItemType().isAmountBasedGeneralLedgerIndicator())) {
148                // setting unit price to be null to be more consistent with other below the line
149                this.setItemUnitPrice(null);
150            }
151            else {
152                setItemUnitPrice(preqItem.getItemUnitPrice());
153            }
154    
155            setItemCatalogNumber(preqItem.getItemCatalogNumber());
156            setItemDescription(preqItem.getItemDescription());
157            
158            setCapitalAssetTransactionTypeCode(preqItem.getCapitalAssetTransactionTypeCode());
159    
160            if (getPreqInvoicedTotalQuantity() == null) {
161                setPreqInvoicedTotalQuantity(KualiDecimal.ZERO);
162            }
163            if (getPreqUnitPrice() == null) {
164                setPreqUnitPrice(BigDecimal.ZERO);
165            }
166            if (getPreqTotalAmount() == null) {
167                setPreqTotalAmount(KualiDecimal.ZERO);
168            }
169    
170            for (Iterator iter = preqItem.getSourceAccountingLines().iterator(); iter.hasNext();) {
171                PaymentRequestAccount account = (PaymentRequestAccount) iter.next();
172    
173                // check if this account is expired/closed and replace as needed
174                SpringContext.getBean(AccountsPayableService.class).processExpiredOrClosedAccount(account, expiredOrClosedAccountList);
175    
176                getSourceAccountingLines().add(new CreditMemoAccount(account));
177            }
178        }
179    
180        /**
181         * @see org.kuali.kfs.module.purap.businessobject.PurApItemBase#getAccountingLineClass()
182         */
183        @Override
184        public Class<CreditMemoAccount> getAccountingLineClass() {
185            return CreditMemoAccount.class;
186        }
187       
188        public KualiDecimal getPoTotalAmount() {
189            return poTotalAmount;
190        }
191    
192        public void setPoTotalAmount(KualiDecimal poTotalAmount) {
193            this.poTotalAmount = poTotalAmount;
194        }
195    
196        public KualiDecimal getPoInvoicedTotalQuantity() {
197            return poInvoicedTotalQuantity;
198        }
199    
200        public void setPoInvoicedTotalQuantity(KualiDecimal poInvoicedTotalQuantity) {
201            this.poInvoicedTotalQuantity = poInvoicedTotalQuantity;
202        }
203    
204        public BigDecimal getPoUnitPrice() {
205            return poUnitPrice;
206        }
207    
208        public void setPoUnitPrice(BigDecimal poUnitPrice) {
209            this.poUnitPrice = poUnitPrice;
210        }
211    
212        public KualiDecimal getPreqTotalAmount() {
213            return preqTotalAmount;
214        }
215    
216        public void setPreqTotalAmount(KualiDecimal preqTotalAmount) {
217            this.preqTotalAmount = preqTotalAmount;
218        }
219    
220        public KualiDecimal getPreqInvoicedTotalQuantity() {
221            return preqInvoicedTotalQuantity;
222        }
223    
224        public void setPreqInvoicedTotalQuantity(KualiDecimal preqInvoicedTotalQuantity) {
225            this.preqInvoicedTotalQuantity = preqInvoicedTotalQuantity;
226        }
227    
228        public BigDecimal getPreqUnitPrice() {
229            return preqUnitPrice;
230        }
231    
232        public void setPreqUnitPrice(BigDecimal preqUnitPrice) {
233            this.preqUnitPrice = preqUnitPrice;
234        }
235    
236        @Override
237        public Class getUseTaxClass() {
238            return CreditMemoItemUseTax.class;
239        }
240        
241        public PurchaseOrderItem getPurchaseOrderItem(){
242            
243            PurchaseOrderItem poi = null;
244            //refresh vendor document
245            if (ObjectUtils.isNotNull(this.getPurapDocumentIdentifier())) {
246                if (ObjectUtils.isNull(this.getVendorCreditMemo())) {
247                    this.refreshReferenceObject(PurapPropertyConstants.PURAP_DOC);
248                }
249            }
250    
251            //if vendor document not null, then attempt to pull PO off of it
252            if (ObjectUtils.isNotNull(getVendorCreditMemo())) {
253                PurchaseOrderDocument purchaseOrderDocument = null;            
254                Integer purchaseOrderDocumentId = getVendorCreditMemo().getPurchaseOrderIdentifier();
255                
256                if (getVendorCreditMemo().isSourceDocumentPaymentRequest() && ObjectUtils.isNull(purchaseOrderDocumentId)) {
257                    PaymentRequestDocument paymentRequestDocument = SpringContext.getBean(PaymentRequestService.class).getPaymentRequestById(getVendorCreditMemo().getPaymentRequestIdentifier());
258                    purchaseOrderDocumentId = paymentRequestDocument.getPurchaseOrderIdentifier();
259                }
260                
261                // if we found a valid po id number then check it for reopening
262                if (ObjectUtils.isNotNull(purchaseOrderDocumentId)) {
263                    purchaseOrderDocument = SpringContext.getBean(PurchaseOrderService.class).getCurrentPurchaseOrder(purchaseOrderDocumentId);
264                }
265                
266                //if we have a PO document, get po item
267                if(ObjectUtils.isNotNull(purchaseOrderDocument)){                
268                    if (this.getItemType().isLineItemIndicator()) {
269                        poi = (PurchaseOrderItem) purchaseOrderDocument.getItem(this.getItemLineNumber().intValue() - 1);
270                    }
271                    else {
272                        poi = (PurchaseOrderItem) SpringContext.getBean(PurapService.class).getBelowTheLineByType(purchaseOrderDocument, this.getItemType());
273                    }
274                }
275            }
276            else {            
277                throw new PurError("Credit Memo Object in Purchase Order item line number " + getItemLineNumber() + "or itemType " + getItemTypeCode() + " is null");
278            }
279            
280            return poi;
281        }
282        
283        public VendorCreditMemoDocument getVendorCreditMemo() {
284            return super.getPurapDocument();
285        }
286    
287    }