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 static org.kuali.kfs.sys.KFSKeyConstants.ERROR_ZERO_AMOUNT;
019    
020    import java.util.ArrayList;
021    import java.util.Collection;
022    import java.util.Collections;
023    import java.util.HashMap;
024    import java.util.HashSet;
025    import java.util.Iterator;
026    import java.util.List;
027    import java.util.Map;
028    import java.util.Properties;
029    import java.util.Set;
030    
031    import javax.servlet.http.HttpServletRequest;
032    import javax.servlet.http.HttpServletResponse;
033    
034    import org.apache.commons.lang.StringUtils;
035    import org.apache.struts.action.ActionForm;
036    import org.apache.struts.action.ActionForward;
037    import org.apache.struts.action.ActionMapping;
038    import org.kuali.kfs.module.ld.LaborConstants;
039    import org.kuali.kfs.module.ld.businessobject.ExpenseTransferAccountingLine;
040    import org.kuali.kfs.module.ld.businessobject.ExpenseTransferSourceAccountingLine;
041    import org.kuali.kfs.module.ld.businessobject.ExpenseTransferTargetAccountingLine;
042    import org.kuali.kfs.module.ld.businessobject.LaborAccountingLineOverride;
043    import org.kuali.kfs.module.ld.businessobject.LedgerBalance;
044    import org.kuali.kfs.module.ld.document.LaborExpenseTransferDocumentBase;
045    import org.kuali.kfs.sys.KFSConstants;
046    import org.kuali.kfs.sys.KFSKeyConstants;
047    import org.kuali.kfs.sys.KFSPropertyConstants;
048    import org.kuali.kfs.sys.businessobject.AccountingLine;
049    import org.kuali.kfs.sys.businessobject.AccountingLineOverride;
050    import org.kuali.kfs.sys.businessobject.SourceAccountingLine;
051    import org.kuali.kfs.sys.context.SpringContext;
052    import org.kuali.kfs.sys.document.AccountingDocument;
053    import org.kuali.kfs.sys.document.validation.event.AddAccountingLineEvent;
054    import org.kuali.kfs.sys.service.SegmentedLookupResultsService;
055    import org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase;
056    import org.kuali.rice.kew.exception.WorkflowException;
057    import org.kuali.rice.kns.bo.PersistableBusinessObject;
058    import org.kuali.rice.kns.document.TransactionalDocument;
059    import org.kuali.rice.kns.rule.event.KualiDocumentEventBase;
060    import org.kuali.rice.kns.service.KualiRuleService;
061    import org.kuali.rice.kns.service.PersistenceService;
062    import org.kuali.rice.kns.util.GlobalVariables;
063    import org.kuali.rice.kns.util.KNSConstants;
064    import org.kuali.rice.kns.util.KualiDecimal;
065    import org.kuali.rice.kns.util.UrlFactory;
066    import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
067    import org.kuali.rice.kns.web.struts.form.KualiForm;
068    
069    /**
070     * Base Struts Action class for Benefit Expense Transfer Document.
071     */
072    public class ExpenseTransferDocumentActionBase extends KualiAccountingDocumentActionBase {
073        protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ExpenseTransferDocumentActionBase.class);
074    
075        /**
076         * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#performBalanceInquiryForSourceLine(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
077         */
078        @Override
079        public ActionForward performBalanceInquiryForSourceLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
080            ExpenseTransferAccountingLine line = (ExpenseTransferAccountingLine)this.getSourceAccountingLine(form, request);        
081            line.setPostingYear(line.getPayrollEndDateFiscalYear());
082            
083            return performBalanceInquiryForAccountingLine(mapping, form, request, line);
084        }
085    
086        /**
087         * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#performBalanceInquiryForTargetLine(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
088         */
089        @Override
090        public ActionForward performBalanceInquiryForTargetLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
091            ExpenseTransferAccountingLine line = (ExpenseTransferAccountingLine)this.getTargetAccountingLine(form, request);        
092            line.setPostingYear(line.getPayrollEndDateFiscalYear());
093            
094            return performBalanceInquiryForAccountingLine(mapping, form, request, line);
095        }
096    
097        /**
098         * Takes care of storing the action form in the user session and forwarding to the balance inquiry lookup action.
099         * 
100         * @param mapping
101         * @param form
102         * @param request
103         * @param response
104         * @return ActionForward
105         * @throws Exception
106         */
107        public ActionForward performBalanceInquiryLookup(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
108            ExpenseTransferDocumentFormBase financialDocumentForm = (ExpenseTransferDocumentFormBase) form;
109            
110            // when we return from the lookup, our next request's method to call is going to be refresh
111            financialDocumentForm.registerEditableProperty(KNSConstants.DISPATCH_REQUEST_PARAMETER);
112            
113            TransactionalDocument document = financialDocumentForm.getTransactionalDocument();
114    
115            String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
116    
117            // parse out the important strings from our methodToCall parameter
118            String fullParameter = (String) request.getAttribute(KFSConstants.METHOD_TO_CALL_ATTRIBUTE);
119    
120            // parse out business object class name for lookup
121            String boClassName = StringUtils.substringBetween(fullParameter, KFSConstants.METHOD_TO_CALL_BOPARM_LEFT_DEL, KFSConstants.METHOD_TO_CALL_BOPARM_RIGHT_DEL);
122            if (StringUtils.isBlank(boClassName)) {
123                throw new RuntimeException("Illegal call to perform lookup, no business object class name specified.");
124            }
125    
126            // build the parameters for the lookup url
127            Properties parameters = new Properties();
128            String conversionFields = StringUtils.substringBetween(fullParameter, KFSConstants.METHOD_TO_CALL_PARM1_LEFT_DEL, KFSConstants.METHOD_TO_CALL_PARM1_RIGHT_DEL);
129            if (StringUtils.isNotBlank(conversionFields)) {
130                parameters.put(KFSConstants.CONVERSION_FIELDS_PARAMETER, conversionFields);
131            }
132    
133            // pass values from form that should be pre-populated on lookup search
134            String parameterFields = StringUtils.substringBetween(fullParameter, KFSConstants.METHOD_TO_CALL_PARM2_LEFT_DEL, KFSConstants.METHOD_TO_CALL_PARM2_RIGHT_DEL);
135            if (StringUtils.isNotBlank(parameterFields)) {
136                String[] lookupParams = parameterFields.split(KFSConstants.FIELD_CONVERSIONS_SEPERATOR);
137    
138                for (int i = 0; i < lookupParams.length; i++) {
139                    String[] keyValue = lookupParams[i].split(KFSConstants.FIELD_CONVERSION_PAIR_SEPERATOR);
140    
141                    // hard-coded passed value
142                    if (StringUtils.contains(keyValue[0], "'")) {
143                        parameters.put(keyValue[1], StringUtils.replace(keyValue[0], "'", ""));
144                    }
145                    // passed value should come from property
146                    else if (StringUtils.isNotBlank(request.getParameter(keyValue[0]))) {
147                        parameters.put(keyValue[1], request.getParameter(keyValue[0]));
148                    }
149                }
150            }
151    
152            // grab whether or not the "return value" link should be hidden or not
153            String hideReturnLink = StringUtils.substringBetween(fullParameter, KFSConstants.METHOD_TO_CALL_PARM3_LEFT_DEL, KFSConstants.METHOD_TO_CALL_PARM3_RIGHT_DEL);
154            if (StringUtils.isNotBlank(hideReturnLink)) {
155                parameters.put(KFSConstants.HIDE_LOOKUP_RETURN_LINK, hideReturnLink);
156            }
157    
158            // anchor, if it exists
159            if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) {
160                parameters.put(KFSConstants.LOOKUP_ANCHOR, ((KualiForm) form).getAnchor());
161            }
162    
163            // determine what the action path is
164            String actionPath = StringUtils.substringBetween(fullParameter, KFSConstants.METHOD_TO_CALL_PARM4_LEFT_DEL, KFSConstants.METHOD_TO_CALL_PARM4_RIGHT_DEL);
165            if (StringUtils.isBlank(actionPath)) {
166                throw new IllegalStateException("The \"actionPath\" attribute is an expected parameter for the <kul:balanceInquiryLookup> tag - it " + "should never be blank.");
167            }
168    
169            // now add required parameters
170            parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, "search");
171            parameters.put(KFSConstants.DOC_FORM_KEY, GlobalVariables.getUserSession().addObject(form));
172            parameters.put(KFSConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, boClassName);
173            parameters.put(KFSConstants.RETURN_LOCATION_PARAMETER, basePath + mapping.getPath() + ".do");
174            //parameters.put(GeneralLedgerConstants.LookupableBeanKeys.SEGMENTED_LOOKUP_FLAG_NAME, Boolean.TRUE.toString());
175    
176            String lookupUrl = UrlFactory.parameterizeUrl(basePath + "/" + actionPath, parameters);
177    
178            return new ActionForward(lookupUrl, true);
179        }
180    
181        /**
182         * Populates the lines of the ST or BT document from a balance lookup. First, the data must be retrieved based on the selected
183         * ids persisted from the framework. The basic steps are: 1) Retrieve selected (row) ids that were persisted 2) Each id has
184         * form: {db object id}.{period name}.{line amount} 3) Retrieve the balance records associated with the object ids 4)Build an
185         * accounting line from the retrieved balance record, using parsed period name as the pay period, and parsed amount as the new
186         * line amount. 5) Call insertAccountingLine
187         * 
188         * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#refresh(ActionMapping, ActionForm, HttpServletRequest,
189         *      HttpServletResponse)
190         */
191        @Override
192        public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
193            super.refresh(mapping, form, request, response);
194    
195            ExpenseTransferDocumentFormBase expenseTransferDocumentForm = (ExpenseTransferDocumentFormBase) form;
196    
197            Collection<PersistableBusinessObject> rawValues = null;
198            Map<String, Set<String>> segmentedSelection = new HashMap<String, Set<String>>();
199    
200            if (StringUtils.equals(KFSConstants.MULTIPLE_VALUE, expenseTransferDocumentForm.getRefreshCaller())) {
201                String lookupResultsSequenceNumber = expenseTransferDocumentForm.getLookupResultsSequenceNumber();
202    
203                if (StringUtils.isNotBlank(lookupResultsSequenceNumber)) {
204                    // actually returning from a multiple value lookup
205                    Set<String> selectedIds = getSegmentedLookupResultsService().retrieveSetOfSelectedObjectIds(lookupResultsSequenceNumber, GlobalVariables.getUserSession().getPerson().getPrincipalId());
206                    for (String selectedId : selectedIds) {
207                        String selectedObjId = StringUtils.substringBefore(selectedId, ".");
208                        String selectedMonthData = StringUtils.substringAfter(selectedId, ".");
209    
210                        if (!segmentedSelection.containsKey(selectedObjId)) {
211                            segmentedSelection.put(selectedObjId, new HashSet<String>());
212                        }
213                        segmentedSelection.get(selectedObjId).add(selectedMonthData);
214                    }
215    
216                    LOG.debug("Asking segmentation service for object ids " + segmentedSelection.keySet());
217                    rawValues = getSegmentedLookupResultsService().retrieveSelectedResultBOs(lookupResultsSequenceNumber, segmentedSelection.keySet(), LedgerBalance.class, GlobalVariables.getUserSession().getPerson().getPrincipalId());
218                }
219    
220                if (rawValues != null) {
221                    boolean isFirstBalance = true;
222                    for (PersistableBusinessObject bo : rawValues) {
223    
224                        // reset the form with the first leadge balance
225                        if (isFirstBalance) {
226                            resetLookupFields(expenseTransferDocumentForm, (LedgerBalance) bo);
227                            isFirstBalance = false;
228                        }
229    
230                        for (String selectedMonthData : segmentedSelection.get(bo.getObjectId())) {
231                            String selectedPeriodName = StringUtils.substringBefore(selectedMonthData, ".");
232                            String selectedPeriodAmount = StringUtils.substringAfter(selectedMonthData, ".");
233    
234                            if (LaborConstants.periodCodeMapping.containsKey(selectedPeriodName)) {
235                                String periodCode = LaborConstants.periodCodeMapping.get(selectedPeriodName);
236                                ExpenseTransferAccountingLine line = (ExpenseTransferAccountingLine) expenseTransferDocumentForm.getFinancialDocument().getSourceAccountingLineClass().newInstance();
237                                LaborExpenseTransferDocumentBase financialDocument = (LaborExpenseTransferDocumentBase) expenseTransferDocumentForm.getDocument();
238    
239                                try {
240                                    KualiDecimal lineAmount = (new KualiDecimal(selectedPeriodAmount)).divide(new KualiDecimal(100));
241    
242                                    // Notice that user tried to import an accounting line which has Zero amount
243                                    if (KualiDecimal.ZERO.compareTo(lineAmount) == 0) {
244                                        GlobalVariables.getMessageMap().putError(KFSPropertyConstants.SOURCE_ACCOUNTING_LINES, ERROR_ZERO_AMOUNT, "an accounting line");
245                                    }
246                                    else {
247                                        buildAccountingLineFromLedgerBalance((LedgerBalance) bo, line, lineAmount, periodCode);
248    
249                                        // SpringContext.getBean(KualiRuleService.class).applyRules(new
250                                        // AddAccountingLineEvent(KFSConstants.NEW_SOURCE_ACCT_LINE_PROPERTY_NAME, financialDocument,
251                                        // line));
252                                        SpringContext.getBean(PersistenceService.class).retrieveNonKeyFields(line);
253    
254                                        insertAccountingLine(true, expenseTransferDocumentForm, line);
255                                        updateAccountOverrideCode(line);
256                                        processAccountingLineOverrides(line);
257                                    }
258                                }
259                                catch (Exception e) {
260                                    // No way to recover gracefully, so throw it back as a RuntimeException
261                                    throw new RuntimeException(e);
262                                }
263                            }
264                        }
265                    }
266    
267                    Collections.sort((List<Comparable>) expenseTransferDocumentForm.getFinancialDocument().getSourceAccountingLines());
268                }
269            }
270    
271            return mapping.findForward(KFSConstants.MAPPING_BASIC);
272        }
273    
274        /**
275         * Overload the method in order to have balance importing section be populated with the last search criteria
276         * 
277         * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#loadDocument(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase)
278         */
279        @Override
280        protected void loadDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException {
281            super.loadDocument(kualiDocumentFormBase);
282            ExpenseTransferDocumentFormBase expenseTransferDocumentForm = (ExpenseTransferDocumentFormBase) kualiDocumentFormBase;
283            expenseTransferDocumentForm.populateSearchFields();
284        }
285    
286        /**
287         * This method copies all accounting lines from financial document form if they pass validation rules
288         * 
289         * @param mapping
290         * @param form
291         * @param request
292         * @param response
293         * @return
294         * @throws Exception
295         */
296        public ActionForward copyAllAccountingLines(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
297            ExpenseTransferDocumentFormBase financialDocumentForm = (ExpenseTransferDocumentFormBase) form;
298            for (Object line : financialDocumentForm.getFinancialDocument().getSourceAccountingLines()) {
299                ExpenseTransferAccountingLine to = (ExpenseTransferAccountingLine) financialDocumentForm.getFinancialDocument().getTargetAccountingLineClass().newInstance();
300                copyAccountingLine((ExpenseTransferAccountingLine) line, to);
301    
302                boolean rulePassed = runRule(new AddAccountingLineEvent(KFSConstants.NEW_TARGET_ACCT_LINE_PROPERTY_NAME, financialDocumentForm.getDocument(), to));
303    
304                // if the rule evaluation passed, let's add it
305                if (rulePassed) {
306                    // add accountingLine
307                    SpringContext.getBean(PersistenceService.class).retrieveNonKeyFields(line);
308                    insertAccountingLine(false, financialDocumentForm, to);
309                }
310                processAccountingLineOverrides(to);
311            }
312            return mapping.findForward(KFSConstants.MAPPING_BASIC);
313        }
314    
315        /**
316         * Delete all source accounting lines
317         * 
318         * @param mapping
319         * @param form
320         * @param request
321         * @param response
322         * @return ActionMapping
323         * @throws Exception
324         */
325        public ActionForward deleteAllSourceAccountingLines(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
326            ExpenseTransferDocumentFormBase financialDocumentForm = (ExpenseTransferDocumentFormBase) form;
327            financialDocumentForm.getFinancialDocument().setSourceAccountingLines(new ArrayList());
328    
329            return mapping.findForward(KFSConstants.MAPPING_BASIC);
330        }
331    
332        /**
333         * Delete all target accounting lines
334         * 
335         * @param mapping
336         * @param form
337         * @param request
338         * @param response
339         * @return ActionMapping
340         * @throws Exception
341         */
342        public ActionForward deleteAllTargetAccountingLines(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
343            ExpenseTransferDocumentFormBase financialDocumentForm = (ExpenseTransferDocumentFormBase) form;
344            financialDocumentForm.getFinancialDocument().setTargetAccountingLines(new ArrayList());
345    
346            return mapping.findForward(KFSConstants.MAPPING_BASIC);
347        }
348    
349    
350        /**
351         * Copy a single accounting line
352         * 
353         * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#copyAccountingLine(ActionMapping, ActionForm,
354         *      HttpServletRequest, HttpServletResponse)
355         */
356        public ActionForward copyAccountingLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
357            ExpenseTransferDocumentFormBase financialDocumentForm = (ExpenseTransferDocumentFormBase) form;
358            LaborExpenseTransferDocumentBase financialDocument = (LaborExpenseTransferDocumentBase) financialDocumentForm.getDocument();
359    
360            int index = getSelectedLine(request);
361    
362            ExpenseTransferAccountingLine line = (ExpenseTransferAccountingLine) financialDocumentForm.getFinancialDocument().getTargetAccountingLineClass().newInstance();
363            copyAccountingLine((ExpenseTransferAccountingLine) financialDocument.getSourceAccountingLine(index), line);
364    
365            boolean rulePassed = runRule(new AddAccountingLineEvent(KFSConstants.NEW_TARGET_ACCT_LINE_PROPERTY_NAME, financialDocumentForm.getDocument(), line));
366            // if the rule evaluation passed, let's add it
367            if (rulePassed) {
368                // add accountingLine
369                SpringContext.getBean(PersistenceService.class).retrieveNonKeyFields(line);
370                insertAccountingLine(false, financialDocumentForm, line);
371            }
372            processAccountingLineOverrides(line);
373    
374            return mapping.findForward(KFSConstants.MAPPING_BASIC);
375        }
376    
377        /**
378         * Reset the lookup fields in the given expense transfer form with the given ledger balance
379         * 
380         * @param expenseTransferDocumentForm the given expense transfer form
381         * @param the given ledger balance
382         */
383        protected void resetLookupFields(ExpenseTransferDocumentFormBase expenseTransferDocumentForm, LedgerBalance balance) {
384            expenseTransferDocumentForm.setUniversityFiscalYear(balance.getUniversityFiscalYear());
385        }
386    
387        /**
388         * Copies content from one accounting line to the other. Ignores Source or Target information.
389         * 
390         * @param source line to copy from
391         * @param target new line to copy data to
392         */
393        protected void copyAccountingLine(ExpenseTransferAccountingLine source, ExpenseTransferAccountingLine target) {
394            target.setChartOfAccountsCode(source.getChartOfAccountsCode());
395            target.setAccountNumber(source.getAccountNumber());
396            target.setSubAccountNumber(source.getSubAccountNumber());
397            target.setPostingYear(source.getPostingYear());
398            target.setPayrollEndDateFiscalYear(source.getPayrollEndDateFiscalYear());
399            target.setFinancialObjectCode(source.getFinancialObjectCode());
400            target.setFinancialSubObjectCode(source.getFinancialSubObjectCode());
401            target.setBalanceTypeCode(source.getBalanceTypeCode());
402            target.setPositionNumber(source.getPositionNumber());
403            target.setAmount(source.getAmount());
404            target.setEmplid(source.getEmplid());
405            target.setPayrollEndDateFiscalPeriodCode(source.getPayrollEndDateFiscalPeriodCode());
406            target.setOverrideCode(source.getOverrideCode());
407            target.setPayrollTotalHours(source.getPayrollTotalHours());
408        }
409    
410        /**
411         * Translates <code>{@link LedgerBalance}</code> data into an <code>{@link ExpenseTransferAccountingLine}</code>
412         * 
413         * @param bo <code>{@link LedgerBalance}</code> instance
414         * @param line <code>{@link ExpenseTransferAccountingLine}</code> to copy data to
415         */
416        protected void buildAccountingLineFromLedgerBalance(LedgerBalance ledgerBalance, ExpenseTransferAccountingLine line, KualiDecimal amount, String periodCode) {
417            line.setChartOfAccountsCode(ledgerBalance.getChartOfAccountsCode());
418            line.setAccountNumber(ledgerBalance.getAccountNumber());
419    
420            if (!KFSConstants.getDashSubAccountNumber().equals(ledgerBalance.getSubAccountNumber())) {
421                line.setSubAccountNumber(ledgerBalance.getSubAccountNumber());
422            }
423    
424            line.setPostingYear(ledgerBalance.getUniversityFiscalYear());
425            line.setPayrollEndDateFiscalYear(ledgerBalance.getUniversityFiscalYear());
426            line.setFinancialObjectCode(ledgerBalance.getFinancialObjectCode());
427    
428            if (!KFSConstants.getDashFinancialSubObjectCode().equals(ledgerBalance.getFinancialSubObjectCode())) {
429                line.setFinancialSubObjectCode(ledgerBalance.getFinancialSubObjectCode());
430            }
431    
432            line.setBalanceTypeCode(ledgerBalance.getFinancialBalanceTypeCode());
433            line.setPositionNumber(ledgerBalance.getPositionNumber());
434            line.setAmount(amount);
435            line.setEmplid(ledgerBalance.getEmplid());
436            line.setPayrollEndDateFiscalPeriodCode(periodCode);
437        }
438    
439        /**
440         * Processes accounting line overrides for output to JSP
441         * 
442         * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#processAccountingLineOverrides(java.util.List)
443         */
444        @Override
445        protected void processAccountingLineOverrides(List accountingLines) {
446            if (!accountingLines.isEmpty()) {
447                SpringContext.getBean(PersistenceService.class).retrieveReferenceObjects(accountingLines, AccountingLineOverride.REFRESH_FIELDS);
448    
449                for (Iterator i = accountingLines.iterator(); i.hasNext();) {
450                    AccountingLine line = (AccountingLine) i.next();
451                    LaborAccountingLineOverride.processForOutput(line);
452                }
453            }
454        }
455    
456        /**
457         * Clear all overrides that are not needed.
458         * 
459         * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#clearOverridesThatBecameUnneeded(org.kuali.kfs.sys.businessobject.AccountingLine)
460         */
461        @Override
462        protected void clearOverridesThatBecameUnneeded(AccountingLine formLine) {
463            AccountingLineOverride currentlyNeeded = LaborAccountingLineOverride.determineNeededOverrides(formLine);
464            AccountingLineOverride currentOverride = AccountingLineOverride.valueOf(formLine.getOverrideCode());
465            if (!currentOverride.isValidMask(currentlyNeeded)) {
466                // todo: handle unsupported combinations of overrides (not a problem until we allow certain multiple overrides)
467            }
468            formLine.setOverrideCode(currentOverride.mask(currentlyNeeded).getCode());
469        }
470    
471        /**
472         * For given accounting line, set the corresponding override code
473         * 
474         * @param line accounting line
475         */
476        protected void updateAccountOverrideCode(ExpenseTransferAccountingLine line) {
477            AccountingLineOverride override = LaborAccountingLineOverride.determineNeededOverrides(line);
478            line.setOverrideCode(override.getCode());
479        }
480    
481        /**
482         * Executes for the given event. This is more of a convenience method.
483         * 
484         * @param event to run the rules for
485         * @return true if rule passes
486         */
487        protected boolean runRule(KualiDocumentEventBase event) {
488            // check any business rules
489    
490            boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(event);
491            return rulePassed;
492        }
493    
494        /**
495         * Get the BO class name of the set of lookup results
496         * 
497         * @param expenseTransferDocumentForm the Struts form for expense transfer document
498         * @return the BO class name of the set of lookup results
499         */
500        protected String getLookupResultsBOClassName(ExpenseTransferDocumentFormBase expenseTransferDocumentForm) {
501            return expenseTransferDocumentForm.getLookupResultsBOClassName();
502        }
503    
504        /**
505         * @return SegmentedLookupResultsService
506         */
507        protected SegmentedLookupResultsService getSegmentedLookupResultsService() {
508            return SpringContext.getBean(SegmentedLookupResultsService.class);
509        }
510    }
511