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 static org.kuali.rice.kns.util.KualiDecimal.ZERO;
020    
021    import java.math.BigDecimal;
022    import java.util.ArrayList;
023    import java.util.LinkedHashMap;
024    import java.util.List;
025    
026    import org.apache.commons.lang.StringUtils;
027    import org.kuali.kfs.module.purap.PurapConstants;
028    import org.kuali.kfs.module.purap.PurapPropertyConstants;
029    import org.kuali.kfs.module.purap.document.PurchaseOrderDocument;
030    import org.kuali.kfs.module.purap.document.service.PurchaseOrderService;
031    import org.kuali.kfs.sys.context.SpringContext;
032    import org.kuali.rice.kns.service.SequenceAccessorService;
033    import org.kuali.rice.kns.util.KualiDecimal;
034    import org.kuali.rice.kns.util.ObjectUtils;
035    
036    /**
037     * Purchase Order Item Business Object.
038     */
039    public class PurchaseOrderItem extends PurchasingItemBase {
040        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PurchaseOrderItem.class);
041    
042        private String documentNumber;
043        private KualiDecimal itemInvoicedTotalQuantity;
044        private KualiDecimal itemInvoicedTotalAmount;
045        private KualiDecimal itemReceivedTotalQuantity;
046        private KualiDecimal itemOutstandingEncumberedQuantity;
047        private KualiDecimal itemOutstandingEncumberedAmount;
048        private boolean itemActiveIndicator = true;
049        private KualiDecimal itemDamagedTotalQuantity;
050            
051        private PurchaseOrderDocument purchaseOrder;
052        
053        // Not persisted to DB
054        private boolean itemSelectedForRetransmitIndicator;
055        private boolean movingToSplit;
056    
057        /**
058         * Default constructor.
059         */
060        public PurchaseOrderItem() {
061    
062        }
063    
064        /**
065         * Constructor.
066         * 
067         * @param ri - Requisition Item
068         * @param po - Purchase Order Document
069         */
070        public PurchaseOrderItem(RequisitionItem ri, PurchaseOrderDocument po, RequisitionCapitalAssetItem reqCamsItem) {
071            super();
072    
073            this.setPurchaseOrder(po);
074            SequenceAccessorService sas = SpringContext.getBean(SequenceAccessorService.class);
075            Integer itemIdentifier = sas.getNextAvailableSequenceNumber("PO_ITM_ID", PurchaseOrderDocument.class).intValue();        
076            this.setItemIdentifier(itemIdentifier);        
077            this.setItemLineNumber(ri.getItemLineNumber());
078            this.setItemUnitOfMeasureCode(ri.getItemUnitOfMeasureCode());
079            this.setItemQuantity(ri.getItemQuantity());
080            this.setItemCatalogNumber(ri.getItemCatalogNumber());
081            this.setItemDescription(ri.getItemDescription());
082            this.setItemUnitPrice(ri.getItemUnitPrice());
083            this.setItemAuxiliaryPartIdentifier(ri.getItemAuxiliaryPartIdentifier());
084            this.setItemAssignedToTradeInIndicator(ri.getItemAssignedToTradeInIndicator());        
085            this.setItemTaxAmount( ri.getItemTaxAmount() );
086            
087            //copy use tax items over, and blank out keys (useTaxId and itemIdentifier)
088            for (PurApItemUseTax useTaxItem : ri.getUseTaxItems()) {
089                PurchaseOrderItemUseTax newItemUseTax = new PurchaseOrderItemUseTax(useTaxItem);
090                newItemUseTax.setItemIdentifier(itemIdentifier);
091                this.getUseTaxItems().add(newItemUseTax);
092    
093            }
094            
095            this.setExternalOrganizationB2bProductReferenceNumber(ri.getExternalOrganizationB2bProductReferenceNumber());
096            this.setExternalOrganizationB2bProductTypeName(ri.getExternalOrganizationB2bProductTypeName());
097    
098            this.setItemReceivedTotalQuantity(ZERO);
099            this.setItemDamagedTotalQuantity(ZERO);
100            
101            this.setItemTypeCode(ri.getItemTypeCode());
102    
103            if (ri.getSourceAccountingLines() != null && ri.getSourceAccountingLines().size() > 0 && 
104                    !StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_ORDER_DISCOUNT_CODE,ri.getItemType().getItemTypeCode())) {
105                List accounts = new ArrayList();
106                for (PurApAccountingLine account : ri.getSourceAccountingLines()) {
107                    PurchaseOrderAccount poAccount = new PurchaseOrderAccount(account);
108                    poAccount.setPurchaseOrderItem(this);
109                    accounts.add(poAccount);
110                }
111                this.setSourceAccountingLines(accounts);
112            }
113            // By default, set the item active indicator to true.
114            // In amendment, the user can set it to false when they click on
115            // the inactivate button.
116            this.setItemActiveIndicator(true);
117            
118            this.setPurchasingCommodityCode(ri.getPurchasingCommodityCode());
119            this.setCommodityCode(getCommodityCode());
120            
121            // If the RequisitionItem has a CapitalAssetItem, create a new PurchasingCapitalAssetItem and add it to the PO.
122            if( ObjectUtils.isNotNull(reqCamsItem) ) {
123                PurchaseOrderCapitalAssetItem newPOCapitalAssetItem = new PurchaseOrderCapitalAssetItem(reqCamsItem, itemIdentifier);
124                po.getPurchasingCapitalAssetItems().add(newPOCapitalAssetItem);
125            }
126        }
127        
128        public boolean isItemActiveIndicator() {
129            return itemActiveIndicator;
130        }
131        
132    //    public String getItemActiveIndicator() {
133    //        return (new Boolean(itemActiveIndicator)).toString();
134    //    }
135    
136        public void setItemActiveIndicator(boolean itemActiveIndicator) {
137            this.itemActiveIndicator = itemActiveIndicator;
138        }
139    
140        public KualiDecimal getItemInvoicedTotalAmount() {
141            return itemInvoicedTotalAmount;
142        }
143    
144        public void setItemInvoicedTotalAmount(KualiDecimal itemInvoicedTotalAmount) {
145            this.itemInvoicedTotalAmount = itemInvoicedTotalAmount;
146        }
147    
148        public KualiDecimal getItemInvoicedTotalQuantity() {
149            return itemInvoicedTotalQuantity;
150        }
151    
152        public void setItemInvoicedTotalQuantity(KualiDecimal itemInvoicedTotalQuantity) {
153            this.itemInvoicedTotalQuantity = itemInvoicedTotalQuantity;
154        }
155    
156        public KualiDecimal getItemOutstandingEncumberedQuantity() {
157            return itemOutstandingEncumberedQuantity;
158        }
159    
160        public void setItemOutstandingEncumberedQuantity(KualiDecimal itemOutstandingEncumberedQuantity) {
161            this.itemOutstandingEncumberedQuantity = itemOutstandingEncumberedQuantity;
162        }
163    
164        public KualiDecimal getItemOutstandingEncumberedAmount() {
165            return itemOutstandingEncumberedAmount;
166        }
167    
168        public void setItemOutstandingEncumberedAmount(KualiDecimal itemOutstandingEncumbranceAmount) {
169            this.itemOutstandingEncumberedAmount = itemOutstandingEncumbranceAmount;
170        }
171    
172        public KualiDecimal getItemReceivedTotalQuantity() {
173            return itemReceivedTotalQuantity;
174        }
175    
176        public void setItemReceivedTotalQuantity(KualiDecimal itemReceivedTotalQuantity) {
177            this.itemReceivedTotalQuantity = itemReceivedTotalQuantity;
178        }
179    
180        /**
181         * Gets the itemDamagedTotalQuantity attribute. 
182         * @return Returns the itemDamagedTotalQuantity.
183         */
184        public KualiDecimal getItemDamagedTotalQuantity() {
185            return itemDamagedTotalQuantity;
186        }
187    
188        /**
189         * Sets the itemDamagedTotalQuantity attribute value.
190         * @param itemDamagedTotalQuantity The itemDamagedTotalQuantity to set.
191         */
192        public void setItemDamagedTotalQuantity(KualiDecimal itemDamagedTotalQuantity) {
193            this.itemDamagedTotalQuantity = itemDamagedTotalQuantity;
194        }
195    
196        public PurchaseOrderDocument getPurchaseOrder() {
197            if (ObjectUtils.isNull(purchaseOrder)) {
198                refreshReferenceObject(PurapPropertyConstants.PURAP_DOC);
199            }
200            return super.getPurapDocument();
201        }
202    
203        public void setPurchaseOrder(PurchaseOrderDocument purchaseOrder) {
204            setPurapDocument(purchaseOrder);
205        }
206    
207        public String getDocumentNumber() {
208            return documentNumber;
209        }
210    
211        public void setDocumentNumber(String documentNumber) {
212            this.documentNumber = documentNumber;
213        }
214    
215        public boolean isItemSelectedForRetransmitIndicator() {
216            return itemSelectedForRetransmitIndicator;
217        }
218    
219        public void setItemSelectedForRetransmitIndicator(boolean itemSelectedForRetransmitIndicator) {
220            this.itemSelectedForRetransmitIndicator = itemSelectedForRetransmitIndicator;
221        }    
222    
223        public boolean isMovingToSplit() {
224            return movingToSplit;
225        }
226    
227        public void setMovingToSplit(boolean movingToSplit) {
228            this.movingToSplit = movingToSplit;
229        }
230    
231        /**
232         * @see org.kuali.rice.kns.bo.BusinessObjectBase#toStringMapper()
233         */
234        @Override
235        protected LinkedHashMap toStringMapper() {
236            LinkedHashMap m = new LinkedHashMap();
237            m.put("documentNumber", this.documentNumber);
238            if (this.getItemIdentifier() != null) {
239                m.put("itemIdentifier", this.getItemIdentifier().toString());
240            }
241            return m;
242        }
243    
244        /**
245         * @see org.kuali.kfs.module.purap.businessobject.PurApItem#getAccountingLineClass()
246         */
247        public Class getAccountingLineClass() {
248            return PurchaseOrderAccount.class;
249        }
250        
251        /**
252         * 
253         * This method returns the total item paid amount
254         * @return
255         */
256        public KualiDecimal getItemPaidAmount() {
257            if (!(this.isItemActiveIndicator())) {
258                return KualiDecimal.ZERO;
259            }
260            return this.getItemInvoicedTotalAmount();
261        }
262    
263        public KualiDecimal getItemEncumbranceRelievedAmount() {
264            // check that it is active else return zero
265            if (this == null || !this.isItemActiveIndicator()) {
266                return KualiDecimal.ZERO;
267            }
268            // setup outstanding amount and get totalEncumberance from this.getExtendedCost()
269            KualiDecimal outstandingAmount = KualiDecimal.ZERO;
270            KualiDecimal totalEncumberance = this.getTotalAmount();
271    
272            ItemType iT = this.getItemType();
273            // if service add the po outstanding amount to outstanding amount
274            if (iT.isAmountBasedGeneralLedgerIndicator()) {
275                outstandingAmount = outstandingAmount.add(this.getItemOutstandingEncumberedAmount());
276            }
277            else {
278                // else add outstanding quantity * unit price
279                BigDecimal qty = new BigDecimal(this.getOutstandingQuantity().toString());
280                outstandingAmount = outstandingAmount.add(new KualiDecimal(this.getItemUnitPrice().multiply(qty).setScale(KualiDecimal.SCALE, KualiDecimal.ROUND_BEHAVIOR)));
281                
282                KualiDecimal itemTaxAmount = this.getItemTaxAmount() == null ? ZERO : this.getItemTaxAmount();
283                KualiDecimal outstandingTaxAmount = new KualiDecimal(qty).divide(this.getItemQuantity()).multiply(itemTaxAmount);
284                outstandingAmount = outstandingAmount.add(outstandingTaxAmount);
285            }
286    
287            // return the total encumbrance subtracted by the outstanding amount from above
288            return totalEncumberance.subtract(outstandingAmount);
289        }
290        
291        /**
292         * Exists due to a setter requirement by the htmlControlAttribute
293         * @deprecated
294         * @param amount - outstanding quantity
295         */
296        public void setOutstandingQuantity(){
297            // do nothing
298        }
299        
300        public KualiDecimal getOutstandingQuantity() {
301                KualiDecimal outstandingQuantity = (this.getItemQuantity() != null) ? this.getItemQuantity() : KualiDecimal.ZERO;
302                KualiDecimal invoicedQuantity = (this.getItemInvoicedTotalQuantity() != null) ? this.getItemInvoicedTotalQuantity() : KualiDecimal.ZERO;
303                return outstandingQuantity.subtract(invoicedQuantity);
304        }
305        
306        public boolean isCanInactivateItem() {
307            if (versionNumber == null) {
308                // don't allow newly added item to be inactivatable.
309                return false;
310            }
311            else if (versionNumber != null && itemActiveIndicator && !getPurchaseOrder().getContainsUnpaidPaymentRequestsOrCreditMemos()) {
312                return true;
313            }
314            return false;
315        }
316            
317        /**
318         * Override the method in PurApItemBase so that if the item is
319         * not eligible to be displayed in the account summary tab,
320         * which is if the item is inactive, we'll return null and
321         * the item won't be added to the list of account summary.
322         * 
323         * @see org.kuali.kfs.module.purap.businessobject.PurApItemBase#getSummaryItem()
324         */
325        @Override
326        public PurApSummaryItem getSummaryItem() {
327            if (!this.itemActiveIndicator) {
328                return null;
329            }
330            else {
331                return super.getSummaryItem();
332            }
333        }
334    
335        public boolean isNewUnorderedItem(){
336            return SpringContext.getBean(PurchaseOrderService.class).isNewUnorderedItem(this);
337        }
338        
339        @Override
340        public boolean isNewItemForAmendment() {
341            return SpringContext.getBean(PurchaseOrderService.class).isNewItemForAmendment(this);
342        }
343    
344        @Override
345        public Class getUseTaxClass() {
346            return PurchaseOrderItemUseTax.class;
347        }
348    }