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 }