gt:         BudgetConstructionForm tForm = (BudgetConstructionForm) form;
context: /*
   * 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.bc.document.web.struts;
  
  import java.math.BigDecimal;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.Properties;
  
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  import javax.xml.namespace.QName;
  
  import org.apache.commons.lang.StringUtils;
  import org.apache.struts.action.ActionForm;
  import org.apache.struts.action.ActionForward;
  import org.apache.struts.action.ActionMapping;
  import org.kuali.kfs.module.bc.BCConstants;
  import org.kuali.kfs.module.bc.BCKeyConstants;
  import org.kuali.kfs.module.bc.BCPropertyConstants;
  import org.kuali.kfs.module.bc.BCConstants.LockStatus;
  import org.kuali.kfs.module.bc.BCConstants.MonthSpreadDeleteType;
  import org.kuali.kfs.module.bc.businessobject.BCKeyLabelPair;
  import org.kuali.kfs.module.bc.businessobject.BudgetConstructionAccountOrganizationHierarchy;
  import org.kuali.kfs.module.bc.businessobject.BudgetConstructionAuthorizationStatus;
  import org.kuali.kfs.module.bc.businessobject.BudgetConstructionHeader;
  import org.kuali.kfs.module.bc.businessobject.BudgetConstructionLockStatus;
  import org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionGeneralLedger;
  import org.kuali.kfs.module.bc.document.BudgetConstructionDocument;
  import org.kuali.kfs.module.bc.document.service.BudgetConstructionMonthlyBudgetsCreateDeleteService;
  import org.kuali.kfs.module.bc.document.service.BudgetDocumentService;
  import org.kuali.kfs.module.bc.document.service.LockService;
  import org.kuali.kfs.module.bc.document.validation.event.AddPendingBudgetGeneralLedgerLineEvent;
  import org.kuali.kfs.module.bc.document.validation.event.DeletePendingBudgetGeneralLedgerLineEvent;
  import org.kuali.kfs.module.bc.exception.BudgetConstructionDocumentAuthorizationException;
  import org.kuali.kfs.module.bc.identity.BudgetConstructionNoAccessMessageSetting;
  import org.kuali.kfs.sys.KFSConstants;
  import org.kuali.kfs.sys.KFSKeyConstants;
  import org.kuali.kfs.sys.KFSPropertyConstants;
  import org.kuali.kfs.sys.context.SpringContext;
  import org.kuali.kfs.sys.identity.KfsKimAttributes;
  import org.kuali.rice.core.api.config.property.ConfigurationService;
  import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
  import org.kuali.rice.core.api.util.type.KualiDecimal;
  import org.kuali.rice.core.api.util.type.KualiInteger;
  import org.kuali.rice.kew.api.WorkflowDocument;
  import org.kuali.rice.kew.api.exception.WorkflowException;
  import org.kuali.rice.kim.api.KimConstants;
  import org.kuali.rice.kim.api.identity.Person;
  import org.kuali.rice.kim.api.identity.principal.Principal;
  import org.kuali.rice.kim.api.role.Role;
  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
  import org.kuali.rice.kim.api.type.KimType;
  import org.kuali.rice.kim.framework.role.RoleTypeService;
  import org.kuali.rice.kns.document.authorization.TransactionalDocumentAuthorizer;
  import org.kuali.rice.kns.question.ConfirmationQuestion;
  import org.kuali.rice.kns.service.DocumentHelperService;
  import org.kuali.rice.kns.util.KNSGlobalVariables;
  import org.kuali.rice.kns.web.struts.action.KualiTransactionalDocumentActionBase;
  import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
  import org.kuali.rice.kns.web.struts.form.KualiForm;
  import org.kuali.rice.krad.UserSession;
  import org.kuali.rice.krad.document.Document;
  import org.kuali.rice.krad.exception.AuthorizationException;
  import org.kuali.rice.krad.exception.UnknownDocumentIdException;
  import org.kuali.rice.krad.service.BusinessObjectService;
  import org.kuali.rice.krad.service.KualiRuleService;
  import org.kuali.rice.krad.service.PersistenceService;
  import org.kuali.rice.krad.service.SessionDocumentService;
  import org.kuali.rice.krad.util.GlobalVariables;
  import org.kuali.rice.krad.util.KRADConstants;
  import org.kuali.rice.krad.util.UrlFactory;
  
  /**
   * need to figure out if this should extend KualiAction, KualiDocumentActionBase or KualiTransactionDocumentActionBase
   */
  public class BudgetConstructionAction extends KualiTransactionalDocumentActionBase {
      protected static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(BudgetConstructionAction.class);
  
      /**
       * Entry point to all actions Checks for cases where methodToCall is loadDocument, performAccountPullup or
       * performAccountPushdown and creates global messages to describe the new editingMode state. Also handles document locking if
       * the editingMode is BudgetConstructionEditMode.FULL_ENTRY. (Re)Populates the pullup and pushdown selection controls based on
       * the current level of the document and the user's approval access for the levels above and below the current level.
       *
       * @see org.kuali.rice.kns.web.struts.action.KualiTransactionalDocumentActionBase#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 {
          BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form;
  
          // this is only used to indicate to the rules the user has clicked save or close save-yes
          // which forces tighter checks (nonZeroRequest amount) when access is cleanup mode
          if (budgetConstructionForm.getBudgetConstructionDocument().isCleanupModeActionForceCheck()) {
              budgetConstructionForm.getBudgetConstructionDocument().setCleanupModeActionForceCheck(Boolean.FALSE);
          }
  
          // TODO: the catch code comes from KualiDocumentActionBase.loadDocument()
          // this allows the top portion of the document to be populated and the close button to function
          // and also displays all the possible error messages for now
          // we need to update this once KIM is adjusted to handle BC no access cases
          // and maybe just show the authorization exception message
          ActionForward forward = null;
          try {
              forward = super.execute(mapping, form, request, response);
          }
          catch (AuthorizationException e) {
              forward = mapping.findForward(KFSConstants.MAPPING_BASIC);
              String docId = budgetConstructionForm.getDocId();
              Document doc = null;
              doc = getDocumentService().getByDocumentHeaderId(docId);
              if (doc == null) {
                  throw new UnknownDocumentIdException("Document no longer exists.  It may have been cancelled before being saved.");
              }
              WorkflowDocument workflowDocument = doc.getDocumentHeader().getWorkflowDocument();
              // if (!getDocumentHelperService().getDocumentAuthorizer(doc).canOpen(doc,
              // GlobalVariables.getUserSession().getPerson())) {
              // throw buildAuthorizationException("open", doc);
              // }
              // re-retrieve the document using the current user's session - remove the system user from the WorkflowDcument object
              if (workflowDocument != doc.getDocumentHeader().getWorkflowDocument()) {
                  LOG.warn("Workflow document changed via canOpen check");
                  doc.getDocumentHeader().setWorkflowDocument(workflowDocument);
              }
              budgetConstructionForm.setDocument(doc);
              WorkflowDocument workflowDoc = doc.getDocumentHeader().getWorkflowDocument();
              budgetConstructionForm.setDocTypeName(workflowDoc.getDocumentTypeName());
              // KualiDocumentFormBase.populate() needs this updated in the session
  
              SpringContext.getBean(SessionDocumentService.class).addDocumentToUserSession(GlobalVariables.getUserSession(), workflowDoc);
  
              budgetConstructionForm.setSecurityNoAccess(true);
              setBudgetDocumentNoAccessMessage(budgetConstructionForm);
              budgetConstructionForm.getDocumentActions().put(KRADConstants.KUALI_ACTION_CAN_CLOSE, Boolean.TRUE);
  
          }
  
          // apprise user of granted access
          if (budgetConstructionForm.getMethodToCall().equals(BCConstants.BC_DOCUMENT_METHOD) || budgetConstructionForm.getMethodToCall().equals(BCConstants.BC_DOCUMENT_PULLUP_METHOD) || budgetConstructionForm.getMethodToCall().equals(BCConstants.BC_DOCUMENT_PUSHDOWN_METHOD)) {
  
              // init the account org hier state on initial load only - this is stored as hiddens
              if (budgetConstructionForm.getMethodToCall().equals(BCConstants.BC_DOCUMENT_METHOD)) {
                  budgetConstructionForm.setAccountOrgHierLevels(SpringContext.getBean(BudgetDocumentService.class).getPushPullLevelList(budgetConstructionForm.getBudgetConstructionDocument(), GlobalVariables.getUserSession().getPerson()));
              }
  
              if (budgetConstructionForm.isSystemViewOnly()) {
                  KNSGlobalVariables.getMessageList().add(BCKeyConstants.MESSAGE_BUDGET_SYSTEM_VIEW_ONLY);
              }
  
              if (!budgetConstructionForm.isEditAllowed()) {
                  KNSGlobalVariables.getMessageList().add(BCKeyConstants.MESSAGE_BUDGET_VIEW_ONLY);
              }
  
              if (budgetConstructionForm.isEditAllowed()) {
                  if (budgetConstructionForm.isSystemViewOnly()) {
                      KNSGlobalVariables.getMessageList().add(BCKeyConstants.MESSAGE_BUDGET_VIEW_ONLY);
                  }
                  else {
  
                      // tell the user if the document is in not budgetable mode
                      budgetConstructionForm.getBudgetConstructionDocument().setBudgetableDocument(SpringContext.getBean(BudgetDocumentService.class).isBudgetableDocumentNoWagesCheck(budgetConstructionForm.getBudgetConstructionDocument()));
                      // budgetConstructionForm.setBudgetableDocument(SpringContext.getBean(BudgetDocumentService.class).isBudgetableDocumentNoWagesCheck(budgetConstructionForm.getBudgetConstructionDocument()));
                      if (!budgetConstructionForm.isBudgetableDocument()) {
                          KNSGlobalVariables.getMessageList().add(BCKeyConstants.MESSAGE_BUDGET_DOCUMENT_NOT_BUDGETABLE);
                      }
  
                      KNSGlobalVariables.getMessageList().add(BCKeyConstants.MESSAGE_BUDGET_EDIT_ACCESS);
                  }
  
                  if (!budgetConstructionForm.isSystemViewOnly()) {
                      LockService lockService = SpringContext.getBean(LockService.class);
                      HashMap primaryKey = new HashMap();
                      primaryKey.put(KFSPropertyConstants.DOCUMENT_NUMBER, budgetConstructionForm.getDocument().getDocumentNumber());
  
                      BudgetConstructionHeader budgetConstructionHeader = SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(BudgetConstructionHeader.class, primaryKey);
                      if (budgetConstructionHeader != null) {
                          // BudgetConstructionLockStatus bcLockStatus = lockService.lockAccount(budgetConstructionHeader,
                          // GlobalVariables.getUserSession().getPerson().getPrincipalId());
                          BudgetConstructionLockStatus bcLockStatus = lockService.lockAccountAndCommit(budgetConstructionHeader, GlobalVariables.getUserSession().getPerson().getPrincipalId());
  
                          if (bcLockStatus.getLockStatus() == LockStatus.SUCCESS) {
  
                              // update the document version number
                              // so the saved lock of header doesn't produce an optimistic lock error
                              // and has the info we just put in the header so doc save doesn't wipe out the lock
                              budgetConstructionForm.getBudgetConstructionDocument().setVersionNumber(bcLockStatus.getBudgetConstructionHeader().getVersionNumber());
                              budgetConstructionForm.getBudgetConstructionDocument().setBudgetLockUserIdentifier(bcLockStatus.getBudgetConstructionHeader().getBudgetLockUserIdentifier());
                          }
                          else {
                              if (bcLockStatus.getLockStatus() == LockStatus.BY_OTHER) {
                                  Principal principal = KimApiServiceLocator.getIdentityService().getPrincipal(bcLockStatus.getAccountLockOwner());
                                  String lockerName = principal.getPrincipalName();
                                  this.cleanupForLockError(budgetConstructionForm);
                                  GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, BCKeyConstants.ERROR_BUDGET_DOCUMENT_LOCKED, lockerName);
                                  return forward;
                              }
                              else {
                                  if (bcLockStatus.getLockStatus() == LockStatus.FLOCK_FOUND) {
                                      this.cleanupForLockError(budgetConstructionForm);
                                      GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, BCKeyConstants.ERROR_BUDGET_FUNDING_LOCKED);
                                      return forward;
                                  }
                                  else {
                                      this.cleanupForLockError(budgetConstructionForm);
                                      GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, BCKeyConstants.ERROR_BUDGET_DOCUMENT_OTHER);
                                      return forward;
                                  }
                              }
                          }
                      }
                      else {
                          // unlikely
                          throw new BudgetConstructionDocumentAuthorizationException(GlobalVariables.getUserSession().getPerson().getName(), "open", budgetConstructionForm.getDocument().getDocumentHeader().getDocumentNumber(), "(can't find document for locking)", budgetConstructionForm.isPickListMode());
                      }
  
                      // if editing, check if 2plg adjustment needed and calc benefits
                      // since checkTwoPlugAdjusmtent will only be set in docHandler during initial load
                      // if document is initially view only we want the 2plg adjustment to happen if the user does a pullup to edit
                      if (budgetConstructionForm.isCheckTwoPlugAdjustment() && budgetConstructionForm.getBudgetConstructionDocument().isContainsTwoPlug() && !budgetConstructionForm.getBudgetConstructionDocument().isSalarySettingOnly()) {
                          // do 2plg related benefits calc and adjust 2plg for any diff - reset checkTwoPlugAdjusment
                          budgetConstructionForm.setCheckTwoPlugAdjustment(false);
                          this.adjustForSalarySettingChanges(budgetConstructionForm);
                      }
                  }
  
                  // getting here implies a lock or system view mode, try to build a pullup list
                  // pushdown is only allowed if user has edit access (regardless of system view only mode)
                  if (budgetConstructionForm.getBudgetConstructionDocument().getOrganizationLevelCode() != 0) {
                      if (!budgetConstructionForm.getAccountOrgHierLevels().isEmpty()) {
                          budgetConstructionForm.populatePushPullLevelKeyLabels(budgetConstructionForm.getBudgetConstructionDocument(), budgetConstructionForm.getAccountOrgHierLevels(), false);
                      }
                  }
                  else {
                      // document(account) at level zero - clear out the pushdownKeyLabels widget for any previous performPush case
                      budgetConstructionForm.setPushdownLevelKeyLabels(new ArrayList<BCKeyLabelPair>());
                  }
              } // FULL_ENTRY
  
              // pullup is allowed regardless of editMode
              if (!budgetConstructionForm.getAccountOrgHierLevels().isEmpty()) {
                  budgetConstructionForm.populatePushPullLevelKeyLabels(budgetConstructionForm.getBudgetConstructionDocument(), budgetConstructionForm.getAccountOrgHierLevels(), true);
              }
          }
  
          // cleanup the session edit mode store so we don't side effect organization salary setting
          if (budgetConstructionForm.isClosingDocument()) {
              GlobalVariables.getUserSession().removeObject(BCConstants.BC_DOC_AUTHORIZATION_STATUS_SESSIONKEY);
          }
  
          return forward;
      }
  
      /**
       * Finds the role type service associated with the document viewer role, than calls method on role type service to set the no
       * access message
       *
       * @param budgetConstructionForm form containing budget document
       */
      protected void setBudgetDocumentNoAccessMessage(BudgetConstructionForm budgetConstructionForm) {
          Role roleInfo = KimApiServiceLocator.getRoleService().getRoleByNamespaceCodeAndName(BCConstants.BUDGET_CONSTRUCTION_NAMESPACE, BCConstants.KimApiConstants.DOCUMENT_VIEWER_ROLE_NAME);
          KimType typeInfo = KimApiServiceLocator.getKimTypeInfoService().getKimType(roleInfo.getKimTypeId());
  
          if (StringUtils.isNotBlank(typeInfo.getServiceName())) {
              // fix to find service using new prefixed name if so configured
              // RoleTypeService roleTypeService = (RoleTypeService) SpringContext.getService(typeInfo.getServiceName());
              RoleTypeService roleTypeService;
              String svcName = typeInfo.getServiceName();
              String[] svcNameParts = svcName.split("\\{|\\}");
              if (svcNameParts.length == 3){
                  String nameSpaceURI = svcNameParts[1];
                  String remoteServiceName = svcNameParts[2];
                  roleTypeService = (RoleTypeService)GlobalResourceLoader.getService(new QName(nameSpaceURI, remoteServiceName));
              } else {
                roleTypeService = (RoleTypeService) SpringContext.getService(typeInfo.getServiceName());
              }
  
              if (roleTypeService instanceof BudgetConstructionNoAccessMessageSetting) {
                  ((BudgetConstructionNoAccessMessageSetting) roleTypeService).setNoAccessMessage(budgetConstructionForm.getBudgetConstructionDocument(), GlobalVariables.getUserSession().getPerson(), GlobalVariables.getMessageMap());
              } else {
                  LOG.warn(String.format("typeInfo.getServiceName() = %s is not an instance of BudgetConstructionNoAccessMessageSetting for role %s/%s", typeInfo.getServiceName(), BCConstants.BUDGET_CONSTRUCTION_NAMESPACE, BCConstants.KimApiConstants.DOCUMENT_VIEWER_ROLE_NAME));
              }
          } else {
              LOG.warn(String.format("typeInfo.getServiceName() returned a blank service name for role %s/%s", BCConstants.BUDGET_CONSTRUCTION_NAMESPACE, BCConstants.KimApiConstants.DOCUMENT_VIEWER_ROLE_NAME));
          }
      }
  
      /**
       * gwp - no call to super, need to work through command we will use randall - This method might be unnecessary, but putting it
       * here allows URL to be consistent with Document URLs gwp - i think we still want this method, just need to figure out if we
       * use command initiate or displayDocSearchView or something else. i expect we will get the account/subaccount or docnumber from
       * the previous form and assume the document will already exist regardless of creation by genesis or
       *
       * @param mapping
       * @param form
       * @param request
       * @param response
       * @return
       * @throws IOException
       * @throws ServletException
       */
      @Override
      public ActionForward docHandler(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form;
  
          loadDocument(budgetConstructionForm);
  
          // set flag to have execute perform 2plug adjusment if the doc goes into edit mode later
          budgetConstructionForm.setCheckTwoPlugAdjustment(true);
  
          this.initAuthorization(budgetConstructionForm);
  
          return mapping.findForward(KFSConstants.MAPPING_BASIC);
      }
  
      /**
       * Initially load the document from the DB Coded this to look like KualiDocumentActionBase.loadDocument()
       *
       * @param budgetConstructionForm
       * @throws WorkflowException
       */
      @Override
      protected void loadDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException {
          BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) kualiDocumentFormBase;
  
          BudgetConstructionHeader budgetConstructionHeader;
          if (budgetConstructionForm.getDocId() != null) {
              Map<String, Object> primaryKey = new HashMap<String, Object>();
              primaryKey.put(KFSPropertyConstants.DOCUMENT_NUMBER, budgetConstructionForm.getDocId());
  
              budgetConstructionHeader = SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(BudgetConstructionHeader.class, primaryKey);
  
              // getting called from doc search?
              if (budgetConstructionForm.getMethodToCall().equalsIgnoreCase(KFSConstants.DOC_HANDLER_METHOD)){
  
                  // now fill in the form parms normally passed from BC selection or Account selection screens
                  budgetConstructionForm.setChartOfAccountsCode(budgetConstructionHeader.getChartOfAccountsCode());
                  budgetConstructionForm.setAccountNumber(budgetConstructionHeader.getAccountNumber());
                  budgetConstructionForm.setSubAccountNumber(budgetConstructionHeader.getSubAccountNumber());
                  budgetConstructionForm.setUniversityFiscalYear(budgetConstructionHeader.getUniversityFiscalYear());
                  budgetConstructionForm.setPickListMode(Boolean.TRUE);
              }
  
          }
          else {
              // use the passed url autoloaded parms to get the record from DB
              // BudgetConstructionDaoOjb bcHeaderDao;
              String chartOfAccountsCode = budgetConstructionForm.getChartOfAccountsCode();
              String accountNumber = budgetConstructionForm.getAccountNumber();
              String subAccountNumber = budgetConstructionForm.getSubAccountNumber();
              Integer universityFiscalYear = budgetConstructionForm.getUniversityFiscalYear();
  
              budgetConstructionHeader = SpringContext.getBean(BudgetDocumentService.class).getByCandidateKey(chartOfAccountsCode, accountNumber, subAccountNumber, universityFiscalYear);
          }
  
          kualiDocumentFormBase.setDocId(budgetConstructionHeader.getDocumentNumber());
          super.loadDocument(kualiDocumentFormBase);
  
          BudgetConstructionDocument budgetConstructionDocument = (BudgetConstructionDocument) kualiDocumentFormBase.getDocument();
  
          // init the benefits calc flags
          budgetConstructionDocument.setBenefitsCalcNeeded(false);
          budgetConstructionDocument.setMonthlyBenefitsCalcNeeded(false);
  
          // init the new line objects
          budgetConstructionForm.initNewLine(budgetConstructionForm.getNewRevenueLine(), true);
          budgetConstructionForm.initNewLine(budgetConstructionForm.getNewExpenditureLine(), false);
  
          // need this here to do totaling on initial load
          budgetConstructionForm.populatePBGLLines();
          budgetConstructionForm.initializePersistedRequestAmounts();
      }
  
      /**
       * Cleans up state info to handle no access lock errors
       *
       * @param budgetConstructionForm
       */
      protected void cleanupForLockError(BudgetConstructionForm budgetConstructionForm) {
          budgetConstructionForm.setSecurityNoAccess(true);
          budgetConstructionForm.getDocumentActions().remove(KRADConstants.KUALI_ACTION_CAN_EDIT);
          budgetConstructionForm.getDocumentActions().remove(KRADConstants.KUALI_ACTION_CAN_SAVE);
          KNSGlobalVariables.getMessageList().remove(BCKeyConstants.MESSAGE_BUDGET_EDIT_ACCESS);
      }
  
      /**
       * Override to set authorization Maps from session
       *
       * @see org.kuali.rice.kns.web.struts.action.KualiTransactionalDocumentActionBase#populateAuthorizationFields(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase)
       */
      @Override
      protected void populateAuthorizationFields(KualiDocumentFormBase formBase) {
          BudgetConstructionAuthorizationStatus authorizationStatus = (BudgetConstructionAuthorizationStatus) GlobalVariables.getUserSession().retrieveObject(BCConstants.BC_DOC_AUTHORIZATION_STATUS_SESSIONKEY);
  
          if (authorizationStatus == null) {
              // execute handles any session timeout before this is called
              return;
          }
  
          formBase.setDocumentActions(authorizationStatus.getDocumentActions());
          formBase.setEditingMode(authorizationStatus.getEditingMode());
      }
  
      /**
       * Calls authorizer to determine if the user has edit permission and checks if budget construction is active is fiscal year
       * function table. Then updates the <code>BudgetConstructionEditStatus</code> in session. Finally updates authorization in the
       * form
       *
       * @param budgetConstructionForm current bc action form that will be updated
       */
      protected void initAuthorization(BudgetConstructionForm budgetConstructionForm) {
          // GlobalVariables.setRequestCache(ROLE_QUALIFICATION_CACHE_NAME, budgetConstructionForm)
          super.populateAuthorizationFields(budgetConstructionForm);
  
          BudgetConstructionAuthorizationStatus editStatus = new BudgetConstructionAuthorizationStatus();
          editStatus.setDocumentActions(budgetConstructionForm.getDocumentActions());
          editStatus.setEditingMode(budgetConstructionForm.getEditingMode());
  
          GlobalVariables.getUserSession().addObject(BCConstants.BC_DOC_AUTHORIZATION_STATUS_SESSIONKEY, editStatus);
      }
  
      /**
       * Applies adjustments due to 2plg existence at initial load or detected salary setting changes upon returning from the Quick
       * Salary Setting screen. The adjustments consist of calculating benefits and adding any expenditure total before/after
       * difference back into a 2plg row, creating or updating as needed. Then, validation is performed. Sucessful validation removes
       * the 2plg row if the final, post benefits calc, adjusted amount is zero. This method assumes the set of expenditure rows in
       * memory currently matches the DB.
       *
       * @param bcForm
       */
      protected void adjustForSalarySettingChanges(BudgetConstructionForm bcForm) {
  
          BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class);
          BudgetConstructionDocument bcDoc = (BudgetConstructionDocument) bcForm.getDocument();
          KualiInteger oldRequestAmount = bcDoc.getExpenditureAccountLineAnnualBalanceAmountTotal();
  
          // calc benefits also handles setting persisted amounts and populating reloaded benefit rows
          budgetDocumentService.calculateBenefits(bcDoc);
          // bcForm.initializePersistedRequestAmounts();
  
          // repop and refresh refs - esp monthly so jsp can properly display state
          // bcForm.populatePBGLLines();
  
          // need 2plg adjustment and save, even if it is zero
          KualiInteger newRquestAmount = bcForm.getBudgetConstructionDocument().getExpenditureAccountLineAnnualBalanceAmountTotal();
          PendingBudgetConstructionGeneralLedger twoPlugRow = budgetDocumentService.updatePendingBudgetGeneralLedgerPlug(bcDoc, newRquestAmount.subtract(oldRequestAmount));
      }
  
      /**
       * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#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 {
  
          // return super.close(mapping, form, request, response);
          BudgetConstructionForm docForm = (BudgetConstructionForm) form;
  
          // only want to prompt them to save if they already can save
          if (docForm.getDocumentActions().keySet().contains(KRADConstants.KUALI_ACTION_CAN_SAVE)) {
              Object question = request.getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME);
              ConfigurationService kualiConfiguration = SpringContext.getBean(ConfigurationService.class);
  
              // logic for close question
              if (question == null) {
                  // ask question if not already asked
                  return this.performQuestionWithoutInput(mapping, form, request, response, KFSConstants.DOCUMENT_SAVE_BEFORE_CLOSE_QUESTION, kualiConfiguration.getPropertyValueAsString(KFSKeyConstants.QUESTION_SAVE_BEFORE_CLOSE), KFSConstants.CONFIRMATION_QUESTION, KFSConstants.MAPPING_CLOSE, "");
              }
              else {
                  Object buttonClicked = request.getParameter(KFSConstants.QUESTION_CLICKED_BUTTON);
                  if ((KFSConstants.DOCUMENT_SAVE_BEFORE_CLOSE_QUESTION.equals(question)) && ConfirmationQuestion.YES.equals(buttonClicked)) {
                      // if yes button clicked - save the doc
                      BudgetConstructionDocument bcDoc = (BudgetConstructionDocument) docForm.getDocument();
  
                      // force tighter checks when saving in cleanup mode
                      if (!bcDoc.isBudgetableDocument()) {
                          bcDoc.setCleanupModeActionForceCheck(Boolean.TRUE);
                      }
  
                      // SpringContext.getBean(DocumentService.class).updateDocument(docForm.getDocument());
                      BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class);
                      budgetDocumentService.saveDocument(bcDoc);
                      docForm.initializePersistedRequestAmounts();
                      if (bcDoc.isBenefitsCalcNeeded() || bcDoc.isMonthlyBenefitsCalcNeeded()) {
                          budgetDocumentService.calculateBenefitsIfNeeded(bcDoc);
  
                          KNSGlobalVariables.getMessageList().add(KFSKeyConstants.MESSAGE_SAVED);
                          return mapping.findForward(KFSConstants.MAPPING_BASIC);
                      }
                      else {
                          // else drop to close logic below
                      }
  
                  }
                  // else drop to close logic below
              }
          }
  
          // do the unlock if they have full access and not system view mode
          if (docForm.isEditAllowed() && !docForm.isSystemViewOnly()) {
              LockService lockService = SpringContext.getBean(LockService.class);
              HashMap primaryKey = new HashMap();
              primaryKey.put(KFSPropertyConstants.DOCUMENT_NUMBER, docForm.getDocument().getDocumentNumber());
  
              BudgetConstructionHeader budgetConstructionHeader = SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(BudgetConstructionHeader.class, primaryKey);
              if (budgetConstructionHeader != null) {
                  LockStatus lockStatus = lockService.unlockAccount(budgetConstructionHeader);
              }
              else {
                  // unlikely, but benign problem here
              }
          }
  
          // flag to cleanup the session edit mode store so we don't side effect organization salary setting
          // used in the bottom of execute()
          docForm.setClosingDocument(Boolean.TRUE);
  
          if (docForm.isPickListMode()) {
              // redisplay with a message
              KNSGlobalVariables.getMessageList().add(BCKeyConstants.MESSAGE_BUDGET_SUCCESSFUL_CLOSE);
              docForm.setPickListClose(true);
  
              // this is a hack to do our own session document cleanup since refreshCaller=QuestionRefresh
              // prevents proper cleanup in KualiRequestProcessor.processActionPerform()
              UserSession userSession = (UserSession) request.getSession().getAttribute(KRADConstants.USER_SESSION_KEY);
              String docFormKey = docForm.getFormKey();
              SpringContext.getBean(SessionDocumentService.class).purgeDocumentForm(docForm.getDocument().getDocumentNumber(), docFormKey, userSession, request.getRemoteAddr());
  
              return mapping.findForward(KFSConstants.MAPPING_BASIC);
  
          }
          else {
              if (docForm.getReturnFormKey() == null) {
  
                  // assume called from doc search or lost the session - go back to main
                  return returnToSender(request, mapping, docForm);
              }
              else {
                  // setup the return parms for the document and anchor and go back to doc select
                  Properties parameters = new Properties();
                  parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, BCConstants.BC_SELECTION_REFRESH_METHOD);
                  parameters.put(KFSConstants.DOC_FORM_KEY, docForm.getReturnFormKey());
                  parameters.put(KFSConstants.ANCHOR, docForm.getReturnAnchor());
                  parameters.put(KFSConstants.REFRESH_CALLER, BCConstants.BC_DOCUMENT_REFRESH_CALLER);
  
                  String lookupUrl = UrlFactory.parameterizeUrl("/" + BCConstants.BC_SELECTION_ACTION, parameters);
  
                  // this is a hack to do our own session document cleanup since refreshCaller=QuestionRefresh
                  // prevents proper cleanup in KualiRequestProcessor.processActionPerform()
                  UserSession userSession = (UserSession) request.getSession().getAttribute(KRADConstants.USER_SESSION_KEY);
                  String docFormKey = docForm.getFormKey();
                  SpringContext.getBean(SessionDocumentService.class).purgeDocumentForm(docForm.getDocument().getDocumentNumber(), docFormKey, userSession, request.getRemoteAddr());
  
                  return new ActionForward(lookupUrl, true);
              }
          }
      }
  
      /**
       * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#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 {
  
          BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form;
          BudgetConstructionDocument bcDocument = (BudgetConstructionDocument) budgetConstructionForm.getDocument();
          // DocumentService documentService = SpringContext.getBean(DocumentService.class);
          BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class);
  
          // force tighter checks when saving in cleanup mode
          if (!bcDocument.isBudgetableDocument()) {
              bcDocument.setCleanupModeActionForceCheck(Boolean.TRUE);
          }
  
          budgetDocumentService.saveDocument(bcDocument);
          budgetConstructionForm.initializePersistedRequestAmounts();
          budgetDocumentService.calculateBenefitsIfNeeded(bcDocument);
          KNSGlobalVariables.getMessageList().add(KFSKeyConstants.MESSAGE_SAVED);
  
          budgetConstructionForm.setAnnotation("");
  
          // redisplay the document along with document saved message
          return mapping.findForward(KFSConstants.MAPPING_BASIC);
      }
  
      /**
       * Calls the single line benefits impact screen by setting up the required parameters and feeding them to the temporary list
       * lookup action for the expenditure line selected. This is called from the ShowBenefits button on the BC document screen when
       * an expenditure line is associated with benefits and benefits calculation is enabled.
       *
       * @param mapping
       * @param form
       * @param request
       * @param response
       * @return
       * @throws Exception
       */
      public ActionForward performShowBenefits(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
  
          BudgetConstructionForm tForm = (BudgetConstructionForm) form;
          BudgetConstructionDocument tDoc = tForm.getBudgetConstructionDocument();
          int selectIndex = this.getSelectedLine(request);
          PendingBudgetConstructionGeneralLedger expLine = tDoc.getPendingBudgetConstructionGeneralLedgerExpenditureLines().get(selectIndex);
  
          // when we return from the lookup, our next request's method to call is going to be refresh
          tForm.registerEditableProperty(KRADConstants.DISPATCH_REQUEST_PARAMETER);
  
          Properties parameters = new Properties();
          parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, KFSConstants.START_METHOD);
  
          String basePath = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(KFSConstants.APPLICATION_URL_KEY);
          parameters.put(KFSConstants.BACK_LOCATION, basePath + mapping.getPath() + ".do");
  
          if (StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) {
              parameters.put(BCConstants.RETURN_ANCHOR, ((KualiForm) form).getAnchor());
          }
  
          // this hack sets the return anchor we want to return too after the inquiry
          // do this here so it gets into the session stored form version
          // refresh checks for this after and resets the anchor
          if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) {
              tForm.setBalanceInquiryReturnAnchor(((KualiForm) form).getAnchor());
          }
  
          parameters.put(KRADConstants.DOC_FORM_KEY, GlobalVariables.getUserSession().addObjectWithGeneratedKey(form, BCConstants.FORMKEY_PREFIX));
          parameters.put(KFSConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, BCConstants.REQUEST_BENEFITS_BO);
          parameters.put(KFSConstants.HIDE_LOOKUP_RETURN_LINK, "true");
          parameters.put(KFSConstants.SUPPRESS_ACTIONS, "true");
          parameters.put(BCConstants.SHOW_INITIAL_RESULTS, "true");
          parameters.put(BCConstants.TempListLookupMode.TEMP_LIST_LOOKUP_MODE, Integer.toString(BCConstants.TempListLookupMode.SHOW_BENEFITS));
  
          parameters.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, expLine.getUniversityFiscalYear().toString());
          parameters.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, expLine.getChartOfAccountsCode());
          parameters.put(KFSConstants.FINANCIAL_OBJECT_CODE_PROPERTY_NAME, expLine.getFinancialObjectCode());
          parameters.put(KFSPropertyConstants.ACCOUNT_LINE_ANNUAL_BALANCE_AMOUNT, expLine.getAccountLineAnnualBalanceAmount().toString());
          parameters.put(KFSPropertyConstants.ACCOUNT_NUMBER, expLine.getAccountNumber());
          parameters.put(KRADConstants.LOOKUP_READ_ONLY_FIELDS, KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR + "," + KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE + "," + KFSConstants.FINANCIAL_OBJECT_CODE_PROPERTY_NAME + "," + KFSPropertyConstants.ACCOUNT_LINE_ANNUAL_BALANCE_AMOUNT);
  
          String url = UrlFactory.parameterizeUrl(basePath + "/" + BCConstants.ORG_TEMP_LIST_LOOKUP, parameters);
          this.setupDocumentExit();
          return new ActionForward(url, true);
      }
  
      public ActionForward performBalanceInquiryForRevenueLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          return performBalanceInquiry(true, mapping, form, request, response);
      }
  
      public ActionForward performBalanceInquiryForExpenditureLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          return performBalanceInquiry(false, mapping, form, request, response);
      }
  
      /**
       * This method is similar to org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase.performBalanceInquiry()
       *
       * @param isRevenue
       * @param mapping
       * @param form
       * @param request
       * @param response
       * @return
       * @throws Exception
       */
      public ActionForward performBalanceInquiry(boolean isRevenue, ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          final String docNumber;
  
          // get the selected line, setup parms and redirect to balance inquiry
          BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form;
          BudgetConstructionDocument bcDocument = (BudgetConstructionDocument) budgetConstructionForm.getDocument();
  
          // when we return from the lookup, our next request's method to call is going to be refresh
          budgetConstructionForm.registerEditableProperty(KRADConstants.DISPATCH_REQUEST_PARAMETER);
  
          PendingBudgetConstructionGeneralLedger pbglLine;
          if (isRevenue) {
              pbglLine = bcDocument.getPendingBudgetConstructionGeneralLedgerRevenueLines().get(this.getSelectedLine(request));
          }
          else {
              pbglLine = bcDocument.getPendingBudgetConstructionGeneralLedgerExpenditureLines().get(this.getSelectedLine(request));
          }
  
          // build out base path for return location, use config service
          String basePath = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(KFSConstants.APPLICATION_URL_KEY);
  
          // this hack sets the return anchor we want to return too after the inquiry
          // do this here so it gets into the session stored form version
          // refresh checks for this after and resets the anchor
          if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) {
              budgetConstructionForm.setBalanceInquiryReturnAnchor(((KualiForm) form).getAnchor());
          }
  
          // build out the actual form key that will be used to retrieve the form on refresh
          String callerDocFormKey = GlobalVariables.getUserSession().addObjectWithGeneratedKey(form, BCConstants.FORMKEY_PREFIX);
  
          // now add required parameters
          Properties parameters = new Properties();
          parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, KFSConstants.START_METHOD);
          // need this next param b/c the lookup's return back will overwrite
          // the original doc form key
          parameters.put(KFSConstants.BALANCE_INQUIRY_REPORT_MENU_CALLER_DOC_FORM_KEY, callerDocFormKey);
          parameters.put(KFSConstants.DOC_FORM_KEY, callerDocFormKey);
          parameters.put(KFSConstants.BACK_LOCATION, basePath + mapping.getPath() + ".do");
  
          // anchor, if it exists
          // this doesn't seem to work with the balance inquiry infrastructure, so added hack above
          if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) {
              parameters.put(BCConstants.RETURN_ANCHOR, ((KualiForm) form).getAnchor());
          }
  
          if (StringUtils.isNotBlank(pbglLine.getChartOfAccountsCode())) {
              parameters.put("chartOfAccountsCode", pbglLine.getChartOfAccountsCode());
          }
          if (StringUtils.isNotBlank(pbglLine.getAccountNumber())) {
              parameters.put("accountNumber", pbglLine.getAccountNumber());
          }
          if (StringUtils.isNotBlank(pbglLine.getFinancialObjectCode())) {
              parameters.put("financialObjectCode", pbglLine.getFinancialObjectCode());
          }
          if (StringUtils.isNotBlank(pbglLine.getSubAccountNumber())) {
              parameters.put("subAccountNumber", pbglLine.getSubAccountNumber());
          }
          if (StringUtils.isNotBlank(pbglLine.getFinancialSubObjectCode())) {
              parameters.put("financialSubObjectCode", pbglLine.getFinancialSubObjectCode());
          }
  
          String lookupUrl = UrlFactory.parameterizeUrl(basePath + "/" + KFSConstants.BALANCE_INQUIRY_REPORT_MENU_ACTION, parameters);
  
          this.setupDocumentExit();
          return new ActionForward(lookupUrl, true);
      }
  
      /**
       * Calls performMonthlyBudget for the selected revenue line
       *
       * @param mapping
       * @param form
       * @param request
       * @param response
       * @return
       * @throws Exception
       */
      public ActionForward performMonthlyRevenueBudget(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          return performMonthlyBudget(true, mapping, form, request, response);
      }
  
      /**
       * Calls performMonthlyBudget for the selected expenditure line
       *
       * @param mapping
       * @param form
       * @param request
       * @param response
       * @return
       * @throws Exception
       */
      public ActionForward performMonthlyExpenditureBudget(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          return performMonthlyBudget(false, mapping, form, request, response);
      }
  
      /**
       * Forwards the user to the monthly budget screen. Doing this in edit mode causes the document to be validated, saved and
       * benefits calculated (if needed).
       *
       * @param isRevenue
       * @param mapping
       * @param form
       * @param request
       * @param response
       * @return
       * @throws Exception
       */
      public ActionForward performMonthlyBudget(boolean isRevenue, ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          final String docNumber;
  
          // this to checks for 2PLG and turns off SS/monthly RI check if found
          // the final save after removing 2PLG will catch any monthly discrepencies
          // also need to save object,subobject key we are operating on so refresh can get the latest row version from DB
  
          // validate, save, etc first then goto the monthly screen or redisplay if errors
          BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form;
          BudgetConstructionDocument bcDocument = (BudgetConstructionDocument) budgetConstructionForm.getDocument();
  
          PendingBudgetConstructionGeneralLedger pbglLine;
          if (isRevenue) {
              pbglLine = bcDocument.getPendingBudgetConstructionGeneralLedgerRevenueLines().get(this.getSelectedLine(request));
          }
          else {
              pbglLine = bcDocument.getPendingBudgetConstructionGeneralLedgerExpenditureLines().get(this.getSelectedLine(request));
          }
  
          // when we return from the lookup, our next request's method to call is going to be refresh
          budgetConstructionForm.registerEditableProperty(KRADConstants.DISPATCH_REQUEST_PARAMETER);
  
          if (budgetConstructionForm.isEditAllowed() && !budgetConstructionForm.isSystemViewOnly()) {
              BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class);
  
              // if the doc contains a 2plg line, turn off RI checking to allow cleanup.
              // The act of attempting to remove a 2plg (delete) forces a complete RI check.
              // The document is assumed inconsistent as long as a 2plg exists.
              if (!isRevenue && bcDocument.isContainsTwoPlug()) {
                  if (pbglLine.getLaborObject() != null && pbglLine.getLaborObject().isDetailPositionRequiredIndicator()) {
                      budgetDocumentService.saveDocumentNoWorkFlow(bcDocument, MonthSpreadDeleteType.EXPENDITURE, false);
                  }
                  else {
                      budgetDocumentService.saveDocumentNoWorkFlow(bcDocument, MonthSpreadDeleteType.EXPENDITURE, true);
                  }
              }
              else {
                  budgetDocumentService.saveDocumentNoWorkflow(bcDocument);
  
              }
              budgetConstructionForm.initializePersistedRequestAmounts();
              budgetDocumentService.calculateBenefitsIfNeeded(bcDocument);
  
              // repop and refresh refs - esp monthly so jsp can properly display state
              // budgetConstructionForm.populatePBGLLines();
  
          }
  
          // String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() +
          // request.getContextPath();
          String basePath = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(KFSConstants.APPLICATION_URL_KEY);
          Properties parameters = new Properties();
          parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, BCConstants.MONTHLY_BUDGET_METHOD);
          parameters.put(KFSConstants.BACK_LOCATION, basePath + mapping.getPath() + ".do");
          parameters.put("documentNumber", pbglLine.getDocumentNumber());
          parameters.put("universityFiscalYear", pbglLine.getUniversityFiscalYear().toString());
          parameters.put("chartOfAccountsCode", pbglLine.getChartOfAccountsCode());
          parameters.put("accountNumber", pbglLine.getAccountNumber());
          parameters.put("subAccountNumber", pbglLine.getSubAccountNumber());
          parameters.put("financialObjectCode", pbglLine.getFinancialObjectCode());
          parameters.put("financialSubObjectCode", pbglLine.getFinancialSubObjectCode());
          parameters.put("financialBalanceTypeCode", pbglLine.getFinancialBalanceTypeCode());
          parameters.put("financialObjectTypeCode", pbglLine.getFinancialObjectTypeCode());
          parameters.put("revenue", (isRevenue ? "true" : "false"));
          parameters.put(BCPropertyConstants.MAIN_WINDOW, (budgetConstructionForm.isMainWindow() ? "true" : "false"));
  
          // anchor, if it exists
          if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) {
              parameters.put(BCConstants.RETURN_ANCHOR, ((KualiForm) form).getAnchor());
          }
  
          // the form object is retrieved and removed upon return by KualiRequestProcessor.processActionForm()
          parameters.put(BCConstants.RETURN_FORM_KEY, GlobalVariables.getUserSession().addObjectWithGeneratedKey(form, BCConstants.FORMKEY_PREFIX));
  
          String lookupUrl = UrlFactory.parameterizeUrl(basePath + "/" + BCConstants.MONTHLY_BUDGET_ACTION, parameters);
          this.setupDocumentExit();
          return new ActionForward(lookupUrl, true);
      }
  
      /**
       * Forwards the user to the quick salary setting screen. Doing this in edit mode causes the document to be validated, saved and
       * benefits calculated (if needed).
       *
       * @param mapping
       * @param form
       * @param request
       * @param response
       * @return
       * @throws Exception
       */
      public ActionForward performSalarySetting(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          final String docNumber;
  
          // this to checks for 2PLG and turns off monthly RI check if found
          // the final save after removing 2PLG will catch any monthly discrepencies
  
          // validate, save, etc first then goto the SalarySetting screen or redisplay if errors
          BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form;
          BudgetConstructionDocument bcDocument = (BudgetConstructionDocument) budgetConstructionForm.getDocument();
  
          // when we return from the lookup, our next request's method to call is going to be refresh
          budgetConstructionForm.registerEditableProperty(KRADConstants.DISPATCH_REQUEST_PARAMETER);
  
          if (budgetConstructionForm.isEditAllowed() && !budgetConstructionForm.isSystemViewOnly()) {
              BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class);
  
              // Regardless if the doc contains a 2plg line, turn off RI checking to allow cleanup.
              // The act of attempting to remove a 2plg (delete) forces a complete RI check.
              // The document is assumed inconsistent as long as a 2plg exists.
              budgetDocumentService.saveDocumentNoWorkFlow(bcDocument, MonthSpreadDeleteType.EXPENDITURE, false);
  
              // init persisted property and get the current list of salary setting related rows
              budgetConstructionForm.initializePersistedRequestAmounts(true);
  
              budgetDocumentService.calculateBenefitsIfNeeded(bcDocument);
  
              // repop and refresh refs - esp monthly so jsp can properly display state
              // budgetConstructionForm.populatePBGLLines();
  
          }
          PendingBudgetConstructionGeneralLedger pbglLine;
          pbglLine = bcDocument.getPendingBudgetConstructionGeneralLedgerExpenditureLines().get(this.getSelectedLine(request));
  
          // String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() +
          // request.getContextPath();
          String basePath = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(KFSConstants.APPLICATION_URL_KEY);
          Properties parameters = new Properties();
          parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, BCConstants.QUICK_SALARY_SETTING_METHOD);
          parameters.put(KFSConstants.BACK_LOCATION, basePath + mapping.getPath() + ".do");
  
          parameters.put("documentNumber", pbglLine.getDocumentNumber());
          parameters.put("universityFiscalYear", pbglLine.getUniversityFiscalYear().toString());
          parameters.put("chartOfAccountsCode", pbglLine.getChartOfAccountsCode());
          parameters.put("accountNumber", pbglLine.getAccountNumber());
          parameters.put("subAccountNumber", pbglLine.getSubAccountNumber());
          parameters.put("financialObjectCode", pbglLine.getFinancialObjectCode());
          parameters.put("financialSubObjectCode", pbglLine.getFinancialSubObjectCode());
          parameters.put("financialBalanceTypeCode", pbglLine.getFinancialBalanceTypeCode());
          parameters.put("financialObjectTypeCode", pbglLine.getFinancialObjectTypeCode());
          parameters.put(BCPropertyConstants.MAIN_WINDOW, (budgetConstructionForm.isMainWindow() ? "true" : "false"));
  
          // anchor, if it exists
          if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) {
              parameters.put(BCConstants.RETURN_ANCHOR, ((KualiForm) form).getAnchor());
          }
  
          // the form object is retrieved and removed upon return by KualiRequestProcessor.processActionForm()
          parameters.put(BCConstants.RETURN_FORM_KEY, GlobalVariables.getUserSession().addObjectWithGeneratedKey(form, BCConstants.FORMKEY_PREFIX));
  
          String lookupUrl = UrlFactory.parameterizeUrl(basePath + "/" + BCConstants.QUICK_SALARY_SETTING_ACTION, parameters);
          this.setupDocumentExit();
          return new ActionForward(lookupUrl, true);
      }
  
      /**
       * This adds a revenue line to the BC document
       *
       * @param mapping
       * @param form
       * @param request
       * @param response
       * @return
       * @throws Exception
       */
      public ActionForward insertRevenueLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form;
  
          PendingBudgetConstructionGeneralLedger line = budgetConstructionForm.getNewRevenueLine();
  
          boolean rulePassed = true;
  
          rulePassed &= SpringContext.getBean(KualiRuleService.class).applyRules(new AddPendingBudgetGeneralLedgerLineEvent(BCConstants.NEW_REVENUE_LINE_PROPERTY_NAME, budgetConstructionForm.getDocument(), line, true));
  
          if (rulePassed) {
              // add PBGLLine
              insertPBGLLine(true, budgetConstructionForm, line);
  
              // clear the used newRevenueLine
              budgetConstructionForm.setNewRevenueLine(new PendingBudgetConstructionGeneralLedger());
              budgetConstructionForm.initNewLine(budgetConstructionForm.getNewRevenueLine(), true);
          }
  
          return mapping.findForward(KFSConstants.MAPPING_BASIC);
      }
  
      /**
       * This adds an expenditure line to the BC document
       *
       * @param mapping
       * @param form
       * @param request
       * @param response
       * @return
       * @throws Exception
       */
      public ActionForward insertExpenditureLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form;
  
          PendingBudgetConstructionGeneralLedger line = budgetConstructionForm.getNewExpenditureLine();
  
          boolean rulePassed = true;
  
          rulePassed &= SpringContext.getBean(KualiRuleService.class).applyRules(new AddPendingBudgetGeneralLedgerLineEvent(BCConstants.NEW_EXPENDITURE_LINE_PROPERTY_NAME, budgetConstructionForm.getDocument(), line, false));
  
          if (rulePassed) {
  
              // add PBGLLine
              insertPBGLLine(false, budgetConstructionForm, line);
  
              // clear the used newExpenditureLine
              budgetConstructionForm.setNewExpenditureLine(new PendingBudgetConstructionGeneralLedger());
              budgetConstructionForm.initNewLine(budgetConstructionForm.getNewExpenditureLine(), false);
          }
  
          return mapping.findForward(KFSConstants.MAPPING_BASIC);
      }
  
      /**
       * This inserts a PBGL revenue or expenditure line
       *
       * @param isRevenue
       * @param budgetConstructionForm
       * @param line
       */
      protected void insertPBGLLine(boolean isRevenue, BudgetConstructionForm budgetConstructionForm, PendingBudgetConstructionGeneralLedger line) {
  
          BudgetConstructionDocument bcDoc = (BudgetConstructionDocument) budgetConstructionForm.getDocument();
  
          // KFSMI-7828 reset object type from object code table
          line.setFinancialObjectTypeCode(line.getFinancialObject().getFinancialObjectTypeCode());
  
          // null subobj must be set to dashes
          if (StringUtils.isBlank(line.getFinancialSubObjectCode())) {
              line.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode());
          }
  
          // check the DB for an existing persisted version of the line
          // and reinstate that with a message to the user indicating such
          boolean isReinstated = false;
          Map<String, Object> primaryKey = new HashMap<String, Object>();
          primaryKey.put(KFSPropertyConstants.DOCUMENT_NUMBER, line.getDocumentNumber());
          primaryKey.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, line.getUniversityFiscalYear());
          primaryKey.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, line.getChartOfAccountsCode());
          primaryKey.put(KFSPropertyConstants.ACCOUNT_NUMBER, line.getAccountNumber());
          primaryKey.put(KFSPropertyConstants.SUB_ACCOUNT_NUMBER, line.getSubAccountNumber());
          primaryKey.put(KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE, line.getFinancialBalanceTypeCode());
          primaryKey.put(KFSPropertyConstants.FINANCIAL_OBJECT_TYPE_CODE, line.getFinancialObjectTypeCode());
  
          primaryKey.put(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, line.getFinancialObjectCode());
          primaryKey.put(KFSPropertyConstants.FINANCIAL_SUB_OBJECT_CODE, line.getFinancialSubObjectCode());
  
          PendingBudgetConstructionGeneralLedger dbLine = SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(PendingBudgetConstructionGeneralLedger.class, primaryKey);
          if (dbLine != null){
              line = dbLine;
              SpringContext.getBean(BudgetDocumentService.class).populatePBGLLine(line);
              isReinstated = true;
          }
  
          // add the line in the proper order - assumes already exists check is done in rules
          int insertPoint = bcDoc.addPBGLLine(line, isRevenue);
  
          if (isReinstated){
              String errorKey;
              if (isRevenue){
                  errorKey = KRADConstants.DOCUMENT_PROPERTY_NAME + "." + BCPropertyConstants.PENDING_BUDGET_CONSTRUCTION_GENERAL_LEDGER_REVENUE_LINES + "[" + insertPoint  + "]." + KFSPropertyConstants.ACCOUNT_LINE_ANNUAL_BALANCE_AMOUNT;
              }
              else {
                  errorKey = KRADConstants.DOCUMENT_PROPERTY_NAME + "." + BCPropertyConstants.PENDING_BUDGET_CONSTRUCTION_GENERAL_LEDGER_EXPENDITURE_LINES + "[" + insertPoint  + "]." + KFSPropertyConstants.ACCOUNT_LINE_ANNUAL_BALANCE_AMOUNT;
              }
              GlobalVariables.getMessageMap().putError(errorKey, BCKeyConstants.ERROR_BUDGET_LINE_REINSTATED, dbLine.getFinancialObjectCode() + "," + dbLine.getFinancialSubObjectCode());
          }
  
          // adjust totals
          if (line.getAccountLineAnnualBalanceAmount() != null && line.getAccountLineAnnualBalanceAmount() != KualiInteger.ZERO) {
              if (isRevenue) {
                  bcDoc.setRevenueAccountLineAnnualBalanceAmountTotal(bcDoc.getRevenueAccountLineAnnualBalanceAmountTotal().add(line.getAccountLineAnnualBalanceAmount()));
              }
              else {
                  bcDoc.setExpenditureAccountLineAnnualBalanceAmountTotal(bcDoc.getExpenditureAccountLineAnnualBalanceAmountTotal().add(line.getAccountLineAnnualBalanceAmount()));
              }
          }
          if (line.getFinancialBeginningBalanceLineAmount() != null && line.getFinancialBeginningBalanceLineAmount() != KualiInteger.ZERO) {
              if (isRevenue) {
                  bcDoc.setRevenueFinancialBeginningBalanceLineAmountTotal(bcDoc.getRevenueFinancialBeginningBalanceLineAmountTotal().add(line.getFinancialBeginningBalanceLineAmount()));
              }
              else {
                  bcDoc.setExpenditureFinancialBeginningBalanceLineAmountTotal(bcDoc.getExpenditureFinancialBeginningBalanceLineAmountTotal().add(line.getFinancialBeginningBalanceLineAmount()));
              }
          }
      }
  
      /**
       * Deletes an existing PendingBudgetConstructionGeneralLedger revenue line if rules passed. Any associated monthly budget
       * (BudgetConstructionMonthly) is also deleted.
       *
       * @param mapping
       * @param form
       * @param request
       * @param response
       * @return
       * @throws Exception
       */
      public ActionForward deleteRevenueLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
  
          BudgetConstructionForm tForm = (BudgetConstructionForm) form;
          BudgetConstructionDocument tDoc = tForm.getBudgetConstructionDocument();
  
          boolean rulePassed = true;
          int deleteIndex = this.getLineToDelete(request);
  
          // check business rule if there is a persisted request amount, otherwise the line can just be removed
          PendingBudgetConstructionGeneralLedger revLine = tDoc.getPendingBudgetConstructionGeneralLedgerRevenueLines().get(deleteIndex);
          if (revLine.getPersistedAccountLineAnnualBalanceAmount() == null) {
              rulePassed = true;
          }
          else {
              // check deletion rules and delete if passed
              String errorPath = KFSConstants.DOCUMENT_PROPERTY_NAME + "." + BCPropertyConstants.PENDING_BUDGET_CONSTRUCTION_GENERAL_LEDGER_REVENUE_LINES + "[" + deleteIndex + "]";
              rulePassed &= SpringContext.getBean(KualiRuleService.class).applyRules(new DeletePendingBudgetGeneralLedgerLineEvent(errorPath, tDoc, revLine, true));
          }
  
          if (rulePassed) {
              deletePBGLLine(true, tForm, deleteIndex, revLine);
          }
  
          return mapping.findForward(KFSConstants.MAPPING_BASIC);
      }
  
      /**
       * Deletes an existing PendingBudgetConstructionGeneralLedger expenditure line if rules passed Any associated monthly budget
       * (BudgetConstructionMonthly) is also deleted. Check for the special case where the line is a 2PLG line, in which case the
       * document is validated and RI checks are forced even if there are no current differences between persisted and request
       * amounts.
       *
       * @param mapping
       * @param form
       * @param request
       * @param response
       * @return
       * @throws Exception
       */
      public ActionForward deleteExpenditureLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
  
          BudgetConstructionForm tForm = (BudgetConstructionForm) form;
          BudgetConstructionDocument tDoc = tForm.getBudgetConstructionDocument();
  
          boolean rulePassed = true;
          int deleteIndex = this.getLineToDelete(request);
  
          // check business rule if there is a persisted request amount, otherwise the line can just be removed
          PendingBudgetConstructionGeneralLedger expLine = tDoc.getPendingBudgetConstructionGeneralLedgerExpenditureLines().get(deleteIndex);
          if (expLine.getPersistedAccountLineAnnualBalanceAmount() == null) {
              rulePassed = true;
          }
          else {
              // check regular deletion rules and delete if passed
              String errorPath = KFSConstants.DOCUMENT_PROPERTY_NAME + "." + BCPropertyConstants.PENDING_BUDGET_CONSTRUCTION_GENERAL_LEDGER_EXPENDITURE_LINES + "[" + deleteIndex + "]";
              rulePassed &= SpringContext.getBean(KualiRuleService.class).applyRules(new DeletePendingBudgetGeneralLedgerLineEvent(errorPath, tDoc, expLine, false));
          }
  
          if (rulePassed) {
  
              // if the line is a 2PLG line do document validation, which forces RI checks in no current change situation
              if (expLine.getFinancialObjectCode().equalsIgnoreCase(KFSConstants.BudgetConstructionConstants.OBJECT_CODE_2PLG)) {
                  SpringContext.getBean(BudgetDocumentService.class).validateDocument(tDoc);
              }
              // gets here if line is not 2PLG or doc is valid from 2plg perspective
              deletePBGLLine(false, tForm, deleteIndex, expLine);
          }
  
          return mapping.findForward(KFSConstants.MAPPING_BASIC);
      }
  
      /**
       * Deletes an existing PendingBudgetConstructionGeneralLedger revenue or expenditure line along with any associated monthly
       * budget (BudgetConstructionMonthly)
       *
       * @param isRevenue
       * @param budgetConstructionForm
       * @param deleteIndex
       */
      protected void deletePBGLLine(boolean isRevenue, BudgetConstructionForm budgetConstructionForm, int deleteIndex, PendingBudgetConstructionGeneralLedger line) {
  
          BudgetConstructionDocument bcDoc = budgetConstructionForm.getBudgetConstructionDocument();
  
          // adjust totals
          if (line.getAccountLineAnnualBalanceAmount() != null && line.getAccountLineAnnualBalanceAmount() != KualiInteger.ZERO) {
              if (isRevenue) {
                  bcDoc.setRevenueAccountLineAnnualBalanceAmountTotal(bcDoc.getRevenueAccountLineAnnualBalanceAmountTotal().subtract(line.getAccountLineAnnualBalanceAmount()));
              }
              else {
                  bcDoc.setExpenditureAccountLineAnnualBalanceAmountTotal(bcDoc.getExpenditureAccountLineAnnualBalanceAmountTotal().subtract(line.getAccountLineAnnualBalanceAmount()));
              }
          }
          if (line.getFinancialBeginningBalanceLineAmount() != null && line.getFinancialBeginningBalanceLineAmount() != KualiInteger.ZERO) {
              if (isRevenue) {
                  bcDoc.setRevenueFinancialBeginningBalanceLineAmountTotal(bcDoc.getRevenueFinancialBeginningBalanceLineAmountTotal().subtract(line.getFinancialBeginningBalanceLineAmount()));
              }
              else {
                  bcDoc.setExpenditureFinancialBeginningBalanceLineAmountTotal(bcDoc.getExpenditureFinancialBeginningBalanceLineAmountTotal().subtract(line.getFinancialBeginningBalanceLineAmount()));
              }
          }
  
          // remove the line
          if (isRevenue) {
              bcDoc.getPendingBudgetConstructionGeneralLedgerRevenueLines().remove(deleteIndex);
          }
          else {
              if (line.getFinancialObjectCode().equalsIgnoreCase(KFSConstants.BudgetConstructionConstants.OBJECT_CODE_2PLG)) {
                  bcDoc.setContainsTwoPlug(false);
              }
              bcDoc.getPendingBudgetConstructionGeneralLedgerExpenditureLines().remove(deleteIndex);
          }
  
      }
  
      /*
       * public ActionForward returnFromMonthly(ActionMapping mapping, ActionForm form, HttpServletRequest request,
       * HttpServletResponse response) throws Exception { BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm)
       * form; String documentNumber = request.getParameter("documentNumber"); BudgetConstructionDocument budgetConstructionDocument =
       * (BudgetConstructionDocument) SpringContext.getBean(DocumentService.class).getByDocumentHeaderId(documentNumber);
       * budgetConstructionForm.setDocument(budgetConstructionDocument); KualiWorkflowDocument workflowDoc =
       * budgetConstructionDocument.getDocumentHeader().getWorkflowDocument();
       * budgetConstructionForm.setDocTypeName(workflowDoc.getDocumentType()); // KualiDocumentFormBase.populate() needs this updated
       * in the session GlobalVariables.getUserSession().setWorkflowDocument(workflowDoc); return
       * mapping.findForward(KFSConstants.MAPPING_BASIC); }
       */
  
      /**
       * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#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 {
          BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form;
          budgetConstructionForm.setDerivedValuesOnForm(request);
  
          // Do specific refresh stuff here based on refreshCaller parameter
          // typical refresh callers would be monthlyBudget or salarySetting or lookupable
          String refreshCaller = request.getParameter(KFSConstants.REFRESH_CALLER);
  
          if (refreshCaller != null && refreshCaller.endsWith(BCConstants.MONTHLY_BUDGET_REFRESH_CALLER)) {
  
              // monthly process applies any changes to the DB and the form session object
              // including any override to the request amount which also changes the request total
              // it also sets up calc monthly benefits if the line is involved in benefits
              BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class);
              budgetDocumentService.calculateBenefitsIfNeeded(budgetConstructionForm.getBudgetConstructionDocument());
  
          }
          if (refreshCaller != null && refreshCaller.endsWith(BCConstants.QUICK_SALARY_SETTING_REFRESH_CALLER)) {
  
  
              BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class);
  
              // if editing - reload expenditure and check for changes to detail salary lines and 2plg request amount
              boolean diffFound = false;
              if (budgetConstructionForm.isEditAllowed() && !budgetConstructionForm.isSystemViewOnly()) {
                  BudgetConstructionDocument currentBCDoc = budgetConstructionForm.getBudgetConstructionDocument();
  
                  // get the current set of salary setting related rows from DB and compare against preSalarySettingRows
  
                  List<PendingBudgetConstructionGeneralLedger> dbSalarySettingRows = budgetDocumentService.getPBGLSalarySettingRows(currentBCDoc);
                  for (PendingBudgetConstructionGeneralLedger dbSalarySettingRow : dbSalarySettingRows) {
                      if (budgetConstructionForm.getPreSalarySettingRows().containsKey(dbSalarySettingRow.getFinancialObjectCode() + dbSalarySettingRow.getFinancialSubObjectCode())) {
  
                          // update the existing row if a difference is found
                          KualiInteger dbReqAmount = dbSalarySettingRow.getAccountLineAnnualBalanceAmount();
                          KualiInteger preReqAmount = budgetConstructionForm.getPreSalarySettingRows().get(dbSalarySettingRow.getFinancialObjectCode() + dbSalarySettingRow.getFinancialSubObjectCode()).getAccountLineAnnualBalanceAmount();
                          Long dbVersionNumber = dbSalarySettingRow.getVersionNumber();
                          Long preReqVersionNumber = budgetConstructionForm.getPreSalarySettingRows().get(dbSalarySettingRow.getFinancialObjectCode() + dbSalarySettingRow.getFinancialSubObjectCode()).getVersionNumber();
                          if ((dbVersionNumber.compareTo(preReqVersionNumber) != 0) || (dbReqAmount.compareTo(preReqAmount) != 0)) {
                              budgetDocumentService.addOrUpdatePBGLRow(currentBCDoc, dbSalarySettingRow, Boolean.FALSE);
  
                              // only flag for existing line diff when the request amount changes
                              // changes in versionNumber implies offsetting updates of some sort
                              if (dbReqAmount.compareTo(preReqAmount) != 0) {
                                  diffFound = true;
                              }
                          }
                      }
                      else {
  
                          // update the req amount and version or add the new row to the current doc as needed
                          // insert the new DB row to the set in memory
                          budgetDocumentService.addOrUpdatePBGLRow(currentBCDoc, dbSalarySettingRow, Boolean.FALSE);
                          diffFound = true;
                      }
                  }
  
                  if (diffFound) {
                      this.adjustForSalarySettingChanges(budgetConstructionForm);
  
                  }
              }
  
          }
  
          if (refreshCaller != null && refreshCaller.endsWith(KFSConstants.LOOKUPABLE_SUFFIX)) {
  
              this.checkAndFixReturnedLookupValues(budgetConstructionForm.getNewRevenueLine(), budgetConstructionForm.getBudgetConstructionDocument());
              this.checkAndFixReturnedLookupValues(budgetConstructionForm.getNewExpenditureLine(), budgetConstructionForm.getBudgetConstructionDocument());
  
              final List REFRESH_FIELDS = Collections.unmodifiableList(Arrays.asList(new String[] { "financialObject", "financialSubObject" }));
              SpringContext.getBean(PersistenceService.class).retrieveReferenceObjects(budgetConstructionForm.getNewRevenueLine(), REFRESH_FIELDS);
              SpringContext.getBean(PersistenceService.class).retrieveReferenceObjects(budgetConstructionForm.getNewExpenditureLine(), REFRESH_FIELDS);
          }
  
          // balance inquiry anchor is set before doing a balance inquiry
          if (budgetConstructionForm.getBalanceInquiryReturnAnchor() != null) {
              budgetConstructionForm.setAnchor(budgetConstructionForm.getBalanceInquiryReturnAnchor());
              budgetConstructionForm.setBalanceInquiryReturnAnchor(null);
          }
          return mapping.findForward(KFSConstants.MAPPING_BASIC);
      }
  
      /**
       * checks the passed in newLine for any data consistency problems compared to the currently loaded document
       * this is typically called after return from a lookup since the user can potentially select from other fiscal years, etc.
       *
       * @param newLine
       * @param bcDoc
       */
      protected void checkAndFixReturnedLookupValues(PendingBudgetConstructionGeneralLedger newLine, BudgetConstructionDocument bcDoc){
          if (!newLine.getUniversityFiscalYear().equals(bcDoc.getUniversityFiscalYear())){
              newLine.setUniversityFiscalYear(bcDoc.getUniversityFiscalYear());
          }
          if (!newLine.getChartOfAccountsCode().equals(bcDoc.getChartOfAccountsCode())){
              newLine.setChartOfAccountsCode(bcDoc.getChartOfAccountsCode());
          }
          if (!newLine.getAccountNumber().equals(bcDoc.getAccountNumber())){
              newLine.setAccountNumber(bcDoc.getAccountNumber());
          }
      }
  
      /**
       * This action changes the value of the hide field in the user interface so that when the page is rendered, the UI knows to show
       * all of the descriptions and labels for each of the pbgl line values.
       *
       * @param mapping
       * @param form
       * @param request
       * @param response
       * @return ActionForward
       * @throws Exception
       */
      public ActionForward showDetails(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          BudgetConstructionForm tForm = (BudgetConstructionForm) form;
          tForm.setHideDetails(false);
          return mapping.findForward(KFSConstants.MAPPING_BASIC);
      }
  
      /**
       * This action toggles the value of the hide field in the user interface to "hide" so that when the page is rendered, the UI
       * displays values without all of the descriptions and labels for each of the pbgl lines.
       *
       * @param mapping
       * @param form
       * @param request
       * @param response
       * @return ActionForward
       * @throws Exception
       */
      public ActionForward hideDetails(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          BudgetConstructionForm tForm = (BudgetConstructionForm) form;
          tForm.setHideDetails(true);
          return mapping.findForward(KFSConstants.MAPPING_BASIC);
      }
  
      public ActionForward toggleAdjustmentMeasurement(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          BudgetConstructionForm docForm = (BudgetConstructionForm) form;
  
          boolean currentStatus = docForm.isHideAdjustmentMeasurement();
          docForm.setHideAdjustmentMeasurement(!currentStatus);
  
          return mapping.findForward(KFSConstants.MAPPING_BASIC);
      }
  
      public ActionForward adjustRevenueLinePercent(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          BudgetConstructionForm docForm = (BudgetConstructionForm) form;
          BudgetConstructionDocument bcDoc = docForm.getBudgetConstructionDocument();
          PendingBudgetConstructionGeneralLedger revLine = bcDoc.getPendingBudgetConstructionGeneralLedgerRevenueLines().get(this.getSelectedLine(request));
  
          if (revLine.getAdjustmentAmount() != null) {
              this.adjustRequest(revLine);
              docForm.populatePBGLLines();
          }
  
          return mapping.findForward(KFSConstants.MAPPING_BASIC);
      }
  
      public ActionForward adjustExpenditureLinePercent(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          BudgetConstructionForm docForm = (BudgetConstructionForm) form;
          BudgetConstructionDocument bcDoc = docForm.getBudgetConstructionDocument();
          PendingBudgetConstructionGeneralLedger expLine = bcDoc.getPendingBudgetConstructionGeneralLedgerExpenditureLines().get(this.getSelectedLine(request));
  
          if (expLine.getAdjustmentAmount() != null) {
              this.adjustRequest(expLine);
              docForm.populatePBGLLines();
          }
  
          return mapping.findForward(KFSConstants.MAPPING_BASIC);
      }
  
      public ActionForward adjustAllRevenueLinesPercent(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          BudgetConstructionForm docForm = (BudgetConstructionForm) form;
          BudgetConstructionDocument bcDoc = docForm.getBudgetConstructionDocument();
          List<PendingBudgetConstructionGeneralLedger> revenueLines = bcDoc.getPendingBudgetConstructionGeneralLedgerRevenueLines();
  
          KualiDecimal adjustmentAmount = docForm.getRevenueAdjustmentAmount();
          if (adjustmentAmount != null) {
  
              // not sure we need this check since the tool isn't displayed in view mode
              boolean isEditable = docForm.isEditAllowed() && !docForm.isSystemViewOnly();
              for (PendingBudgetConstructionGeneralLedger revenueLine : revenueLines) {
                  if (isEditable) {
                      revenueLine.setAdjustmentAmount(adjustmentAmount);
                      this.adjustRequest(revenueLine);
                  }
              }
              if (isEditable){
                  docForm.populatePBGLLines();
              }
          }
  
          return mapping.findForward(KFSConstants.MAPPING_BASIC);
      }
  
      public ActionForward adjustAllExpenditureLinesPercent(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
          BudgetConstructionForm docForm = (BudgetConstructionForm) form;
          BudgetConstructionDocument bcDoc = docForm.getBudgetConstructionDocument();
          List<PendingBudgetConstructionGeneralLedger> expenditureLines = bcDoc.getPendingBudgetConstructionGeneralLedgerExpenditureLines();
  
          KualiDecimal adjustmentAmount = docForm.getExpenditureAdjustmentAmount();
          if (adjustmentAmount != null) {
  
              // not sure we need this check since the tool isn't displayed in view mode
              boolean isEditable = docForm.isEditAllowed() && !docForm.isSystemViewOnly();
              // (!benecalcDisabled && !empty item.laborObject && item.laborObject.financialObjectFringeOrSalaryCode == 'F')
              for (PendingBudgetConstructionGeneralLedger expenditureLine : expenditureLines) {
                  boolean isLineEditable = (isEditable && (docForm.isBenefitsCalculationDisabled() || (expenditureLine.getLaborObject() == null) || !expenditureLine.getLaborObject().getFinancialObjectFringeOrSalaryCode().equalsIgnoreCase(BCConstants.LABOR_OBJECT_FRINGE_CODE)));
                  if (isLineEditable) {
                      expenditureLine.setAdjustmentAmount(adjustmentAmount);
                      this.adjustRequest(expenditureLine);
                  }
              }
              if (isEditable){
                  docForm.populatePBGLLines();
              }
          }
  
          return mapping.findForward(KFSConstants.MAPPING_BASIC);
      }
  
      /**
       * Handles the document (account) pullup action, resetting the cached editingMode as appropriate for the new level.
       *
       * @param mapping
       * @param form
       * @param request
       * @param response
       * @return
       * @throws Exception
       */
      public ActionForward performAccountPullup(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
  