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.ld.document.web.struts;
017    
018    import java.text.MessageFormat;
019    
020    import javax.servlet.http.HttpServletRequest;
021    import javax.servlet.http.HttpServletResponse;
022    
023    import org.apache.struts.action.ActionForm;
024    import org.apache.struts.action.ActionForward;
025    import org.apache.struts.action.ActionMapping;
026    import org.kuali.kfs.module.ld.LaborConstants;
027    import org.kuali.kfs.module.ld.LaborKeyConstants;
028    import org.kuali.kfs.module.ld.businessobject.LedgerBalance;
029    import org.kuali.kfs.module.ld.document.SalaryExpenseTransferDocument;
030    import org.kuali.kfs.module.ld.document.web.struts.SalaryExpenseTransferForm;
031    import org.kuali.kfs.module.ld.document.service.SalaryTransferPeriodValidationService;
032    import org.kuali.kfs.sys.KFSConstants;
033    import org.kuali.kfs.sys.KFSPropertyConstants;
034    import org.kuali.kfs.sys.ObjectUtil;
035    import org.kuali.kfs.sys.context.SpringContext;
036    import org.kuali.rice.kns.document.authorization.TransactionalDocumentAuthorizer;
037    import org.kuali.rice.kns.question.ConfirmationQuestion;
038    import org.kuali.rice.kns.service.DocumentHelperService;
039    import org.kuali.rice.kns.service.KualiConfigurationService;
040    import org.kuali.rice.kns.service.ParameterService;
041    import org.kuali.rice.kns.util.ErrorMessage;
042    import org.kuali.rice.kns.util.GlobalVariables;
043    import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
044    /**
045     * Struts action class for Salary Expense Transfer Document. This class extends the parent FinancialSystemTransactionalDocumentActionBase
046     * class, which contains all common action methods. Since the SEP follows the basic transactional document pattern, there are no
047     * specific actions that it has to implement; however, this empty class is necessary for integrating into the framework.
048     */
049    public class SalaryExpenseTransferAction extends ExpenseTransferDocumentActionBase {
050        /**
051         * Resets lookup fields for salary expense transfer action
052         * 
053         * @see org.kuali.kfs.module.ld.document.web.struts.ExpenseTransferDocumentActionBase#resetLookupFields(org.kuali.kfs.module.ld.document.web.struts.ExpenseTransferDocumentFormBase,
054         *      org.kuali.kfs.module.ld.businessobject.LedgerBalance)
055         */
056        @Override
057        protected void resetLookupFields(ExpenseTransferDocumentFormBase expenseTransferDocumentForm, LedgerBalance balance) {
058            SalaryExpenseTransferForm expenseTransferForm = (SalaryExpenseTransferForm) expenseTransferDocumentForm;
059            expenseTransferForm.getSalaryExpenseTransferDocument().setEmplid(balance.getEmplid());
060            ObjectUtil.buildObject(expenseTransferForm, balance);
061        }
062    
063        /**
064         * If user is approving document, capture the object code balances for comparison in business rules on route
065         * 
066         * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#docHandler(org.apache.struts.action.ActionMapping,
067         *      org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
068         */
069        @Override
070        public ActionForward docHandler(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
071            ActionForward forward = super.docHandler(mapping, form, request, response);
072    
073            SalaryExpenseTransferDocument salaryExpenseDocument = (SalaryExpenseTransferDocument) ((KualiDocumentFormBase) form).getDocument();
074            if (salaryExpenseDocument.getDocumentHeader().getWorkflowDocument().isApprovalRequested()) {
075                salaryExpenseDocument.setApprovalObjectCodeBalances(salaryExpenseDocument.getUnbalancedObjectCodes());
076            }
077    
078            return forward;
079        }
080    
081        /**
082         * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#route(org.apache.struts.action.ActionMapping,
083         *      org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
084         */
085        @Override
086        public ActionForward route(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
087            ActionForward forward = doEffortCertificationValidation(mapping, form, request, response, KFSConstants.ROUTE_METHOD);
088            if (forward != null) {
089                return forward;
090            }
091    
092            return super.route(mapping, form, request, response);
093        }
094    
095        /**
096         * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#approve(org.apache.struts.action.ActionMapping,
097         *      org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
098         */
099        @Override
100        public ActionForward approve(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
101            ActionForward forward = doEffortCertificationValidation(mapping, form, request, response, KFSConstants.APPROVE_METHOD);
102            if (forward != null) {
103                return forward;
104            }
105    
106            return super.approve(mapping, form, request, response);
107        }
108    
109        /**
110         * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#blanketApprove(org.apache.struts.action.ActionMapping,
111         *      org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
112         */
113        @Override
114        public ActionForward blanketApprove(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
115            ActionForward forward = doEffortCertificationValidation(mapping, form, request, response, KFSConstants.BLANKET_APPROVE_METHOD);
116            if (forward != null) {
117                return forward;
118            }
119    
120            return super.blanketApprove(mapping, form, request, response);
121        }
122    
123        /**
124         * Calls service to verify the salary transfer does not conflict with effort certifications and handle any errors returned.
125         * 
126         * @return ActionForward which is null if everything was OK, the question redirect if errors found and user is admin, the basic
127         *         mapping (which goes back to document) if errors were found and the user is not admin and document is not enroute, or
128         *         finally redirect back to portal if document was disapproved due to errors
129         */
130        protected ActionForward doEffortCertificationValidation(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String caller) throws Exception {
131            SalaryExpenseTransferDocument salaryExpenseDocument = (SalaryExpenseTransferDocument) ((KualiDocumentFormBase) form).getDocument();
132    
133            // check sys parameter indicating if we should check effort certification rules
134            boolean doEffortValidation = SpringContext.getBean(ParameterService.class).getIndicatorParameter(SalaryExpenseTransferDocument.class, LaborConstants.SalaryExpenseTransfer.VALIDATE_AGAINST_EFFORT_PARM_NM);
135            if (!doEffortValidation) {
136                return null;
137            }
138    
139            // check if we are returning from a question, in which case we previously check effort and asked admin to confirm. If not,
140            // we need to perform validation.
141            String question = request.getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME);
142            if (question == null) { // question hasn't been asked
143                boolean transferValid = SpringContext.getBean(SalaryTransferPeriodValidationService.class).validateTransfers(salaryExpenseDocument);
144                if (!transferValid) {
145                    return handleEffortValidationErrors(mapping, form, request, response, caller, false);
146                }
147            }
148            else {
149                // check if admin wants to continue, or not in which case we return to document or cancel document (in enroute)
150                String buttonClicked = request.getParameter(KFSConstants.QUESTION_CLICKED_BUTTON);
151                if ((LaborConstants.SalaryExpenseTransfer.EFFORT_VALIDATION_OVERRIDE_QUESTION.equals(question)) && ConfirmationQuestion.NO.equals(buttonClicked)) {
152                    return handleEffortValidationErrors(mapping, form, request, response, caller, true);
153                }
154            }
155    
156            return null;
157        }
158    
159        /**
160         * If the user is an effort administrator ask if they want to override the errors (if not already asked). Otherwise if the
161         * document is enroute it will be disapproved or if being initiated just return to doc.
162         * 
163         * @return ActionForward which is question redirect, portal redirect, or basic mapping (back to doc)
164         * @throws Exception
165         */
166        protected ActionForward handleEffortValidationErrors(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String caller, boolean questionAsked) throws Exception {
167            SalaryExpenseTransferDocument salaryExpenseDocument = (SalaryExpenseTransferDocument) ((KualiDocumentFormBase) form).getDocument();
168            
169            TransactionalDocumentAuthorizer documentAuthorizer = (TransactionalDocumentAuthorizer) SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(salaryExpenseDocument);        
170            
171            boolean isAdmin = documentAuthorizer.isAuthorized(salaryExpenseDocument, LaborConstants.LABOR_MODULE_CODE, 
172                     LaborConstants.PermissionNames.OVERRIDE_TRANSFER_IMPACTING_EFFORT_CERTIFICATION, 
173                                      GlobalVariables.getUserSession().getPerson().getPrincipalId());
174            
175            if (isAdmin && !questionAsked) {
176                // error found, ask admin user if they want to override
177                KualiConfigurationService kualiConfigurationService = SpringContext.getBean(KualiConfigurationService.class);
178    
179                // build question text (contains error messages found)
180                String message = "";
181                if (GlobalVariables.getMessageMap().containsKey(KFSPropertyConstants.SOURCE_ACCOUNTING_LINES)) {
182                    for (Object errorMessage : GlobalVariables.getMessageMap().getMessages(KFSPropertyConstants.SOURCE_ACCOUNTING_LINES)) {
183                        String errorMsg = kualiConfigurationService.getPropertyString(((ErrorMessage) errorMessage).getErrorKey());
184                        message += MessageFormat.format(errorMsg, (Object[]) ((ErrorMessage) errorMessage).getMessageParameters());
185                    }
186                }
187                
188                if (GlobalVariables.getMessageMap().containsKey(KFSPropertyConstants.TARGET_ACCOUNTING_LINES)) {
189                    for (Object errorMessage : GlobalVariables.getMessageMap().getMessages(KFSPropertyConstants.TARGET_ACCOUNTING_LINES)) {
190                        String errorMsg = kualiConfigurationService.getPropertyString(((ErrorMessage) errorMessage).getErrorKey());
191                        message += MessageFormat.format(errorMsg, (Object[]) ((ErrorMessage) errorMessage).getMessageParameters());
192                    }
193                }
194                message += " " + kualiConfigurationService.getPropertyString(LaborKeyConstants.EFFORT_VALIDATION_OVERRIDE_MESSAGE);
195    
196                return this.performQuestionWithoutInput(mapping, form, request, response, LaborConstants.SalaryExpenseTransfer.EFFORT_VALIDATION_OVERRIDE_QUESTION, message, KFSConstants.CONFIRMATION_QUESTION, caller, "");
197            }
198    
199            // errors found, return to document if it is being initiated, or disapproved if enroute
200            if (salaryExpenseDocument.getDocumentHeader().getWorkflowDocument().stateIsEnroute()) {
201                SpringContext.getBean(SalaryTransferPeriodValidationService.class).disapproveSalaryExpenseDocument(salaryExpenseDocument);
202    
203                return returnToSender(request, mapping, (KualiDocumentFormBase) form);
204            }
205    
206            return mapping.findForward(KFSConstants.MAPPING_BASIC);
207        }
208    
209        /**
210         * Delete all source accounting lines
211         * 
212         * @param mapping
213         * @param form
214         * @param request
215         * @param response
216         * @return ActionMapping
217         * @throws Exception
218         */
219        @Override
220        public ActionForward deleteAllSourceAccountingLines(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
221            SalaryExpenseTransferForm financialDocumentForm = (SalaryExpenseTransferForm) form;
222            financialDocumentForm.getSalaryExpenseTransferDocument().setNextSourceLineNumber(KFSConstants.ONE.intValue());
223            
224            return super.deleteAllSourceAccountingLines(mapping, form, request, response);
225        }
226        
227        /**
228         * Delete all target accounting lines
229         * 
230         * @param mapping
231         * @param form
232         * @param request
233         * @param response
234         * @return ActionMapping
235         * @throws Exception
236         */
237        @Override
238        public ActionForward deleteAllTargetAccountingLines(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
239            SalaryExpenseTransferForm financialDocumentForm = (SalaryExpenseTransferForm) form;
240            financialDocumentForm.getSalaryExpenseTransferDocument().setNextTargetLineNumber(KFSConstants.ONE.intValue());
241            
242            return super.deleteAllTargetAccountingLines(mapping, form, request, response);
243        }
244    }
245