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 }