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 package org.kuali.kfs.module.purap.document; 017 018 import java.util.LinkedHashMap; 019 import java.util.List; 020 021 import org.apache.commons.lang.StringUtils; 022 import org.kuali.kfs.module.purap.PurapConstants; 023 import org.kuali.kfs.module.purap.PurapWorkflowConstants; 024 import org.kuali.kfs.module.purap.businessobject.LineItemReceivingItem; 025 import org.kuali.kfs.module.purap.businessobject.PurchaseOrderItem; 026 import org.kuali.kfs.module.purap.document.service.PurapService; 027 import org.kuali.kfs.module.purap.document.service.PurchaseOrderService; 028 import org.kuali.kfs.module.purap.document.service.ReceivingService; 029 import org.kuali.kfs.module.purap.document.validation.event.AttributedContinuePurapEvent; 030 import org.kuali.kfs.sys.context.SpringContext; 031 import org.kuali.rice.kew.dto.DocumentRouteLevelChangeDTO; 032 import org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO; 033 import org.kuali.rice.kns.bo.DocumentHeader; 034 import org.kuali.rice.kns.rule.event.KualiDocumentEvent; 035 import org.kuali.rice.kns.service.DataDictionaryService; 036 import org.kuali.rice.kns.util.KNSPropertyConstants; 037 import org.kuali.rice.kns.util.KualiDecimal; 038 import org.kuali.rice.kns.util.TypedArrayList; 039 040 /** 041 * @author Kuali Nervous System Team (kualidev@oncourse.iu.edu) 042 */ 043 public class LineItemReceivingDocument extends ReceivingDocumentBase { 044 045 //Collections 046 protected List<LineItemReceivingItem> items; 047 048 /** 049 * Default constructor. 050 */ 051 public LineItemReceivingDocument() { 052 super(); 053 items = new TypedArrayList(getItemClass()); 054 } 055 056 @Override 057 public void initiateDocument(){ 058 super.initiateDocument(); 059 this.setLineItemReceivingStatusCode(PurapConstants.LineItemReceivingStatuses.IN_PROCESS); 060 } 061 062 public void populateReceivingLineFromPurchaseOrder(PurchaseOrderDocument po){ 063 064 //populate receiving line document from purchase order 065 this.setPurchaseOrderIdentifier( po.getPurapDocumentIdentifier() ); 066 this.getDocumentHeader().setOrganizationDocumentNumber( po.getDocumentHeader().getOrganizationDocumentNumber() ); 067 this.setAccountsPayablePurchasingDocumentLinkIdentifier( po.getAccountsPayablePurchasingDocumentLinkIdentifier() ); 068 069 //copy vendor 070 this.setVendorHeaderGeneratedIdentifier( po.getVendorHeaderGeneratedIdentifier() ); 071 this.setVendorDetailAssignedIdentifier( po.getVendorDetailAssignedIdentifier() ); 072 this.setVendorName( po.getVendorName() ); 073 this.setVendorNumber( po.getVendorNumber() ); 074 this.setVendorAddressGeneratedIdentifier( po.getVendorAddressGeneratedIdentifier() ); 075 this.setVendorLine1Address( po.getVendorLine1Address() ); 076 this.setVendorLine2Address( po.getVendorLine2Address() ); 077 this.setVendorCityName( po.getVendorCityName() ); 078 this.setVendorStateCode( po.getVendorStateCode() ); 079 this.setVendorPostalCode( po.getVendorPostalCode() ); 080 this.setVendorCountryCode( po.getVendorCountryCode() ); 081 082 //copy alternate vendor 083 this.setAlternateVendorName( po.getAlternateVendorName() ); 084 this.setAlternateVendorNumber( po.getAlternateVendorNumber() ); 085 this.setAlternateVendorDetailAssignedIdentifier( po.getAlternateVendorDetailAssignedIdentifier() ); 086 this.setAlternateVendorHeaderGeneratedIdentifier( po.getAlternateVendorHeaderGeneratedIdentifier() ); 087 088 //copy delivery 089 this.setDeliveryBuildingCode( po.getDeliveryBuildingCode() ); 090 this.setDeliveryBuildingLine1Address( po.getDeliveryBuildingLine1Address() ); 091 this.setDeliveryBuildingLine2Address( po.getDeliveryBuildingLine2Address() ); 092 this.setDeliveryBuildingName( po.getDeliveryBuildingName() ); 093 this.setDeliveryBuildingRoomNumber( po.getDeliveryBuildingRoomNumber() ); 094 this.setDeliveryCampusCode( po.getDeliveryCampusCode() ); 095 this.setDeliveryCityName( po.getDeliveryCityName() ); 096 this.setDeliveryCountryCode( po.getDeliveryCountryCode() ); 097 this.setDeliveryInstructionText( po.getDeliveryInstructionText() ); 098 this.setDeliveryPostalCode( po.getDeliveryPostalCode() ); 099 this.setDeliveryRequiredDate( po.getDeliveryRequiredDate() ); 100 this.setDeliveryRequiredDateReasonCode( po.getDeliveryRequiredDateReasonCode() ); 101 this.setDeliveryStateCode( po.getDeliveryStateCode() ); 102 this.setDeliveryToEmailAddress( po.getDeliveryToEmailAddress() ); 103 this.setDeliveryToName( po.getDeliveryToName() ); 104 this.setDeliveryToPhoneNumber( po.getDeliveryToPhoneNumber() ); 105 106 //copy purchase order items 107 for (PurchaseOrderItem poi : (List<PurchaseOrderItem>) po.getItems()) { 108 //TODO: Refactor this check into a service call. route FYI during submit 109 if(poi.isItemActiveIndicator() && 110 poi.getItemType().isQuantityBasedGeneralLedgerIndicator() && 111 poi.getItemType().isLineItemIndicator() ){ 112 this.getItems().add(new LineItemReceivingItem(poi, this)); 113 } 114 } 115 116 populateDocumentDescription(po); 117 } 118 119 /** 120 * Perform logic needed to clear the initial fields on a Receiving Line Document 121 */ 122 public void clearInitFields(boolean fromPurchaseOrder) { 123 // Clearing document overview fields 124 this.getDocumentHeader().setDocumentDescription(null); 125 this.getDocumentHeader().setExplanation(null); 126 this.getDocumentHeader().setFinancialDocumentTotalAmount(null); 127 this.getDocumentHeader().setOrganizationDocumentNumber(null); 128 129 // Clearing document Init fields 130 if(fromPurchaseOrder == false){ 131 this.setPurchaseOrderIdentifier(null); 132 } 133 this.setShipmentReceivedDate(null); 134 this.setShipmentPackingSlipNumber(null); 135 this.setShipmentBillOfLadingNumber(null); 136 this.setCarrierCode(null); 137 } 138 139 140 @Override 141 public void prepareForSave(KualiDocumentEvent event) { 142 143 // first populate, then call super 144 if (event instanceof AttributedContinuePurapEvent) { 145 SpringContext.getBean(ReceivingService.class).populateReceivingLineFromPurchaseOrder(this); 146 } 147 148 super.prepareForSave(event); 149 } 150 151 @Override 152 public void doRouteStatusChange(DocumentRouteStatusChangeDTO statusChangeEvent) { 153 super.doRouteStatusChange(statusChangeEvent); 154 // DOCUMENT CANCELED 155 // If the document is canceled then set the line item receiving 156 // status code to CANC. 157 if (this.getDocumentHeader().getWorkflowDocument().stateIsCanceled()) { 158 setLineItemReceivingStatusCode(PurapConstants.LineItemReceivingStatuses.CANCELLED); 159 } 160 } 161 162 @Override 163 public void doRouteLevelChange(DocumentRouteLevelChangeDTO change) { 164 //If the new node is Outstanding Transactions then we want to set the line item 165 //receiving status code to APOO. 166 if (StringUtils.equals(PurapConstants.LineItemReceivingDocumentStrings.AWAITING_PO_OPEN_STATUS, change.getNewNodeName())){ 167 setLineItemReceivingStatusCode(PurapConstants.LineItemReceivingStatuses.AWAITING_PO_OPEN_STATUS); 168 } 169 //If the new node is Join, this means we're done with the routing, so we'll set 170 //the line item receiving status code to CMPT. 171 else if (StringUtils.equals(PurapConstants.LineItemReceivingDocumentStrings.JOIN_NODE, change.getNewNodeName())) { 172 setLineItemReceivingStatusCode(PurapConstants.LineItemReceivingStatuses.COMPLETE); 173 } 174 SpringContext.getBean(PurapService.class).saveDocumentNoValidation(this); 175 } 176 177 /** 178 * @see org.kuali.rice.kns.bo.BusinessObjectBase#toStringMapper() 179 */ 180 protected LinkedHashMap toStringMapper() { 181 LinkedHashMap m = new LinkedHashMap(); 182 m.put("documentNumber", this.documentNumber); 183 return m; 184 } 185 186 public Class getItemClass() { 187 return LineItemReceivingItem.class; 188 } 189 190 public List getItems() { 191 return items; 192 } 193 194 public void setItems(List items) { 195 this.items = items; 196 } 197 198 public LineItemReceivingItem getItem(int pos) { 199 return (LineItemReceivingItem) items.get(pos); 200 } 201 202 public void addItem(LineItemReceivingItem item) { 203 getItems().add(item); 204 } 205 206 public void deleteItem(int lineNum) { 207 if (getItems().remove(lineNum) == null) { 208 // throw error here 209 } 210 } 211 212 protected void populateDocumentDescription(PurchaseOrderDocument poDocument) { 213 String description = "PO: " + poDocument.getPurapDocumentIdentifier() + " Vendor: " + poDocument.getVendorName(); 214 int noteTextMaxLength = SpringContext.getBean(DataDictionaryService.class).getAttributeMaxLength(DocumentHeader.class, KNSPropertyConstants.DOCUMENT_DESCRIPTION).intValue(); 215 if (noteTextMaxLength < description.length()) { 216 description = description.substring(0, noteTextMaxLength); 217 } 218 getDocumentHeader().setDocumentDescription(description); 219 } 220 221 222 protected boolean isAwaitingPurchaseOrderOpen() { 223 return SpringContext.getBean(PurchaseOrderService.class).isPurchaseOrderOpenForProcessing(getPurchaseOrderDocument()); 224 } 225 226 /** 227 * Provides answers to the following splits: 228 * RelatesToOutstandingTransactions 229 * 230 * @see org.kuali.kfs.sys.document.FinancialSystemTransactionalDocumentBase#answerSplitNodeQuestion(java.lang.String) 231 */ 232 public boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException { 233 if (nodeName.equals(PurapWorkflowConstants.RELATES_TO_OUTSTANDING_TRANSACTIONS)) return !isAwaitingPurchaseOrderOpen(); 234 throw new UnsupportedOperationException("Cannot answer split question for this node you call \""+nodeName+"\""); 235 } 236 237 public List buildListOfDeletionAwareLists() { 238 List managedLists = super.buildListOfDeletionAwareLists(); 239 managedLists.add(this.getItems()); 240 return managedLists; 241 } 242 243 public KualiDecimal getTotalItemReceivedGivenLineNumber(Integer lineNumber) { 244 for (LineItemReceivingItem item : items) { 245 if (item.getItemLineNumber().equals(lineNumber)) { 246 return item.getItemReceivedTotalQuantity(); 247 } 248 } 249 return new KualiDecimal(0); 250 } 251 }