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 */ 016package org.kuali.ole.select.document.service.impl; 017 018 019import org.apache.commons.lang.StringUtils; 020import org.kuali.ole.module.purap.PurapConstants; 021import org.kuali.ole.module.purap.businessobject.*; 022import org.kuali.ole.module.purap.document.CorrectionReceivingDocument; 023import org.kuali.ole.module.purap.document.PurchaseOrderDocument; 024import org.kuali.ole.module.purap.document.ReceivingDocument; 025import org.kuali.ole.module.purap.document.service.ReceivingService; 026import org.kuali.ole.module.purap.document.service.impl.ReceivingServiceImpl; 027import org.kuali.ole.select.businessobject.*; 028import org.kuali.ole.sys.OLEConstants; 029import org.kuali.ole.sys.context.SpringContext; 030import org.kuali.rice.core.api.util.type.KualiDecimal; 031import org.kuali.rice.kew.api.exception.WorkflowException; 032import org.kuali.rice.krad.bo.AdHocRoutePerson; 033import org.kuali.rice.krad.service.BusinessObjectService; 034import org.kuali.rice.krad.util.ObjectUtils; 035import org.springframework.transaction.annotation.Transactional; 036 037import java.util.ArrayList; 038import java.util.HashMap; 039import java.util.List; 040import java.util.Map; 041 042/** 043 * This class has implementation for ReceivingService with respect to OLE. 044 */ 045 046@Transactional 047public class OleReceivingServiceImpl extends ReceivingServiceImpl implements ReceivingService { 048 049 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OleReceivingServiceImpl.class); 050 051 /** 052 * This method is overridden to set total parts received and total parts damaged for 053 * a PurchaseOrderItem 054 * 055 * @param receivingDocument ReceivingDocument from which total parts received and damaged are to be set in PO 056 * @param poDoc Purchase order document to set total parts received and damaged 057 * @return 058 * @see org.kuali.ole.module.purap.document.service.impl.ReceivingServiceImpl#updateReceivingTotalsOnPurchaseOrder(org.kuali.ole.module.purap.document.ReceivingDocument, org.kuali.ole.module.purap.document.PurchaseOrderDocument) 059 */ 060 @Override 061 protected void updateReceivingTotalsOnPurchaseOrder(ReceivingDocument receivingDocument, PurchaseOrderDocument poDoc) { 062 LOG.debug("Inside updateReceivingTotalsOnPurchaseOrder of OleReceivingServiceImpl"); 063 super.updateReceivingTotalsOnPurchaseOrder(receivingDocument, poDoc); 064 for (OleReceivingItem receivingItem : (List<OleReceivingItem>) receivingDocument.getItems()) { 065 ItemType itemType = receivingItem.getItemType(); 066 if (!StringUtils.equalsIgnoreCase(itemType.getItemTypeCode(), PurapConstants.ItemTypeCodes.ITEM_TYPE_UNORDERED_ITEM_CODE)) { 067 //TODO: Chris - this method of getting the line out of po should be turned into a method that can get an item based on a combo or itemType and line 068 OlePurchaseOrderItem poItem = (OlePurchaseOrderItem) poDoc.getItemByLineNumber(receivingItem.getItemLineNumber()); 069 070 if (ObjectUtils.isNotNull(poItem)) { 071 KualiDecimal poItemPartsReceivedTotal = poItem.getItemReceivedTotalParts(); 072 073 KualiDecimal receivingItemPartsReceivedOriginal = receivingItem.getItemOriginalReceivedTotalParts(); 074 075 if (ObjectUtils.isNull(receivingItemPartsReceivedOriginal)) { 076 receivingItemPartsReceivedOriginal = KualiDecimal.ZERO; 077 } 078 KualiDecimal receivingItemPartsReceived = receivingItem.getItemReceivedTotalParts(); 079 KualiDecimal receivingItemPartsTotalReceivedAdjusted = receivingItemPartsReceived.subtract(receivingItemPartsReceivedOriginal); 080 081 if (ObjectUtils.isNull(poItemPartsReceivedTotal)) { 082 poItemPartsReceivedTotal = KualiDecimal.ZERO; 083 } 084 KualiDecimal poItemPartsReceivedTotalAdjusted = poItemPartsReceivedTotal.add(receivingItemPartsTotalReceivedAdjusted); 085 086 KualiDecimal receivingItemPartsReturnedOriginal = receivingItem.getItemOriginalReturnedTotalParts(); 087 if (ObjectUtils.isNull(receivingItemPartsReturnedOriginal)) { 088 receivingItemPartsReturnedOriginal = KualiDecimal.ZERO; 089 } 090 091 KualiDecimal receivingItemPartsReturned = receivingItem.getItemReturnedTotalParts(); 092 if (ObjectUtils.isNull(receivingItemPartsReturned)) { 093 receivingItemPartsReturned = KualiDecimal.ZERO; 094 } 095 096 KualiDecimal receivingItemPartsTotalReturnedAdjusted = receivingItemPartsReturned.subtract(receivingItemPartsReturnedOriginal); 097 098 poItemPartsReceivedTotalAdjusted = poItemPartsReceivedTotalAdjusted.subtract(receivingItemPartsTotalReturnedAdjusted); 099 100 poItem.setItemReceivedTotalParts(poItemPartsReceivedTotalAdjusted); 101 102 KualiDecimal poPartsTotalDamaged = poItem.getItemDamagedTotalParts(); 103 if (ObjectUtils.isNull(poPartsTotalDamaged)) { 104 poPartsTotalDamaged = KualiDecimal.ZERO; 105 } 106 107 KualiDecimal receivingItemPartsTotalDamagedOriginal = receivingItem.getItemOriginalDamagedTotalParts(); 108 if (ObjectUtils.isNull(receivingItemPartsTotalDamagedOriginal)) { 109 receivingItemPartsTotalDamagedOriginal = KualiDecimal.ZERO; 110 } 111 112 KualiDecimal receivingItemPartsTotalDamaged = receivingItem.getItemDamagedTotalParts(); 113 if (ObjectUtils.isNull(receivingItemPartsTotalDamaged)) { 114 receivingItemPartsTotalDamaged = KualiDecimal.ZERO; 115 } 116 117 KualiDecimal receivingItemPartsTotalDamagedAdjusted = receivingItemPartsTotalDamaged.subtract(receivingItemPartsTotalDamagedOriginal); 118 119 poItem.setItemDamagedTotalParts(poPartsTotalDamaged.add(receivingItemPartsTotalDamagedAdjusted)); 120 } 121 } 122 } 123 LOG.debug("Leaving updateReceivingTotalsOnPurchaseOrder of OleReceivingServiceImpl"); 124 } 125 126 /** 127 * This method is overridden to set total parts receiving and damaged in OlePurchaseOrderItem from OleLineItemReceivingItem 128 * 129 * @param rlItem Receiving line item from which total damaged and received parts are to be set in PO 130 * @return 131 * @see org.kuali.ole.module.purap.document.service.impl.ReceivingServiceImpl#createPoItemFromReceivingLine(org.kuali.ole.module.purap.businessobject.LineItemReceivingItem) 132 */ 133 @Override 134 protected PurchaseOrderItem createPoItemFromReceivingLine(LineItemReceivingItem rlItem) { 135 LOG.debug("Inside createPoItemFromReceivingLine of OleReceivingServiceImpl"); 136 OlePurchaseOrderItem poi = (OlePurchaseOrderItem) super.createPoItemFromReceivingLine(rlItem); 137 OleLineItemReceivingItem oleRlItem = (OleLineItemReceivingItem) rlItem; 138 poi.setItemDamagedTotalParts(oleRlItem.getItemDamagedTotalParts()); 139 poi.setItemReceivedTotalParts(oleRlItem.getItemReceivedTotalParts()); 140 poi.setBibInfoBean(oleRlItem.getBibInfoBean()); 141 poi.setItemTitleId(oleRlItem.getItemTitleId()); 142 LOG.debug("Leaving createPoItemFromReceivingLine of OleReceivingServiceImpl"); 143 return poi; 144 } 145 146 147 /** 148 * This method is overridden to disable notes on a document when quantity returned or damaged is entered. 149 * 150 * @param recDoc Receiving Document 151 * @return 152 * @see org.kuali.ole.module.purap.document.service.impl.ReceivingServiceImpl#createNoteForReturnedAndDamagedItems(org.kuali.ole.module.purap.document.ReceivingDocument) 153 */ 154 @Override 155 public void createNoteForReturnedAndDamagedItems(ReceivingDocument recDoc) { 156 157 } 158 159 /** 160 * This method is overridden to include parts values in creating a list of fiscal officers for new unordered items added to a purchase order. 161 * 162 * @param recDoc ReceivingDocument 163 * @return Fiscal officer list to send notification 164 * @see org.kuali.ole.module.purap.document.service.impl.ReceivingServiceImpl#createFyiFiscalOfficerList(org.kuali.ole.module.purap.document.ReceivingDocument) 165 */ 166 @Override 167 protected List<AdHocRoutePerson> createFyiFiscalOfficerList(ReceivingDocument recDoc) { 168 LOG.debug("Inside createFyiFiscalOfficerList of OleReceivingServiceImpl"); 169 PurchaseOrderDocument po = recDoc.getPurchaseOrderDocument(); 170 List<AdHocRoutePerson> adHocRoutePersons = new ArrayList<AdHocRoutePerson>(); 171 Map fiscalOfficers = new HashMap(); 172 AdHocRoutePerson adHocRoutePerson = null; 173 174 for (OleReceivingItem recItem : (List<OleReceivingItem>) recDoc.getItems()) { 175 //if this item has an item line number then it is coming from the po 176 if (ObjectUtils.isNotNull(recItem.getItemLineNumber())) { 177 OlePurchaseOrderItem poItem = (OlePurchaseOrderItem) po.getItemByLineNumber(recItem.getItemLineNumber()); 178 179 if ((poItem.getItemQuantity().isLessThan(poItem.getItemReceivedTotalQuantity()) || 180 recItem.getItemDamagedTotalQuantity().isGreaterThan(KualiDecimal.ZERO)) 181 && (((poItem.getItemNoOfParts().kualiDecimalValue()).isLessThan(poItem.getItemReceivedTotalParts())) 182 || recItem.getItemDamagedTotalParts().isGreaterThan(KualiDecimal.ZERO))) { 183 184 // loop through accounts and pull off fiscal officer 185 for (PurApAccountingLine account : poItem.getSourceAccountingLines()) { 186 187 //check for dupes of fiscal officer 188 if (fiscalOfficers.containsKey(account.getAccount().getAccountFiscalOfficerUser().getPrincipalName()) == false) { 189 190 //add fiscal officer to list 191 fiscalOfficers.put(account.getAccount().getAccountFiscalOfficerUser().getPrincipalName(), account.getAccount().getAccountFiscalOfficerUser().getPrincipalName()); 192 193 //create AdHocRoutePerson object and add to list 194 adHocRoutePerson = new AdHocRoutePerson(); 195 adHocRoutePerson.setId(account.getAccount().getAccountFiscalOfficerUser().getPrincipalName()); 196 adHocRoutePerson.setActionRequested(OLEConstants.WORKFLOW_FYI_REQUEST); 197 adHocRoutePersons.add(adHocRoutePerson); 198 } 199 } 200 201 } 202 203 } 204 } 205 LOG.debug("Leaving createFyiFiscalOfficerList of OleReceivingServiceImpl"); 206 return adHocRoutePersons; 207 } 208 209 /** 210 * This method is overridden to change annotation to include Parts 211 * 212 * @see org.kuali.ole.module.purap.document.service.impl.ReceivingServiceImpl#sendFyiForItems(org.kuali.ole.module.purap.document.ReceivingDocument) 213 */ 214 @Override 215 protected void sendFyiForItems(ReceivingDocument recDoc) { 216 LOG.debug("Inside sendFyiForItems of OleReceivingServiceImpl"); 217 List<AdHocRoutePerson> fyiList = createFyiFiscalOfficerList(recDoc); 218 String annotation = "Notification of Item exceeded Quantity/Parts or Damaged" + "(document id " + recDoc.getDocumentNumber() + ")"; 219 String responsibilityNote = "Please Review"; 220 221 for (AdHocRoutePerson adHocPerson : fyiList) { 222 try { 223 recDoc.appSpecificRouteDocumentToUser( 224 recDoc.getDocumentHeader().getWorkflowDocument(), 225 adHocPerson.getId(), 226 annotation, 227 responsibilityNote); 228 } catch (WorkflowException e) { 229 throw new RuntimeException("Error routing fyi for document with id " + recDoc.getDocumentNumber(), e); 230 } 231 232 } 233 LOG.debug("Leaving sendFyiForItems of OleReceivingServiceImpl"); 234 } 235 236 /** 237 * This method deletes unneeded items and updates the totals on the po and does any additional processing based on items i.e. 238 * FYI etc 239 * 240 * @param receivingDocument receiving document 241 */ 242 @Override 243 public void completeCorrectionReceivingDocument(ReceivingDocument correctionDocument) { 244 ReceivingDocument receivingDoc = ((CorrectionReceivingDocument) correctionDocument) 245 .getLineItemReceivingDocument(); 246 247 if (correctionDocument.getItems().size() >= 1) { 248 for (OleCorrectionReceivingItem correctionItem : (List<OleCorrectionReceivingItem>) correctionDocument.getItems()) { 249 if (!StringUtils.equalsIgnoreCase(correctionItem.getItemType().getItemTypeCode(), 250 PurapConstants.ItemTypeCodes.ITEM_TYPE_UNORDERED_ITEM_CODE)) { 251 int itemNumber = correctionItem.getItemLineNumber().intValue(); 252 OleLineItemReceivingItem recItem = (OleLineItemReceivingItem) receivingDoc.getItem(correctionItem 253 .getItemLineNumber().intValue() - itemNumber); 254 List<PurchaseOrderItem> purchaseOrderItems = receivingDoc.getPurchaseOrderDocument().getItems(); 255 PurchaseOrderItem poItem = purchaseOrderItems.get(correctionItem.getItemLineNumber().intValue() 256 - itemNumber); 257 258 if (ObjectUtils.isNotNull(recItem)) { 259 recItem.setItemReceivedTotalQuantity(correctionItem.getItemReceivedTotalQuantity()); 260 recItem.setItemReceivedTotalParts(correctionItem.getItemReceivedTotalParts()); 261 recItem.setItemReturnedTotalQuantity(correctionItem.getItemReturnedTotalQuantity()); 262 recItem.setItemReturnedTotalParts(correctionItem.getItemReturnedTotalParts()); 263 recItem.setItemDamagedTotalQuantity(correctionItem.getItemDamagedTotalQuantity()); 264 recItem.setItemDamagedTotalParts(correctionItem.getItemDamagedTotalParts()); 265 updateReceivingItemReceiptStatus(recItem, correctionItem); 266 } 267 } 268 } 269 270 271 } else { 272 for (CorrectionReceivingItem correctionItem : (List<CorrectionReceivingItem>) correctionDocument.getItems()) { 273 if (!StringUtils.equalsIgnoreCase(correctionItem.getItemType().getItemTypeCode(), 274 PurapConstants.ItemTypeCodes.ITEM_TYPE_UNORDERED_ITEM_CODE)) { 275 LineItemReceivingItem recItem = (LineItemReceivingItem) receivingDoc.getItem(correctionItem 276 .getItemLineNumber().intValue() - 1); 277 List<PurchaseOrderItem> purchaseOrderItems = receivingDoc.getPurchaseOrderDocument().getItems(); 278 PurchaseOrderItem poItem = purchaseOrderItems 279 .get(correctionItem.getItemLineNumber().intValue() - 1); 280 281 if (ObjectUtils.isNotNull(recItem)) { 282 recItem.setItemReceivedTotalQuantity(correctionItem.getItemReceivedTotalQuantity()); 283 recItem.setItemReturnedTotalQuantity(correctionItem.getItemReturnedTotalQuantity()); 284 recItem.setItemDamagedTotalQuantity(correctionItem.getItemDamagedTotalQuantity()); 285 } 286 } 287 } 288 } 289 } 290 291 public void updateReceivingItemReceiptStatus(OleLineItemReceivingItem recItem, 292 OleCorrectionReceivingItem correctionItem) { 293 294 int finalCopiesReceived = (correctionItem.getItemReceivedTotalQuantity().subtract( 295 correctionItem.getItemReturnedTotalQuantity()).intValue()); 296 int finalPartsReceived = (correctionItem.getItemReceivedTotalParts().subtract( 297 correctionItem.getItemReturnedTotalParts()).intValue()); 298 if (correctionItem.getItemOriginalReceivedTotalQuantity().intValue() == finalCopiesReceived 299 && correctionItem.getItemOriginalReceivedTotalParts().intValue() == finalPartsReceived) { 300 recItem.setReceiptStatusId(getReceiptStatusDetails(OLEConstants.RCV_RECEIPT_STATUS_RCVD)); 301 } else { 302 if (finalCopiesReceived == 0 && finalCopiesReceived == 0) { 303 recItem.setReceiptStatusId(getReceiptStatusDetails(OLEConstants.RCV_RECEIPT_STATUS_NONE)); 304 } else { 305 recItem.setReceiptStatusId(getReceiptStatusDetails(OLEConstants.RCV_RECEIPT_STATUS_EXPTD)); 306 } 307 } 308 } 309 310 public int getReceiptStatusDetails(String receiptStatusCd) { 311 int receiptStatusId = 0; 312 Map<String, String> receiptStatusCdMap = new HashMap<String, String>(); 313 receiptStatusCdMap.put(OLEConstants.RCPT_STATUS_CD, receiptStatusCd); 314 List<OleReceiptStatus> oleReceiptStatusList = (List) SpringContext.getBean(BusinessObjectService.class) 315 .findMatching(OleReceiptStatus.class, receiptStatusCdMap); 316 for (OleReceiptStatus oleReceiptStatus : oleReceiptStatusList) { 317 receiptStatusId = oleReceiptStatus.getReceiptStatusId().intValue(); 318 } 319 return receiptStatusId; 320 } 321 322} 323