001/*
002 * Copyright 2008 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.module.purap.document.web.struts;
017
018import org.apache.struts.action.ActionForm;
019import org.apache.struts.action.ActionForward;
020import org.apache.struts.action.ActionMapping;
021import org.kuali.ole.module.purap.PurapConstants;
022import org.kuali.ole.module.purap.PurapConstants.CorrectionReceivingDocumentStrings;
023import org.kuali.ole.module.purap.PurapConstants.PREQDocumentsStrings;
024import org.kuali.ole.module.purap.PurapKeyConstants;
025import org.kuali.ole.module.purap.PurapPropertyConstants;
026import org.kuali.ole.module.purap.businessobject.LineItemReceivingItem;
027import org.kuali.ole.module.purap.document.LineItemReceivingDocument;
028import org.kuali.ole.module.purap.document.PurchaseOrderDocument;
029import org.kuali.ole.module.purap.document.ReceivingDocument;
030import org.kuali.ole.module.purap.document.service.PurchaseOrderService;
031import org.kuali.ole.module.purap.document.service.ReceivingService;
032import org.kuali.ole.module.purap.document.validation.event.AddReceivingItemEvent;
033import org.kuali.ole.module.purap.util.ReceivingQuestionCallback;
034import org.kuali.ole.sys.OLEConstants;
035import org.kuali.ole.sys.OLEKeyConstants;
036import org.kuali.ole.sys.OLEPropertyConstants;
037import org.kuali.ole.sys.context.SpringContext;
038import org.kuali.rice.core.api.config.property.ConfigurationService;
039import org.kuali.rice.core.api.util.type.KualiDecimal;
040import org.kuali.rice.kew.api.exception.WorkflowException;
041import org.kuali.rice.kim.api.KimConstants;
042import org.kuali.rice.kns.question.ConfirmationQuestion;
043import org.kuali.rice.kns.service.DocumentHelperService;
044import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
045import org.kuali.rice.krad.service.KualiRuleService;
046import org.kuali.rice.krad.util.GlobalVariables;
047import org.kuali.rice.krad.util.KRADConstants;
048import org.kuali.rice.krad.util.ObjectUtils;
049import org.kuali.rice.krad.util.UrlFactory;
050
051import javax.servlet.http.HttpServletRequest;
052import javax.servlet.http.HttpServletResponse;
053import java.util.HashMap;
054import java.util.List;
055import java.util.Properties;
056
057public class LineItemReceivingAction extends ReceivingBaseAction {
058
059    @Override
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(OLEPropertyConstants.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, OLEKeyConstants.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, OLEKeyConstants.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(OLEConstants.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, KRADConstants.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(OLEConstants.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(OLEConstants.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            @Override
152            public ReceivingDocument doPostQuestion(ReceivingDocument document, String noteText) throws Exception {
153                //mark question completed
154                this.setQuestionComplete(true);
155                this.setCorrectionDocumentCreationNoteText(noteText);
156                return document;
157            }
158
159            @Override
160            public boolean isQuestionComplete() {
161                return this.questionComplete;
162            }
163
164            @Override
165            public void setQuestionComplete(boolean questionComplete) {
166                this.questionComplete = questionComplete;
167            }
168
169            @Override
170            public String getCorrectionDocumentCreationNoteText() {
171                return correctionDocumentnoteText;
172            }
173
174            @Override
175            public void setCorrectionDocumentCreationNoteText(String noteText) {
176                correctionDocumentnoteText = noteText;
177            }
178        };
179
180        //ask question
181        ActionForward forward = askQuestionWithInput(mapping, form, request, response, CorrectionReceivingDocumentStrings.NOTE_QUESTION, CorrectionReceivingDocumentStrings.NOTE_PREFIX, operation, PurapKeyConstants.MESSAGE_RECEIVING_CORRECTION_NOTE, callback);
182
183        //if question asked is complete, then route
184        if (callback.isQuestionComplete()) {
185
186            //set parameters
187            String basePath = getApplicationBaseUrl();
188            String methodToCallDocHandler = "docHandler";
189            String methodToCallReceivingCorrection = "initiate";
190
191            Properties parameters = new Properties();
192            parameters.put(OLEConstants.DISPATCH_REQUEST_PARAMETER, methodToCallDocHandler);
193            parameters.put(OLEConstants.PARAMETER_COMMAND, methodToCallReceivingCorrection);
194            parameters.put(OLEConstants.DOCUMENT_TYPE_NAME, "RCVC");
195            parameters.put("receivingLineDocId", document.getDocumentHeader().getDocumentNumber());
196            parameters.put(PurapConstants.CorrectionReceivingDocumentStrings.CORRECTION_RECEIVING_CREATION_NOTE_PARAMETER, callback.getCorrectionDocumentCreationNoteText());
197
198            //create url
199            String receivingCorrectionUrl = UrlFactory.parameterizeUrl(basePath + "/" + "purapCorrectionReceiving.do", parameters);
200            //create forward
201            forward = new ActionForward(receivingCorrectionUrl, true);
202        }
203
204        return forward;
205
206    }
207
208    public ActionForward clearInitFields(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
209        LineItemReceivingForm rlForm = (LineItemReceivingForm) form;
210        LineItemReceivingDocument rlDocument = (LineItemReceivingDocument) rlForm.getDocument();
211        rlDocument.clearInitFields(rlForm.isFromPurchaseOrder());
212
213        return mapping.findForward(OLEConstants.MAPPING_BASIC);
214    }
215
216    protected ActionForward performDuplicateReceivingLineCheck(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, LineItemReceivingDocument lineItemReceivingDocument) throws Exception {
217        ActionForward forward = null;
218        HashMap<String, String> duplicateMessages = SpringContext.getBean(ReceivingService.class).receivingLineDuplicateMessages(lineItemReceivingDocument);
219        if (duplicateMessages != null && !duplicateMessages.isEmpty()) {
220            Object question = request.getParameter(OLEConstants.QUESTION_INST_ATTRIBUTE_NAME);
221            if (question == null) {
222
223                return this.performQuestionWithoutInput(mapping, form, request, response, PurapConstants.LineItemReceivingDocumentStrings.DUPLICATE_RECEIVING_LINE_QUESTION, duplicateMessages.get(PurapConstants.LineItemReceivingDocumentStrings.DUPLICATE_RECEIVING_LINE_QUESTION), OLEConstants.CONFIRMATION_QUESTION, OLEConstants.ROUTE_METHOD, "");
224            }
225
226            Object buttonClicked = request.getParameter(OLEConstants.QUESTION_CLICKED_BUTTON);
227            if ((PurapConstants.LineItemReceivingDocumentStrings.DUPLICATE_RECEIVING_LINE_QUESTION.equals(question)) && ConfirmationQuestion.NO.equals(buttonClicked)) {
228                forward = mapping.findForward(OLEConstants.MAPPING_BASIC);
229            }
230        }
231
232        return forward;
233    }
234
235    /**
236     * Add a new item to the document.
237     *
238     * @param mapping  An ActionMapping
239     * @param form     An ActionForm
240     * @param request  The HttpServletRequest
241     * @param response The HttpServletResponse
242     * @return An ActionForward
243     * @throws Exception
244     */
245    public ActionForward addItem(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
246        LineItemReceivingForm lineItemReceivingForm = (LineItemReceivingForm) form;
247        LineItemReceivingItem item = lineItemReceivingForm.getNewLineItemReceivingItemLine();
248        LineItemReceivingDocument lineItemReceivingDocument = (LineItemReceivingDocument) lineItemReceivingForm.getDocument();
249
250        boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new AddReceivingItemEvent(PurapPropertyConstants.NEW_LINE_ITEM_RECEIVING_ITEM_LINE, lineItemReceivingDocument, item));
251        if (rulePassed) {
252            lineItemReceivingForm.setHideAddUnorderedItem(true); // hide the add unordered item line once an item is added
253            item = lineItemReceivingForm.getAndResetNewReceivingItemLine();
254            lineItemReceivingDocument.addItem(item);
255            //TODO: we need to set the line number correctly to match up to PO
256        }
257
258        return mapping.findForward(OLEConstants.MAPPING_BASIC);
259    }
260
261    /**
262     * For each item, it's quantity received value is set to zero.
263     *
264     * @param mapping
265     * @param form
266     * @param request
267     * @param response
268     * @return
269     * @throws Exception
270     */
271    public ActionForward clearQty(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
272        LineItemReceivingForm lineItemReceivingForm = (LineItemReceivingForm) form;
273
274        LineItemReceivingDocument lineItemReceivingDocument = (LineItemReceivingDocument) lineItemReceivingForm.getDocument();
275
276        for (LineItemReceivingItem item : (List<LineItemReceivingItem>) lineItemReceivingDocument.getItems()) {
277            item.setItemReceivedTotalQuantity(KualiDecimal.ZERO);
278        }
279
280        return mapping.findForward(OLEConstants.MAPPING_BASIC);
281    }
282
283    /**
284     * For each item, loads total order quantity minus prior received quantity into total received quantity.
285     *
286     * @param mapping
287     * @param form
288     * @param request
289     * @param response
290     * @return
291     * @throws Exception
292     */
293    public ActionForward loadQty(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
294        LineItemReceivingForm lineItemReceivingForm = (LineItemReceivingForm) form;
295
296        LineItemReceivingDocument lineItemReceivingDocument = (LineItemReceivingDocument) lineItemReceivingForm.getDocument();
297
298        for (LineItemReceivingItem item : (List<LineItemReceivingItem>) lineItemReceivingDocument.getItems()) {
299            if (item.isOrderedItem()) {
300                if (item.getItemOrderedQuantity().subtract(item.getItemReceivedPriorQuantity()).isGreaterEqual(KualiDecimal.ZERO)) {
301                    item.setItemReceivedTotalQuantity(item.getItemOrderedQuantity().subtract(item.getItemReceivedPriorQuantity()));
302                } else {
303                    item.setItemReceivedTotalQuantity(KualiDecimal.ZERO);
304                }
305            }
306        }
307
308        return mapping.findForward(OLEConstants.MAPPING_BASIC);
309    }
310
311    /**
312     * Gives a warning before showing the add new unordered line item; if the user confirms the action, proceeds;
313     * otherwise cancels the action and returns to the current LineItemReceivingDocument.
314     *
315     * @param mapping  An ActionMapping
316     * @param form     An ActionForm
317     * @param request  The HttpServletRequest
318     * @param response The HttpServletResponse
319     * @return An ActionForward
320     * @throws Exception
321     */
322    public ActionForward showAddUnorderedItem(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
323        LineItemReceivingForm lineItemReceivingForm = (LineItemReceivingForm) form;
324
325        boolean shouldGiveWarning = lineItemReceivingForm.shouldGiveAddUnorderedItemWarning();
326        if (!shouldGiveWarning) {
327            lineItemReceivingForm.setHideAddUnorderedItem(false);
328            return mapping.findForward(OLEConstants.MAPPING_BASIC);
329        }
330
331        String msgkey = PurapKeyConstants.WARNING_RECEIVING_LINEITEM_ADD_UNORDERED;
332        String msgtxt = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(msgkey);
333        Object question = request.getParameter(OLEConstants.QUESTION_INST_ATTRIBUTE_NAME);
334
335        if (question == null) {
336            return performQuestionWithoutInput(mapping, form, request, response, msgkey, msgtxt, OLEConstants.CONFIRMATION_QUESTION, "showAddUnorderedItem", "");
337        }
338
339        Object buttonClicked = request.getParameter(OLEConstants.QUESTION_CLICKED_BUTTON);
340        if ((msgkey.equals(question)) && ConfirmationQuestion.YES.equals(buttonClicked)) {
341            lineItemReceivingForm.setHideAddUnorderedItem(false);
342        }
343
344        return mapping.findForward(OLEConstants.MAPPING_BASIC);
345    }
346
347}