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.web.struts;
017
018 import java.util.HashMap;
019 import java.util.List;
020 import java.util.Properties;
021
022 import javax.servlet.http.HttpServletRequest;
023 import javax.servlet.http.HttpServletResponse;
024
025 import org.apache.commons.lang.StringUtils;
026 import org.apache.struts.action.ActionForm;
027 import org.apache.struts.action.ActionForward;
028 import org.apache.struts.action.ActionMapping;
029 import org.kuali.kfs.module.purap.PurapConstants;
030 import org.kuali.kfs.module.purap.PurapKeyConstants;
031 import org.kuali.kfs.module.purap.PurapPropertyConstants;
032 import org.kuali.kfs.module.purap.PurapConstants.CorrectionReceivingDocumentStrings;
033 import org.kuali.kfs.module.purap.PurapConstants.PREQDocumentsStrings;
034 import org.kuali.kfs.module.purap.businessobject.LineItemReceivingItem;
035 import org.kuali.kfs.module.purap.document.LineItemReceivingDocument;
036 import org.kuali.kfs.module.purap.document.PurchaseOrderDocument;
037 import org.kuali.kfs.module.purap.document.ReceivingDocument;
038 import org.kuali.kfs.module.purap.document.service.PurchaseOrderService;
039 import org.kuali.kfs.module.purap.document.service.ReceivingService;
040 import org.kuali.kfs.module.purap.document.validation.event.AddReceivingItemEvent;
041 import org.kuali.kfs.module.purap.util.ReceivingQuestionCallback;
042 import org.kuali.kfs.sys.KFSConstants;
043 import org.kuali.kfs.sys.KFSKeyConstants;
044 import org.kuali.kfs.sys.KFSPropertyConstants;
045 import org.kuali.kfs.sys.context.SpringContext;
046 import org.kuali.rice.kew.exception.WorkflowException;
047 import org.kuali.rice.kim.util.KimConstants;
048 import org.kuali.rice.kns.question.ConfirmationQuestion;
049 import org.kuali.rice.kns.service.DocumentHelperService;
050 import org.kuali.rice.kns.service.KualiRuleService;
051 import org.kuali.rice.kns.util.GlobalVariables;
052 import org.kuali.rice.kns.util.KNSConstants;
053 import org.kuali.rice.kns.util.KualiDecimal;
054 import org.kuali.rice.kns.util.ObjectUtils;
055 import org.kuali.rice.kns.util.UrlFactory;
056 import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
057
058 public class LineItemReceivingAction extends ReceivingBaseAction {
059
060 protected void createDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException {
061
062 super.createDocument(kualiDocumentFormBase);
063
064 LineItemReceivingForm rlf = (LineItemReceivingForm)kualiDocumentFormBase;
065 LineItemReceivingDocument rlDoc = (LineItemReceivingDocument)rlf.getDocument();
066
067 //set identifier from form value
068 rlDoc.setPurchaseOrderIdentifier( rlf.getPurchaseOrderId() );
069
070 rlDoc.initiateDocument();
071
072 }
073
074 public ActionForward continueReceivingLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
075 LineItemReceivingForm rlf = (LineItemReceivingForm)form;
076 LineItemReceivingDocument rlDoc = (LineItemReceivingDocument)rlf.getDocument();
077
078 GlobalVariables.getMessageMap().clearErrorPath();
079 GlobalVariables.getMessageMap().addToErrorPath(KFSPropertyConstants.DOCUMENT);
080 boolean valid = true;
081 boolean poNotNull = true;
082
083 //check for a po id
084 if (ObjectUtils.isNull(rlDoc.getPurchaseOrderIdentifier())) {
085 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.PURCHASE_ORDER_IDENTIFIER, KFSKeyConstants.ERROR_REQUIRED, PREQDocumentsStrings.PURCHASE_ORDER_ID);
086 poNotNull = false;
087 }
088
089 if (ObjectUtils.isNull(rlDoc.getShipmentReceivedDate())) {
090 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.SHIPMENT_RECEIVED_DATE, KFSKeyConstants.ERROR_REQUIRED, PurapConstants.LineItemReceivingDocumentStrings.VENDOR_DATE);
091 }
092
093 //exit early as the po is null, no need to proceed further until this is taken care of
094 if(poNotNull == false){
095 return mapping.findForward(KFSConstants.MAPPING_BASIC);
096 }
097
098 PurchaseOrderDocument po = SpringContext.getBean(PurchaseOrderService.class).getCurrentPurchaseOrder(rlDoc.getPurchaseOrderIdentifier());
099 if (ObjectUtils.isNotNull(po)) {
100 // TODO figure out a more straightforward way to do this. ailish put this in so the link id would be set and the perm check would work
101 rlDoc.setAccountsPayablePurchasingDocumentLinkIdentifier(po.getAccountsPayablePurchasingDocumentLinkIdentifier());
102
103 //TODO hjs-check to see if user is allowed to initiate doc based on PO sensitive data (add this to all other docs except acm doc)
104 if (!SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(rlDoc).isAuthorizedByTemplate(rlDoc, KNSConstants.KNS_NAMESPACE, KimConstants.PermissionTemplateNames.OPEN_DOCUMENT, GlobalVariables.getUserSession().getPrincipalId())) {
105 throw buildAuthorizationException("initiate document", rlDoc);
106 }
107 }else{
108 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.PURCHASE_ORDER_IDENTIFIER, PurapKeyConstants.ERROR_PURCHASE_ORDER_NOT_EXIST);
109 return mapping.findForward(KFSConstants.MAPPING_BASIC);
110 }
111
112 //perform duplicate check
113 ActionForward forward = performDuplicateReceivingLineCheck(mapping, form, request, response, rlDoc);
114 if( forward != null ){
115 return forward;
116 }
117
118 if (!SpringContext.getBean(ReceivingService.class).isPurchaseOrderActiveForLineItemReceivingDocumentCreation(rlDoc.getPurchaseOrderIdentifier())){
119 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.PURCHASE_ORDER_IDENTIFIER, PurapKeyConstants.ERROR_RECEIVING_LINE_DOCUMENT_PO_NOT_ACTIVE, rlDoc.getPurchaseOrderIdentifier().toString());
120 valid &= false;
121 }
122
123 if( SpringContext.getBean(ReceivingService.class).canCreateLineItemReceivingDocument(rlDoc.getPurchaseOrderIdentifier(), rlDoc.getDocumentNumber()) == false){
124 String inProcessDocNum = "";
125 List<String> inProcessDocNumbers = SpringContext.getBean(ReceivingService.class).getLineItemReceivingDocumentNumbersInProcessForPurchaseOrder(rlDoc.getPurchaseOrderIdentifier(), rlDoc.getDocumentNumber());
126 if (!inProcessDocNumbers.isEmpty()) { // should not be empty if we reach this point
127 inProcessDocNum = inProcessDocNumbers.get(0);
128 }
129 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.PURCHASE_ORDER_IDENTIFIER, PurapKeyConstants.ERROR_RECEIVING_LINE_DOCUMENT_ACTIVE_FOR_PO, inProcessDocNum, rlDoc.getPurchaseOrderIdentifier().toString());
130 valid &= false;
131 }
132
133 //populate and save Receiving Line Document from Purchase Order, only if we passed all the rules
134 if(valid){
135 SpringContext.getBean(ReceivingService.class).populateAndSaveLineItemReceivingDocument(rlDoc);
136 }
137
138 return mapping.findForward(KFSConstants.MAPPING_BASIC);
139 }
140
141 public ActionForward createReceivingCorrection(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
142 LineItemReceivingForm rlForm = (LineItemReceivingForm) form;
143 LineItemReceivingDocument document = (LineItemReceivingDocument) rlForm.getDocument();
144
145 String operation = "AddCorrectionNote ";
146
147 ReceivingQuestionCallback callback = new ReceivingQuestionCallback() {
148 public boolean questionComplete = false;
149 protected String correctionDocumentnoteText;
150
151 public ReceivingDocument doPostQuestion(ReceivingDocument document, String noteText) throws Exception {
152 //mark question completed
153 this.setQuestionComplete(true);
154 this.setCorrectionDocumentCreationNoteText(noteText);
155 return document;
156 }
157
158 public boolean isQuestionComplete(){
159 return this.questionComplete;
160 }
161
162 public void setQuestionComplete(boolean questionComplete){
163 this.questionComplete = questionComplete;
164 }
165
166 public String getCorrectionDocumentCreationNoteText() {
167 return correctionDocumentnoteText;
168 }
169
170 public void setCorrectionDocumentCreationNoteText(String noteText) {
171 correctionDocumentnoteText = noteText;
172 }
173 };
174
175 //ask question
176 ActionForward forward = askQuestionWithInput(mapping, form, request, response, CorrectionReceivingDocumentStrings.NOTE_QUESTION, CorrectionReceivingDocumentStrings.NOTE_PREFIX, operation, PurapKeyConstants.MESSAGE_RECEIVING_CORRECTION_NOTE, callback);
177
178 //if question asked is complete, then route
179 if(callback.isQuestionComplete()){
180
181 //set parameters
182 String basePath = getBasePath(request);
183 String methodToCallDocHandler = "docHandler";
184 String methodToCallReceivingCorrection = "initiate";
185
186 Properties parameters = new Properties();
187 parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, methodToCallDocHandler);
188 parameters.put(KFSConstants.PARAMETER_COMMAND, methodToCallReceivingCorrection);
189 parameters.put(KFSConstants.DOCUMENT_TYPE_NAME, "RCVC");
190 parameters.put("receivingLineDocId", document.getDocumentHeader().getDocumentNumber() );
191 parameters.put(PurapConstants.CorrectionReceivingDocumentStrings.CORRECTION_RECEIVING_CREATION_NOTE_PARAMETER, callback.getCorrectionDocumentCreationNoteText());
192
193 //create url
194 String receivingCorrectionUrl = UrlFactory.parameterizeUrl(basePath + "/" + "purapCorrectionReceiving.do", parameters);
195 //create forward
196 forward = new ActionForward(receivingCorrectionUrl, true);
197 }
198
199 return forward;
200
201 }
202
203 public ActionForward clearInitFields(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
204 LineItemReceivingForm rlForm = (LineItemReceivingForm) form;
205 LineItemReceivingDocument rlDocument = (LineItemReceivingDocument) rlForm.getDocument();
206 rlDocument.clearInitFields(rlForm.isFromPurchaseOrder());
207
208 return mapping.findForward(KFSConstants.MAPPING_BASIC);
209 }
210
211 protected ActionForward performDuplicateReceivingLineCheck(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, LineItemReceivingDocument lineItemReceivingDocument) throws Exception {
212 ActionForward forward = null;
213 HashMap<String, String> duplicateMessages = SpringContext.getBean(ReceivingService.class).receivingLineDuplicateMessages(lineItemReceivingDocument);
214 if (duplicateMessages != null && !duplicateMessages.isEmpty()) {
215 Object question = request.getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME);
216 if (question == null) {
217
218 return this.performQuestionWithoutInput(mapping, form, request, response, PurapConstants.LineItemReceivingDocumentStrings.DUPLICATE_RECEIVING_LINE_QUESTION, duplicateMessages.get(PurapConstants.LineItemReceivingDocumentStrings.DUPLICATE_RECEIVING_LINE_QUESTION), KFSConstants.CONFIRMATION_QUESTION, KFSConstants.ROUTE_METHOD, "");
219 }
220
221 Object buttonClicked = request.getParameter(KFSConstants.QUESTION_CLICKED_BUTTON);
222 if ((PurapConstants.LineItemReceivingDocumentStrings.DUPLICATE_RECEIVING_LINE_QUESTION.equals(question)) && ConfirmationQuestion.NO.equals(buttonClicked)) {
223 forward = mapping.findForward(KFSConstants.MAPPING_BASIC);
224 }
225 }
226
227 return forward;
228 }
229 /**
230 * Add a new item to the document.
231 *
232 * @param mapping An ActionMapping
233 * @param form An ActionForm
234 * @param request The HttpServletRequest
235 * @param response The HttpServletResponse
236 * @throws Exception
237 * @return An ActionForward
238 */
239 public ActionForward addItem(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
240 LineItemReceivingForm lineItemReceivingForm = (LineItemReceivingForm) form;
241 LineItemReceivingItem item = lineItemReceivingForm.getNewLineItemReceivingItemLine();
242 LineItemReceivingDocument lineItemReceivingDocument = (LineItemReceivingDocument) lineItemReceivingForm.getDocument();
243 boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new AddReceivingItemEvent(PurapPropertyConstants.NEW_LINE_ITEM_RECEIVING_ITEM_LINE, lineItemReceivingDocument, item));
244
245 if (rulePassed) {
246 item = lineItemReceivingForm.getAndResetNewReceivingItemLine();
247 lineItemReceivingDocument.addItem(item);
248 //TODO: we need to set the line number correctly to match up to PO
249 }
250
251 return mapping.findForward(KFSConstants.MAPPING_BASIC);
252 }
253
254 /**
255 * For each item, it's quantity received value is set to zero.
256 *
257 * @param mapping
258 * @param form
259 * @param request
260 * @param response
261 * @return
262 * @throws Exception
263 */
264 public ActionForward clearQty(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
265 LineItemReceivingForm lineItemReceivingForm = (LineItemReceivingForm) form;
266
267 LineItemReceivingDocument lineItemReceivingDocument = (LineItemReceivingDocument) lineItemReceivingForm.getDocument();
268
269 for(LineItemReceivingItem item : (List <LineItemReceivingItem>)lineItemReceivingDocument.getItems()){
270 item.setItemReceivedTotalQuantity(KualiDecimal.ZERO);
271 }
272
273 return mapping.findForward(KFSConstants.MAPPING_BASIC);
274 }
275
276 /**
277 * For each item, loads total order quantity minus prior received quantity into total received quantity.
278 *
279 * @param mapping
280 * @param form
281 * @param request
282 * @param response
283 * @return
284 * @throws Exception
285 */
286 public ActionForward loadQty(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
287 LineItemReceivingForm lineItemReceivingForm = (LineItemReceivingForm) form;
288
289 LineItemReceivingDocument lineItemReceivingDocument = (LineItemReceivingDocument) lineItemReceivingForm.getDocument();
290
291 for(LineItemReceivingItem item : (List <LineItemReceivingItem>)lineItemReceivingDocument.getItems()){
292 if (item.isOrderedItem()){
293 if( item.getItemOrderedQuantity().subtract(item.getItemReceivedPriorQuantity()).isGreaterEqual(KualiDecimal.ZERO) ){
294 item.setItemReceivedTotalQuantity( item.getItemOrderedQuantity().subtract(item.getItemReceivedPriorQuantity()) );
295 }else{
296 item.setItemReceivedTotalQuantity(KualiDecimal.ZERO);
297 }
298 }
299 }
300
301 return mapping.findForward(KFSConstants.MAPPING_BASIC);
302 }
303
304 }