/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.module.tem.document.web.struts; import static org.kuali.kfs.module.tem.TemConstants.CERTIFICATION_STATEMENT_ATTRIBUTE; import static org.kuali.kfs.module.tem.TemConstants.EMPLOYEE_TEST_ATTRIBUTE; import static org.kuali.kfs.module.tem.TemConstants.SHOW_ACCOUNT_DISTRIBUTION_ATTRIBUTE; import static org.kuali.kfs.module.tem.TemConstants.TravelReimbursementParameters.DISPLAY_ACCOUNTING_DISTRIBUTION_TAB_IND; import static org.kuali.kfs.module.tem.TemPropertyConstants.NEW_EMERGENCY_CONTACT_LINE; import static org.kuali.kfs.sys.KFSPropertyConstants.FINANCIAL_OBJECT_CODE; import static org.kuali.kfs.sys.KFSPropertyConstants.NEW_SOURCE_LINE; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.kuali.kfs.module.purap.SingleConfirmationQuestion; import org.kuali.kfs.module.tem.TemConstants; import org.kuali.kfs.module.tem.TemConstants.TravelAuthorizationParameters; import org.kuali.kfs.module.tem.TemConstants.TravelAuthorizationStatusCodeKeys; import org.kuali.kfs.module.tem.TemConstants.TravelParameters; import org.kuali.kfs.module.tem.TemKeyConstants; import org.kuali.kfs.module.tem.TemParameterConstants; import org.kuali.kfs.module.tem.TemPropertyConstants; import org.kuali.kfs.module.tem.TemWorkflowConstants; import org.kuali.kfs.module.tem.businessobject.TemSourceAccountingLine; import org.kuali.kfs.module.tem.businessobject.TravelerDetailEmergencyContact; import org.kuali.kfs.module.tem.document.TravelAuthorizationAmendmentDocument; import org.kuali.kfs.module.tem.document.TravelAuthorizationDocument; import org.kuali.kfs.module.tem.document.TravelDocument; import org.kuali.kfs.module.tem.document.TravelDocumentBase; import org.kuali.kfs.module.tem.document.authorization.TravelAuthorizationAuthorizer; import org.kuali.kfs.module.tem.document.validation.event.AddEmergencyContactLineEvent; import org.kuali.kfs.module.tem.document.web.bean.TravelAuthorizationMvcWrapperBean; import org.kuali.kfs.sys.KFSConstants; import org.kuali.kfs.sys.KFSKeyConstants; import org.kuali.kfs.sys.businessobject.SourceAccountingLine; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.document.validation.event.AccountingDocumentSaveWithNoLedgerEntryGenerationEvent; import org.kuali.kfs.sys.document.validation.event.AddAccountingLineEvent; import org.kuali.kfs.sys.document.validation.event.DeleteAccountingLineEvent; import org.kuali.kfs.sys.web.struts.KualiAccountingDocumentFormBase; import org.kuali.rice.core.api.config.property.ConfigurationService; import org.kuali.rice.core.api.util.RiceConstants; import org.kuali.rice.core.api.util.type.KualiDecimal; import org.kuali.rice.kns.question.ConfirmationQuestion; import org.kuali.rice.kns.util.KNSGlobalVariables; import org.kuali.rice.kns.util.WebUtils; import org.kuali.rice.kns.web.struts.form.BlankFormFile; import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase; import org.kuali.rice.kns.web.struts.form.KualiForm; import org.kuali.rice.krad.bo.Note; import org.kuali.rice.krad.dao.DocumentDao; import org.kuali.rice.krad.document.Copyable; import org.kuali.rice.krad.document.Document; import org.kuali.rice.krad.exception.ValidationException; import org.kuali.rice.krad.service.DataDictionaryService; import org.kuali.rice.krad.service.DocumentService; import org.kuali.rice.krad.service.KualiRuleService; import org.kuali.rice.krad.service.PersistenceService; import org.kuali.rice.krad.util.GlobalVariables; import org.kuali.rice.krad.util.KRADConstants; import org.kuali.rice.krad.util.ObjectUtils; /** * Handles action events through the struts framework for the {@link TravelAuthorizationDocument} */ public class TravelAuthorizationAction extends TravelActionBase { public static Logger LOG = Logger.getLogger(TravelAuthorizationAction.class); public static final String DOCUMENT_ERROR_PREFIX = "document."; public static final String NEW_SOURCE_LINE_OBJECT_CODE = String.format("%s.%s", NEW_SOURCE_LINE, FINANCIAL_OBJECT_CODE); private DocumentDao documentDao; /** * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#execute(org.apache.struts.action.ActionMapping, * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TravelAuthorizationForm authForm = (TravelAuthorizationForm) form; // try pulling the transpo modes from the form or the request String[] transpoModes = request.getParameterValues("selectedTransportationModes"); final ActionForward retval = super.execute(mapping, form, request, response); TravelAuthorizationDocument travelAuthDocument = (TravelAuthorizationDocument) authForm.getDocument(); if (transpoModes != null) { authForm.setSelectedTransportationModes(Arrays.asList(transpoModes)); } else { authForm.setSelectedTransportationModes(authForm.getTravelAuthorizationDocument().getTransportationModeCodes()); } refreshTransportationModesAfterButtonAction(travelAuthDocument, authForm); // should we refresh the trip type, upon which so much depends? let's check and do so if we need to if (!StringUtils.isBlank(travelAuthDocument.getTripTypeCode())) { if (ObjectUtils.isNull(travelAuthDocument.getTripType()) || !StringUtils.equals(travelAuthDocument.getTripType().getCode(), travelAuthDocument.getTripTypeCode())) { travelAuthDocument.refreshReferenceObject(TemPropertyConstants.TRIP_TYPE); } } else { travelAuthDocument.setTripType(null); } if (travelAuthDocument.getTraveler() != null && travelAuthDocument.getTraveler().getPrincipalId() != null) { travelAuthDocument.getTraveler().setPrincipalName(getPersonService().getPerson(travelAuthDocument.getTraveler().getPrincipalId()).getPrincipalName()); } setButtonPermissions(authForm); String perDiemPercentage = getParameterService().getParameterValueAsString(TravelAuthorizationDocument.class, TravelAuthorizationParameters.FIRST_AND_LAST_DAY_PER_DIEM_PERCENTAGE); final String travelIdentifier = travelAuthDocument.getTravelDocumentIdentifier(); authForm.setPerDiemPercentage(perDiemPercentage); disablePerDiemExpenes(travelAuthDocument); if(ObjectUtils.isNotNull(travelAuthDocument.getActualExpenses())){ travelAuthDocument.enableExpenseTypeSpecificFields(travelAuthDocument.getActualExpenses()); } LOG.debug("Got "+ authForm.getRelatedDocuments().size()+ " related documents"); if (!isReturnFromObjectCodeLookup(authForm, request)) { getTravelEncumbranceService().updateEncumbranceObjectCode(travelAuthDocument, authForm.getNewSourceLine()); } getMessages(authForm); // update the list of related documents refreshRelatedDocuments(authForm); if (((TravelFormBase) form).getMethodToCall().equalsIgnoreCase(KFSConstants.DOC_HANDLER_METHOD) && travelAuthDocument.getPrimaryDestinationId() != null){ if (travelAuthDocument.getPrimaryDestinationId().intValue() == TemConstants.CUSTOM_PRIMARY_DESTINATION_ID){ travelAuthDocument.getPrimaryDestination().setPrimaryDestinationName(travelAuthDocument.getPrimaryDestinationName()); travelAuthDocument.getPrimaryDestination().setCounty(travelAuthDocument.getPrimaryDestinationCounty()); travelAuthDocument.getPrimaryDestination().getRegion().setRegionName(travelAuthDocument.getPrimaryDestinationCountryState()); } } request.setAttribute(CERTIFICATION_STATEMENT_ATTRIBUTE, getCertificationStatement(travelAuthDocument)); request.setAttribute(EMPLOYEE_TEST_ATTRIBUTE, isEmployee(travelAuthDocument.getTraveler())); // force recalculate if(!getCalculateIgnoreList().contains(authForm.getMethodToCall())){ recalculateTripDetailTotalOnly(mapping, form, request, response); } setupTravelAdvances(authForm); travelAuthDocument.propagateAdvanceInformationIfNeeded(); populateAnyMissingAdvanceAccountingLineObjectCodes(authForm); if (travelAuthDocument.getTravelAdvances() != null && !travelAuthDocument.getTravelAdvances().isEmpty()) { authForm.setShowTravelAdvancesForTrip(true); } setTabStateForEmergencyContacts(authForm); return retval; } /** * Decides whether to show the tab which allows the traveler to accept the rules with receiving a travel advance * @param form the form for the travel authorization */ private void setupTravelAdvances(TravelAuthorizationForm form) { TravelAuthorizationDocument document = form.getTravelAuthorizationDocument(); boolean waitingOnTraveler = document.getAppDocStatus().equals(TemConstants.TravelAuthorizationStatusCodeKeys.AWAIT_TRVLR); String initiator = document.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId(); String travelerID = ""; boolean showPolicy = false; if (document.getTraveler() != null){ travelerID = document.getTraveler().getPrincipalId(); if (travelerID != null){ //traveler must accept policy, if initiator is arranger, the traveler will have to accept later. showPolicy = initiator.equals(travelerID) || GlobalVariables.getUserSession().getPrincipalId().equals(travelerID); } else{ //Non-kim traveler, arranger accepts policy showPolicy = true; } } form.setWaitingOnTraveler(waitingOnTraveler); form.setShowPolicy(showPolicy); } /** * Extended to handle the overrides for the advances accounting lines * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#processAccountingLineOverrides(org.kuali.kfs.sys.web.struts.KualiAccountingDocumentFormBase) */ @Override protected void processAccountingLineOverrides(KualiAccountingDocumentFormBase transForm) { super.processAccountingLineOverrides(transForm); processAccountingLineOverrides(((TravelAuthorizationForm)transForm).getNewAdvanceAccountingLine()); if (transForm.hasDocumentId()) { TravelAuthorizationDocument authorizationDocument = (TravelAuthorizationDocument) transForm.getDocument(); if (!ObjectUtils.isNull(authorizationDocument.getAdvanceAccountingLines()) && !authorizationDocument.getAdvanceAccountingLines().isEmpty()) { processAccountingLineOverrides(authorizationDocument,authorizationDocument.getAdvanceAccountingLines()); } } } /** * If the parameter KFS-TEM / TravelAuthorization / TRAVEL_ADVANCE_OBJECT_CODE is set and some of the advance accounting lines do not have object codes set, fill the object codes in * @param form the form with the document to update */ protected void populateAnyMissingAdvanceAccountingLineObjectCodes(TravelAuthorizationForm form) { final String advanceAccountingLineObjectCode = getParameterService().getParameterValueAsString(TravelAuthorizationDocument.class, TemConstants.TravelAuthorizationParameters.TRAVEL_ADVANCE_OBJECT_CODE, KFSConstants.EMPTY_STRING); if (!StringUtils.isBlank(advanceAccountingLineObjectCode)) { final TravelAuthorizationDocument authorizationDocument = form.getTravelAuthorizationDocument(); if (authorizationDocument.getAdvanceAccountingLines() != null && !authorizationDocument.getAdvanceAccountingLines().isEmpty()) { for (TemSourceAccountingLine accountingLine : authorizationDocument.getAdvanceAccountingLines()) { if (StringUtils.isBlank(accountingLine.getFinancialObjectCode())) { accountingLine.setFinancialObjectCode(advanceAccountingLineObjectCode); } } } } } /** * This action executes an insert of an accounting line associated with an advance * @param mapping this is the mapping * @param form this is the form * @param request we have to assume this is a "request" of some sort * @param response is this used? for...something? * @return ActionForward we promise to return one of these things * @throws Exception 'cause sometimes bad things happen */ public ActionForward insertAdvanceAccountingLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TravelAuthorizationForm authorizationDocumentForm = (TravelAuthorizationForm) form; TemSourceAccountingLine line = authorizationDocumentForm.getNewAdvanceAccountingLine(); boolean rulePassed = true; // check any business rules rulePassed &= SpringContext.getBean(KualiRuleService.class).applyRules(new AddAccountingLineEvent(TemPropertyConstants.NEW_ADVANCE_ACCOUNTING_LINE, authorizationDocumentForm.getDocument(), line)); if (rulePassed) { SpringContext.getBean(PersistenceService.class).refreshAllNonUpdatingReferences(line); authorizationDocumentForm.setAnchor(TemConstants.SOURCE_ANCHOR); authorizationDocumentForm.getTravelAuthorizationDocument().addAdvanceAccountingLine(line); authorizationDocumentForm.setNewAdvanceAccountingLine(null); } return mapping.findForward(KFSConstants.MAPPING_BASIC); } /** * This method will remove an accounting line associated with the travel advance from a FinancialDocument. This assumes that the user presses the delete button * for a specific accounting line on the document and that the document is represented by a FinancialDocumentFormBase. If these assumptions are not meant...wow. * That's trouble, isn't it? * @param mapping a thing * @param form another thing * @param request I'm sure the Struts documentation covers this in detail * @param response for the remaining amount of time we're using Struts * @return ActionForward ah well...enjoy this, upcoming javadoc'ers * @throws Exception thrown if a bad thing happens */ public ActionForward deleteAdvanceAccountingLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TravelAuthorizationForm authorizationDocumentForm = (TravelAuthorizationForm) form; int deleteIndex = getLineToDelete(request); String errorPath = KFSConstants.DOCUMENT_PROPERTY_NAME + "." + TemPropertyConstants.ADVANCE_ACCOUNTING_LINES + "[" + deleteIndex + "]"; boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new DeleteAccountingLineEvent(errorPath, authorizationDocumentForm.getDocument(), authorizationDocumentForm.getTravelAuthorizationDocument().getAdvanceAccountingLine(deleteIndex), false)); // if the rule evaluation passed, let's delete it if (rulePassed) { authorizationDocumentForm.setAnchor(TemConstants.SOURCE_ANCHOR); authorizationDocumentForm.getTravelAuthorizationDocument().getAdvanceAccountingLines().remove(deleteIndex); } else { String[] errorParams = new String[] { "source", Integer.toString(deleteIndex + 1) }; GlobalVariables.getMessageMap().putError(errorPath, KFSKeyConstants.ERROR_ACCOUNTINGLINE_DELETERULE_INVALIDACCOUNT, errorParams); } return mapping.findForward(KFSConstants.MAPPING_BASIC); } /** * Takes care of storing the action form in the User session and forwarding to the balance inquiry report menu action for an accounting line * associated with a travel advance * @param mapping * @param form * @param request * @param response * @return ActionForward * @throws Exception */ public ActionForward performBalanceInquiryForAdvanceAccountingLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TemSourceAccountingLine line = getAdvanceAccountingLine(form, request); return performBalanceInquiryForAccountingLine(mapping, form, request, line); } /** * This method is a helper method that will return a source accounting line. The reason we're making it protected in here is so * that we can override this method in some of the modules. PurchasingActionBase is one of the subclasses that will be * overriding this, because in PurchasingActionBase, we'll need to get the source accounting line using both an item index and * an account index. * * @param form * @param request * @param isSource * @return */ protected TemSourceAccountingLine getAdvanceAccountingLine(ActionForm form, HttpServletRequest request) { final int lineIndex = getSelectedLine(request); TemSourceAccountingLine line = (TemSourceAccountingLine) ObjectUtils.deepCopy(((TravelAuthorizationForm) form).getTravelAuthorizationDocument().getAdvanceAccountingLine(lineIndex)); return line; } /** * Determines if the request is a return from an Object Code lookup. In this case we want special treatment. We know the return * from a lookup by checking the refreshCaller attribute. We know it's for an object code when an object code for a * newSourceLine is present in the request parameter. * * @param form to get refresh caller from * @param request to get the object code parameter from * @return boolean true if return from an object code lookup or false otherwise */ protected boolean isReturnFromObjectCodeLookup(final TravelAuthorizationForm form, final HttpServletRequest request) { return (form.getRefreshCaller() != null && request.getParameter(NEW_SOURCE_LINE_OBJECT_CODE) != null); } private void getMessages(TravelAuthorizationForm authForm) { TravelAuthorizationDocument document = authForm.getTravelAuthorizationDocument(); if (!StringUtils.isBlank(document.getAppDocStatus())) { if (document.getAppDocStatus().equals(TravelAuthorizationStatusCodeKeys.REIMB_HELD)) { KNSGlobalVariables.getMessageList().add(TemKeyConstants.TA_MESSAGE_HOLD_DOCUMENT_TEXT, new String[] { document.getHoldRequestorPersonName() }); } else if (document.getAppDocStatus().equals(TravelAuthorizationStatusCodeKeys.RETIRED_VERSION)) { KNSGlobalVariables.getMessageList().add(TemKeyConstants.TA_MESSAGE_RETIRED_DOCUMENT_TEXT); } else if (document.getAppDocStatus().equals(TravelAuthorizationStatusCodeKeys.PEND_AMENDMENT)) { KNSGlobalVariables.getMessageList().add(TemKeyConstants.TA_MESSAGE_AMEND_DOCUMENT_TEXT); } } } /** * This method sets all the boolean properties on the form to determine what buttons can be displayed depending on what is going * on */ protected void setButtonPermissions(TravelAuthorizationForm authForm) { canSave(authForm); setCanCalculate(authForm); setCanReturnToFisicalOfficer(authForm); hideButtons(authForm); } protected void hideButtons(TravelAuthorizationForm authForm) { boolean can = false; TravelAuthorizationAuthorizer documentAuthorizer = getDocumentAuthorizer(authForm); can = documentAuthorizer.hideButtons(authForm.getTravelAuthorizationDocument(), GlobalVariables.getUserSession().getPerson()); if (can){ authForm.getDocumentActions().remove(KRADConstants.KUALI_ACTION_CAN_SAVE); authForm.getDocumentActions().remove(KRADConstants.KUALI_ACTION_CAN_CLOSE); authForm.getDocumentActions().remove(KRADConstants.KUALI_ACTION_CAN_SEND_ADHOC_REQUESTS); authForm.getDocumentActions().remove(KRADConstants.KUALI_ACTION_CAN_COPY); authForm.getDocumentActions().remove(KRADConstants.KUALI_ACTION_CAN_RELOAD); } } protected void canSave(TravelAuthorizationForm authForm) { boolean can = !(isFinal(authForm) || isProcessed(authForm)); if (can) { TravelAuthorizationAuthorizer documentAuthorizer = getDocumentAuthorizer(authForm); can = documentAuthorizer.canSave(authForm.getTravelAuthorizationDocument(), GlobalVariables.getUserSession().getPerson()); } if (!can){ boolean isTravelManager = getTravelDocumentService().isTravelManager(GlobalVariables.getUserSession().getPerson()); boolean isDelinquent = authForm.getTravelAuthorizationDocument().getDelinquentAction() != null; if (isTravelManager && isDelinquent){ can = true; } } if (can) { authForm.getDocumentActions().put(KRADConstants.KUALI_ACTION_CAN_SAVE,true); } else{ authForm.getDocumentActions().remove(KRADConstants.KUALI_ACTION_CAN_SAVE); } } /** * Overriding this so that we can populate the transportation modes before a user leaves the page * * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#performLookup(org.apache.struts.action.ActionMapping, * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override public ActionForward performLookup(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TravelAuthorizationForm authForm = (TravelAuthorizationForm) form; List<String> selectedTransportationModes = authForm.getTempSelectedTransporationModes(); if (selectedTransportationModes != null) { authForm.getTravelAuthorizationDocument().setTransportationModeCodes(selectedTransportationModes); } else { authForm.getTravelAuthorizationDocument().setTransportationModeCodes(new ArrayList<String>()); } return super.performLookup(mapping, form, request, response); } /** * @see org.kuali.rice.kns.web.struts.action.KualiAction#refresh(org.apache.struts.action.ActionMapping, * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TravelAuthorizationForm authForm = (TravelAuthorizationForm) form; authForm.setSelectedTransportationModes(authForm.getTravelAuthorizationDocument().getTransportationModeCodes()); String refreshCaller = authForm.getRefreshCaller(); LOG.debug("refresh call is: "+ refreshCaller); String groupTravelerId = request.getParameter("newGroupTravelerLine.groupTravelerEmpId"); // if a cancel occurred on address lookup we need to reset the payee id and type, rest of fields will still have correct // information if (refreshCaller == null) { authForm.setTravelerId(authForm.getTempTravelerId()); } ActionForward actionAfterPrimaryDestinationLookup = this.refreshAfterPrimaryDestinationLookup(mapping, authForm, request); if (actionAfterPrimaryDestinationLookup != null) { return actionAfterPrimaryDestinationLookup; } return super.refresh(mapping, form, request, response); } /** * * @param travelReqDoc * @param request * @param authForm */ protected void refreshTransportationModesAfterButtonAction(TravelAuthorizationDocument travelReqDoc, TravelAuthorizationForm authForm) { List<String> selectedTransportationModes = authForm.getTempSelectedTransporationModes(); if (selectedTransportationModes != null) { LOG.debug("selected transportation modes are: "+ selectedTransportationModes.toString()); travelReqDoc.setTransportationModeCodes(selectedTransportationModes); } else { LOG.debug("setting selected transportation modes to empty list"); travelReqDoc.setTransportationModeCodes(new ArrayList<String>()); } } @Override protected void performRequesterRefresh(TravelDocument document, TravelFormBase travelForm, HttpServletRequest request) { LOG.debug("Looking up customer with number "+ document.getTraveler().getCustomerNumber()); document.getTraveler().refreshReferenceObject(TemPropertyConstants.CUSTOMER); document.getTraveler().refreshReferenceObject(TemPropertyConstants.TRAVELER_TYPE); LOG.debug("Got "+ document.getTraveler().getCustomer()); if (document.getTraveler().getPrincipalId() != null) { final String principalName = getPersonService().getPerson(document.getTraveler().getPrincipalId()).getPrincipalName(); document.getTraveler().setPrincipalName(principalName); } ((TravelAuthorizationDocument)document).updatePayeeTypeForAuthorization(); updateAccountsWithNewProfile(travelForm, document.getTemProfile()); } /** * This method adds a new emergency contact into the travel request document * * @param mapping * @param form * @param request * @param response * @return * @throws Exception */ public ActionForward addEmergencyContactLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TravelAuthorizationForm travelauthForm = (TravelAuthorizationForm) form; TravelAuthorizationDocument travelReqDoc = (TravelAuthorizationDocument) travelauthForm.getDocument(); TravelerDetailEmergencyContact newEmergencyContactLine = travelauthForm.getNewEmergencyContactLine(); boolean rulePassed = true; // check any business rules rulePassed &= SpringContext.getBean(KualiRuleService.class).applyRules(new AddEmergencyContactLineEvent(NEW_EMERGENCY_CONTACT_LINE, travelauthForm.getDocument(), newEmergencyContactLine)); if (rulePassed) { travelReqDoc.addEmergencyContactLine(newEmergencyContactLine); travelauthForm.setNewEmergencyContactLine(new TravelerDetailEmergencyContact()); } return mapping.findForward(KFSConstants.MAPPING_BASIC); } /** * This method removes an emergency contact from this collection * * @param mapping * @param form * @param request * @param response * @return * @throws Exception */ public ActionForward deleteEmergencyContactLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TravelAuthorizationForm travelauthForm = (TravelAuthorizationForm) form; TravelAuthorizationDocument travelReqDoc = (TravelAuthorizationDocument) travelauthForm.getDocument(); int deleteIndex = getLineToDelete(request); travelReqDoc.getTraveler().getEmergencyContacts().remove(deleteIndex); return mapping.findForward(KFSConstants.MAPPING_BASIC); } /** * @see org.kuali.kfs.module.tem.document.web.struts.TravelActionBase#updatePerDiemExpenses(org.apache.struts.action.ActionMapping, * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override public ActionForward updatePerDiemExpenses(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TravelAuthorizationForm taForm = (TravelAuthorizationForm) form; TravelAuthorizationDocument document = taForm.getTravelAuthorizationDocument(); ActionForward forward = super.updatePerDiemExpenses(mapping, form, request, response); taForm.getNewSourceLine().setAmount(this.getAccountingLineAmountToFillIn(taForm)); getTravelEncumbranceService().updateEncumbranceObjectCode(document, taForm.getNewSourceLine()); return forward; } /** * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#save(org.apache.struts.action.ActionMapping, * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override public ActionForward save(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TravelAuthorizationForm authForm = (TravelAuthorizationForm) form; TravelAuthorizationDocument travelReqDoc = authForm.getTravelAuthorizationDocument(); String tripTypeCode = travelReqDoc.getTripTypeCode(); LOG.debug("Got special circumstances "+ authForm.getTravelAuthorizationDocument().getSpecialCircumstances()); LOG.debug("Save Called on "+ getClass().getSimpleName()+ " for "+ authForm.getDocument().getClass().getSimpleName()); LOG.debug("Saving document traveler detail "+ travelReqDoc.getTravelerDetailId()); return super.save(mapping, form, request, response); } /** * Recalculates the Expenses Total Tab * * @param mapping * @param form * @param request * @param response * @throws Exception */ public ActionForward recalculate(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { return recalculateTripDetailTotal(mapping, form, request, response); } // Custom button actions /** * For use with a specific set of methods of this class that create new purchase order-derived document types in response to * user actions, including <code>amendTa</code>. It employs the question framework to ask the user for a response before * creating and routing the new document. The response should consist of a note detailing a reason, and either yes or no. This * method can be better understood if it is noted that it will be gone through twice (via the question framework); when each * question is originally asked, and again when the yes/no response is processed, for confirmation. * * @param mapping These are boiler-plate. * @param form " * @param request " * @param response " * @param questionType A string identifying the type of question being asked. * @param confirmType A string identifying which type of question is being confirmed. * @param documentType A string, the type of document to create * @param notePrefix A string to appear before the note in the BO Notes tab * @param messageType A string to appear on the PO once the question framework is done, describing the action taken * @param operation A string, the verb to insert in the original question describing the action to be taken * @return An ActionForward * @throws Exception */ @Override protected ActionForward askQuestionsAndPerformDocumentAction(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String questionType, String confirmType, String documentType, String notePrefix, String messageType, String operation) throws Exception { LOG.debug("askQuestionsAndPerformDocumentAction started."); TravelAuthorizationForm taForm = (TravelAuthorizationForm) form; TravelDocumentBase taDoc = taForm.getTravelAuthorizationDocument(); Object question = request.getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME); String reason = request.getParameter(KFSConstants.QUESTION_REASON_ATTRIBUTE_NAME); String noteText = ""; try { ConfigurationService kualiConfiguration = SpringContext.getBean(ConfigurationService.class); // Start in logic for confirming the proposed operation. if (ObjectUtils.isNull(question)) { String message = ""; String key = kualiConfiguration.getPropertyValueAsString(TemKeyConstants.TA_QUESTION_DOCUMENT); message = StringUtils.replace(key, "{0}", operation); // Ask question if not already asked. return this.performQuestionWithInput(mapping, form, request, response, questionType, message, KFSConstants.CONFIRMATION_QUESTION, questionType, ""); } else { Object buttonClicked = request.getParameter(KFSConstants.QUESTION_CLICKED_BUTTON); if (question.equals(questionType) && buttonClicked.equals(ConfirmationQuestion.NO)) { // If 'No' is the button clicked, just reload the doc return returnToPreviousPage(mapping, taForm); } else if (question.equals(confirmType) && buttonClicked.equals(SingleConfirmationQuestion.OK)) { // This is the case when the user clicks on "OK" in the end. // After we inform the user that the close has been rerouted, we'll redirect to the portal page. return mapping.findForward(KFSConstants.MAPPING_PORTAL); } else { // Have to check length on value entered. String introNoteMessage = notePrefix + KFSConstants.BLANK_SPACE; // Build out full message. noteText = introNoteMessage + reason; int noteTextLength = noteText.length(); // Get note text max length from DD. int noteTextMaxLength = SpringContext.getBean(DataDictionaryService.class).getAttributeMaxLength(Note.class, KFSConstants.NOTE_TEXT_PROPERTY_NAME).intValue(); if (StringUtils.isBlank(reason) || (noteTextLength > noteTextMaxLength)) { // Figure out exact number of characters that the user can enter. int reasonLimit = noteTextMaxLength - noteTextLength; if (ObjectUtils.isNull(reason)) { // Prevent a NPE by setting the reason to a blank string. reason = ""; } return this.performQuestionWithInputAgainBecauseOfErrors(mapping, form, request, response, questionType, kualiConfiguration.getPropertyValueAsString(TemKeyConstants.TA_QUESTION_DOCUMENT), KFSConstants.CONFIRMATION_QUESTION, questionType, "", reason, TemKeyConstants.ERROR_TA_REASON_REQUIRED, KFSConstants.QUESTION_REASON_ATTRIBUTE_NAME, new Integer(reasonLimit).toString()); } } } // Below used as a place holder to allow code to specify actionForward to return if not a 'success question' ActionForward returnActionForward = null; String newStatus = null; if (documentType.equals(TemConstants.TravelDocTypes.TRAVEL_AUTHORIZATION_AMEND_DOCUMENT)) { newStatus = TemConstants.TravelAuthorizationStatusCodeKeys.PEND_AMENDMENT; returnActionForward = mapping.findForward(KFSConstants.MAPPING_BASIC); noteText = noteText + " (Previous Document Id is " + taForm.getDocId() + ")"; } else if (questionType.equals(TemConstants.HOLD_TA_QUESTION)) { newStatus = TemConstants.TravelAuthorizationStatusCodeKeys.REIMB_HELD; } else if (questionType.equals(TemConstants.REMOVE_HOLD_TA_QUESTION)) { newStatus = TemConstants.TravelAuthorizationStatusCodeKeys.OPEN_REIMB; } Note newNote = getDocumentService().createNoteFromDocument(taDoc, noteText); taForm.setNewNote(newNote); taForm.setAttachmentFile(new BlankFormFile()); insertBONote(mapping, taForm, request, response); // save the new state on the document taDoc.updateAndSaveAppDocStatus(newStatus); // send FYI for Hold, Remove Hold if (questionType.equals(TemConstants.REMOVE_HOLD_TA_QUESTION) || questionType.equals(TemConstants.HOLD_TA_QUESTION)) { getTravelDocumentService().addAdHocFYIRecipient(taDoc, taDoc.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId()); } SpringContext.getBean(DocumentService.class).saveDocument(taDoc); if (ObjectUtils.isNotNull(returnActionForward)) { return returnActionForward; } else { return this.performQuestionWithoutInput(mapping, form, request, response, confirmType, kualiConfiguration.getPropertyValueAsString(messageType), "temSingleConfirmationQuestion", questionType, ""); } } catch (ValidationException ve) { throw ve; } } /** * Is invoked when the user pressed on the Amend button on a Travel Authorization page to amend the TA. It will display the * question page to the user to ask whether the user really wants to amend the TA and ask the user to enter a reason in the text * area. If the user has entered the reason, it will invoke a service method to do the processing for amending the TA, then * display a Single Confirmation page to inform the user that the <code>TravelAuthorizationAmendmentDocument</code> has been * routed. * * @param mapping An ActionMapping * @param form An ActionForm * @param request The HttpServletRequest * @param response The HttpServletResponse * @throws Exception * @return An ActionForward * @see org.kuali.kfs.module.tem.document.TravelAuthorizationAmendmentDocument */ public ActionForward amendTa(final ActionMapping mapping, final ActionForm form, final HttpServletRequest request, final HttpServletResponse response) throws Exception { LOG.debug("Amend TA started"); final Inquisitive<TravelAuthorizationDocument, ActionForward> inq = getInquisitive(mapping, form, request, response); if (inq.wasQuestionAsked()) { if (request.getParameterMap().containsKey(KFSConstants.QUESTION_REASON_ATTRIBUTE_NAME)){ getDocumentService().saveDocument(((TravelAuthorizationForm)form).getDocument(), AccountingDocumentSaveWithNoLedgerEntryGenerationEvent.class); } } ActionForward forward = askQuestionsAndPerformDocumentAction(inq, TemConstants.AMENDMENT_TA_QUESTION); return forward; } /** * * @param mapping * @param form * @param request * @param response * @return * @throws Exception */ public ActionForward holdTa(final ActionMapping mapping, final ActionForm form, final HttpServletRequest request, final HttpServletResponse response) throws Exception { LOG.debug("Hold TA started"); final Inquisitive<TravelAuthorizationDocument, ActionForward> inq = getInquisitive(mapping, form, request, response); return askQuestionsAndPerformDocumentAction(inq, TemConstants.HOLD_TA_QUESTION); } /** * * @param mapping * @param form * @param request * @param response * @return * @throws Exception */ public ActionForward removeHoldTa(final ActionMapping mapping, final ActionForm form, final HttpServletRequest request, final HttpServletResponse response) throws Exception { LOG.debug("Remove Hold TA started"); final Inquisitive<TravelAuthorizationDocument, ActionForward> inq = getInquisitive(mapping, form, request, response); return askQuestionsAndPerformDocumentAction(inq, TemConstants.REMOVE_HOLD_TA_QUESTION); } /** * * @param mapping * @param form * @param request * @param response * @return * @throws Exception */ public ActionForward cancelTa(final ActionMapping mapping, final ActionForm form, final HttpServletRequest request, final HttpServletResponse response) throws Exception { LOG.debug("Cancel TA started"); final Inquisitive<TravelAuthorizationDocument, ActionForward> inq = getInquisitive(mapping, form, request, response); return askQuestionsAndPerformDocumentAction(inq, TemConstants.CANCEL_TA_QUESTION); } /** * * @param mapping * @param form * @param request * @param response * @return * @throws Exception */ public ActionForward closeTa(final ActionMapping mapping, final ActionForm form, final HttpServletRequest request, final HttpServletResponse response) throws Exception { LOG.debug("Close TA started"); String operation = "Close "; final Inquisitive<TravelAuthorizationDocument, ActionForward> inq = getInquisitive(mapping, form, request, response); return askQuestionsAndPerformDocumentAction(inq, TemConstants.CLOSE_TA_QUESTION); } /** * Forward to creation of new reimbursement document * * @param mapping * @param form * @param request * @param response * @return * @throws Exception */ public ActionForward newReimbursement(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { final TravelAuthorizationDocument travelAuth = ((TravelAuthorizationForm)form).getTravelAuthorizationDocument(); return new ActionForward(buildNewReimbursementUrl(travelAuth), true); } /** * * @param mapping * @param form * @param request * @param response * @return */ protected Inquisitive<TravelAuthorizationDocument, ActionForward> getInquisitive(final ActionMapping mapping, final ActionForm form, final HttpServletRequest request, final HttpServletResponse response) { final Inquisitive<TravelAuthorizationDocument, ActionForward> inq = new StrutsInquisitor<TravelAuthorizationDocument, TravelAuthorizationForm, TravelAuthorizationAction>(mapping, (TravelAuthorizationForm) form, this, request, response); return inq; } /** * * @param inq * @param questionId * @return * @throws Exception */ protected ActionForward askQuestionsAndPerformDocumentAction(final Inquisitive<TravelAuthorizationDocument, ActionForward> inq, final String questionId) throws Exception { final QuestionHandler<TravelAuthorizationDocument> questionHandler = getQuestionHandler(questionId); if (inq.wasQuestionAsked()) { return questionHandler.handleResponse(inq); } return questionHandler.askQuestion(inq); } /** * This is a utility method used to prepare to and to return to a previous page, making sure that the buttons will be restored * in the process. * * @param kualiDocumentFormBase The Form, considered as a KualiDocumentFormBase, as it typically is here. * @return An actionForward mapping back to the original page. */ protected ActionForward returnToPreviousPage(ActionMapping mapping, KualiDocumentFormBase kualiDocumentFormBase) { return mapping.findForward(KFSConstants.MAPPING_BASIC); } @Override protected KualiDecimal getAccountingLineAmountToFillIn(TravelFormBase travelFormBase) { TravelAuthorizationForm travelAuthForm = (TravelAuthorizationForm) travelFormBase; KualiDecimal amount = new KualiDecimal(0); KualiDecimal encTotal = travelAuthForm.getTravelAuthorizationDocument().getEncumbranceTotal(); KualiDecimal expenseTotal = travelAuthForm.getTravelAuthorizationDocument().getExpenseLimit(); List<SourceAccountingLine> accountingLines = travelAuthForm.getTravelAuthorizationDocument().getSourceAccountingLines(); KualiDecimal accountingTotal = new KualiDecimal(0); for (SourceAccountingLine accountingLine : accountingLines) { accountingTotal = accountingTotal.add(accountingLine.getAmount()); } if (ObjectUtils.isNull(expenseTotal)) { amount = encTotal.subtract(accountingTotal); } else if (expenseTotal.isLessThan(encTotal)) { amount = expenseTotal.subtract(accountingTotal); } else { amount = encTotal.subtract(accountingTotal); } return amount; } /** * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase#insertSourceLine(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override public ActionForward insertSourceLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TravelAuthorizationForm travelauthForm = (TravelAuthorizationForm) form; // before we try to insert - set the card type to encumbrance TemSourceAccountingLine accountingLine = (TemSourceAccountingLine)(((TravelAuthorizationForm)form).getNewSourceLine()); accountingLine.setCardType(TemConstants.ENCUMBRANCE); super.insertSourceLine(mapping, form, request, response); // after we insert and have a blank line - set the amount to fill in travelauthForm.getNewSourceLine().setAmount(this.getAccountingLineAmountToFillIn(travelauthForm)); return mapping.findForward(KFSConstants.MAPPING_BASIC); } /** * @see org.kuali.kfs.module.tem.document.web.struts.TravelActionBase#deleteSourceLine(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override public ActionForward deleteSourceLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { super.deleteSourceLine(mapping, form, request, response); TravelAuthorizationForm travelauthForm = (TravelAuthorizationForm) form; travelauthForm.getNewSourceLine().setAmount(this.getAccountingLineAmountToFillIn(travelauthForm)); return mapping.findForward(KFSConstants.MAPPING_BASIC); } /** * @see org.kuali.kfs.module.tem.document.web.struts.TravelActionBase#cancel(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override public ActionForward cancel(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { Object buttonClicked = request.getParameter(KRADConstants.QUESTION_CLICKED_BUTTON); if (ConfirmationQuestion.YES.equals(buttonClicked)) { reverseAmendment((TravelAuthorizationForm) form); } return super.cancel(mapping, form, request, response); } @Override public ActionForward disapprove(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { Object buttonClicked = request.getParameter(KRADConstants.QUESTION_CLICKED_BUTTON); if (ConfirmationQuestion.YES.equals(buttonClicked)) { reverseAmendment((TravelAuthorizationForm) form); } return super.disapprove(mapping, form, request, response); } /** * @see org.kuali.kfs.module.tem.document.web.struts.TravelActionBase#close(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override public ActionForward close(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { Object buttonClicked = request.getParameter(KRADConstants.QUESTION_CLICKED_BUTTON); return super.close(mapping, form, request, response); } /** * @see org.kuali.kfs.module.tem.document.web.struts.TravelActionBase#route(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override public ActionForward route(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { recalculateTripDetailTotalOnly(mapping, form, request, response); TravelAuthorizationForm authForm = (TravelAuthorizationForm) form; TravelAuthorizationDocument document = authForm.getTravelAuthorizationDocument(); document.propagateAdvanceInformationIfNeeded(); return super.route(mapping, form, request, response); } /** * @see org.kuali.kfs.module.tem.document.web.struts.TravelActionBase#blanketApprove(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override public ActionForward blanketApprove(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { if (((TravelAuthorizationForm)form).getTravelAuthorizationDocument().shouldProcessAdvanceForDocument()) { ((TravelAuthorizationForm)form).getTravelAuthorizationDocument().propagateAdvanceInformationIfNeeded(); ((TravelAuthorizationForm)form).getTravelAuthorizationDocument().getTravelAdvance().setTravelAdvancePolicy(true); } return super.blanketApprove(mapping, form, request, response); } /** * At PaymentMethod node, propogate the advance amount if needed * @see org.kuali.kfs.module.tem.document.web.struts.TravelActionBase#approve(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override public ActionForward approve(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { if (isAtApprovalPropagateAdvanceInfoNode(((TravelAuthorizationForm)form).getTravelAuthorizationDocument().getDocumentHeader().getWorkflowDocument().getCurrentNodeNames()) && ((TravelAuthorizationForm)form).getTravelAuthorizationDocument().shouldProcessAdvanceForDocument()) { ((TravelAuthorizationForm)form).getTravelAuthorizationDocument().propagateAdvanceInformationIfNeeded(); } return super.approve(mapping, form, request, response); } /** * Determines if the approval request is coming from a node which should propagate advance information (specifically the amount of the advance) * @param nodeNames the Set of nodes where the document is currently at * @return true if the advance info should be propagated, false otherwise */ protected boolean isAtApprovalPropagateAdvanceInfoNode(Set<String> nodeNames) { if (nodeNames != null && !nodeNames.isEmpty()) { return nodeNames.contains(KFSConstants.RouteLevelNames.PAYMENT_METHOD) || nodeNames.contains(TemWorkflowConstants.RouteNodeNames.AP_TRAVEL); } return false; } /** * action which clears out an advance - this allows travel managers to clear advance as needed */ public ActionForward clearAdvance(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { if (((TravelAuthorizationForm)form).getTravelAuthorizationDocument().shouldProcessAdvanceForDocument()) { final TravelAuthorizationDocument doc = ((TravelAuthorizationForm)form).getTravelAuthorizationDocument(); doc.getTravelAdvance().clear(); // clean up due date and payment amount from travel payment if (!ObjectUtils.isNull(doc.getAdvanceTravelPayment())) { doc.getAdvanceTravelPayment().setDueDate(null); doc.getAdvanceTravelPayment().setCheckTotalAmount(null); doc.getAdvanceTravelPayment().setPaymentMethodCode(KFSConstants.PaymentMethod.ACH_CHECK.getCode()); // set to check, so that foreign draft or wire transfer is not processed } // clean up accounting lines if (doc.allParametersForAdvanceAccountingLinesSet()) { doc.getAdvanceAccountingLine(0).setAmount(KualiDecimal.ZERO); } else { doc.setAdvanceAccountingLines(new ArrayList<TemSourceAccountingLine>()); } } return mapping.findForward(KFSConstants.MAPPING_BASIC); } /** * Update the TA status if the amendment is canceled or closed and not saved. * * @param form */ protected void reverseAmendment(TravelAuthorizationForm form) { if (form.getTravelAuthorizationDocument() instanceof TravelAuthorizationAmendmentDocument) { TravelDocument travelDocument = form.getTravelAuthorizationDocument(); getTravelDocumentService().revertOriginalDocument(travelDocument, TravelAuthorizationStatusCodeKeys.OPEN_REIMB); } } /** * Overridden to always return TravelAuthorizationDocument even if we're dealing with an amendment or a close * @see org.kuali.kfs.module.tem.document.web.struts.TravelActionBase#showAccountDistribution(javax.servlet.http.HttpServletRequest, org.kuali.rice.krad.document.Document) */ @Override protected void showAccountDistribution(HttpServletRequest request, Document document) { if (document instanceof TravelAuthorizationDocument) { final boolean showAccountDistribution = getParameterService().getParameterValueAsBoolean(TravelAuthorizationDocument.class, DISPLAY_ACCOUNTING_DISTRIBUTION_TAB_IND); request.setAttribute(SHOW_ACCOUNT_DISTRIBUTION_ATTRIBUTE, showAccountDistribution); } else { super.showAccountDistribution(request, document); } } /** * Overridden so that if a TAA is copied, it actually generates a new TA * @see org.kuali.rice.kns.web.struts.action.KualiTransactionalDocumentActionBase#copy(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override public ActionForward copy(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TravelAuthorizationForm travelAuthForm = (TravelAuthorizationForm) form; TravelAuthorizationDocument doc = travelAuthForm.getTravelAuthorizationDocument(); if (!travelAuthForm.getDocumentActions().containsKey(KRADConstants.KUALI_ACTION_CAN_COPY)) { throw buildAuthorizationException("copy", doc); } if (doc.shouldRevertToOriginalAuthorizationOnCopy()) { TravelAuthorizationDocument newTaDoc = doc.toCopyTA(); travelAuthForm.setDocument(newTaDoc); travelAuthForm.setDocTypeName(TemConstants.TravelDocTypes.TRAVEL_AUTHORIZATION_DOCUMENT); } else { ((Copyable) travelAuthForm.getTransactionalDocument()).toCopy(); } return mapping.findForward(RiceConstants.MAPPING_BASIC); } protected void setTabStateForEmergencyContacts(TravelAuthorizationForm form) { TravelAuthorizationDocument travelAuthDocument = (TravelAuthorizationDocument) form.getDocument(); boolean openTab = false; Collection<String> internationalTrips = getParameterService().getParameterValuesAsString(TemParameterConstants.TEM_DOCUMENT.class, TravelParameters.INTERNATIONAL_TRIP_TYPES); if (travelAuthDocument.getTripTypeCode() != null) { if (internationalTrips.contains(travelAuthDocument.getTripTypeCode())){ openTab = true; } if (openTab) { String tabKey = WebUtils.generateTabKey(TemConstants.TabTitles.EMERGENCY_CONTACT_INFORMATION_TAB_TITLE); form.getTabStates().put(tabKey, KualiForm.TabState.OPEN.name()); } } return; } /** * @see org.kuali.kfs.module.tem.document.web.bean.TravelReimbursementMvcWrapperBean * @see org.kuali.kfs.module.tem.document.web.bean.TravelMvcWrapperBean * @see org.kuali.kfs.module.tem.document.web.struts.TravelActionBase#getMvcWrapperInterface() * @see org.kuali.kfs.module.tem.document.web.struts.TravelActionBase#newMvcDelegate(ActionForm) * @see org.kuali.kfs.module.tem.document.web.struts.TravelStrutsObservable */ @Override protected Class getMvcWrapperInterface() { return TravelAuthorizationMvcWrapperBean.class; } }