001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.kfs.module.bc.document.web.struts; 017 018 import java.math.BigDecimal; 019 import java.util.Arrays; 020 import java.util.Collections; 021 import java.util.HashMap; 022 import java.util.List; 023 import java.util.Map; 024 import java.util.Properties; 025 026 import javax.servlet.http.HttpServletRequest; 027 import javax.servlet.http.HttpServletResponse; 028 029 import org.apache.commons.lang.StringUtils; 030 import org.apache.struts.action.ActionForm; 031 import org.apache.struts.action.ActionForward; 032 import org.apache.struts.action.ActionMapping; 033 import org.kuali.kfs.module.bc.BCConstants; 034 import org.kuali.kfs.module.bc.BCKeyConstants; 035 import org.kuali.kfs.module.bc.BCPropertyConstants; 036 import org.kuali.kfs.module.bc.BCConstants.LockStatus; 037 import org.kuali.kfs.module.bc.BCConstants.MonthSpreadDeleteType; 038 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionAccountOrganizationHierarchy; 039 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionAuthorizationStatus; 040 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionHeader; 041 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionLockStatus; 042 import org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionGeneralLedger; 043 import org.kuali.kfs.module.bc.document.BudgetConstructionDocument; 044 import org.kuali.kfs.module.bc.document.service.BudgetConstructionMonthlyBudgetsCreateDeleteService; 045 import org.kuali.kfs.module.bc.document.service.BudgetDocumentService; 046 import org.kuali.kfs.module.bc.document.service.LockService; 047 import org.kuali.kfs.module.bc.document.validation.event.AddPendingBudgetGeneralLedgerLineEvent; 048 import org.kuali.kfs.module.bc.document.validation.event.DeletePendingBudgetGeneralLedgerLineEvent; 049 import org.kuali.kfs.module.bc.exception.BudgetConstructionDocumentAuthorizationException; 050 import org.kuali.kfs.module.bc.identity.BudgetConstructionNoAccessMessageSetting; 051 import org.kuali.kfs.sys.KFSConstants; 052 import org.kuali.kfs.sys.KFSKeyConstants; 053 import org.kuali.kfs.sys.KFSPropertyConstants; 054 import org.kuali.kfs.sys.context.SpringContext; 055 import org.kuali.kfs.sys.identity.KfsKimAttributes; 056 import org.kuali.rice.kew.exception.WorkflowException; 057 import org.kuali.rice.kim.bo.Person; 058 import org.kuali.rice.kim.bo.role.dto.KimRoleInfo; 059 import org.kuali.rice.kim.bo.types.dto.AttributeSet; 060 import org.kuali.rice.kim.bo.types.dto.KimTypeInfo; 061 import org.kuali.rice.kim.service.KimTypeInfoService; 062 import org.kuali.rice.kim.service.RoleManagementService; 063 import org.kuali.rice.kim.service.support.KimRoleTypeService; 064 import org.kuali.rice.kim.util.KimConstants; 065 import org.kuali.rice.kns.UserSession; 066 import org.kuali.rice.kns.document.Document; 067 import org.kuali.rice.kns.document.authorization.TransactionalDocumentAuthorizer; 068 import org.kuali.rice.kns.exception.AuthorizationException; 069 import org.kuali.rice.kns.exception.UnknownDocumentIdException; 070 import org.kuali.rice.kns.question.ConfirmationQuestion; 071 import org.kuali.rice.kns.service.BusinessObjectService; 072 import org.kuali.rice.kns.service.DocumentHelperService; 073 import org.kuali.rice.kns.service.KualiConfigurationService; 074 import org.kuali.rice.kns.service.KualiRuleService; 075 import org.kuali.rice.kns.service.PersistenceService; 076 import org.kuali.rice.kns.service.SessionDocumentService; 077 import org.kuali.rice.kns.util.GlobalVariables; 078 import org.kuali.rice.kns.util.KNSConstants; 079 import org.kuali.rice.kns.util.KualiDecimal; 080 import org.kuali.rice.kns.util.KualiInteger; 081 import org.kuali.rice.kns.util.UrlFactory; 082 import org.kuali.rice.kns.web.struts.action.KualiTransactionalDocumentActionBase; 083 import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase; 084 import org.kuali.rice.kns.web.struts.form.KualiForm; 085 import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument; 086 087 /** 088 * need to figure out if this should extend KualiAction, KualiDocumentActionBase or KualiTransactionDocumentActionBase 089 */ 090 public class BudgetConstructionAction extends KualiTransactionalDocumentActionBase { 091 protected static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(BudgetConstructionAction.class); 092 093 /** 094 * Entry point to all actions Checks for cases where methodToCall is loadDocument, performAccountPullup or 095 * performAccountPushdown and creates global messages to describe the new editingMode state. Also handles document locking if 096 * the editingMode is BudgetConstructionEditMode.FULL_ENTRY. (Re)Populates the pullup and pushdown selection controls based on 097 * the current level of the document and the user's approval access for the levels above and below the current level. 098 * 099 * @see org.kuali.rice.kns.web.struts.action.KualiTransactionalDocumentActionBase#execute(org.apache.struts.action.ActionMapping, 100 * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) 101 */ 102 @Override 103 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 104 BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form; 105 106 Boolean isBCHeartBeating = (Boolean) GlobalVariables.getUserSession().retrieveObject(BCConstants.BC_HEARTBEAT_SESSIONFLAG); 107 if (isBCHeartBeating == null) { 108 if (budgetConstructionForm.isPickListMode()) { 109 budgetConstructionForm.setPickListClose(true); 110 GlobalVariables.getMessageList().add(BCKeyConstants.MESSAGE_BUDGET_PREVIOUS_SESSION_TIMEOUT); 111 return mapping.findForward(KFSConstants.MAPPING_BASIC); 112 113 } 114 115 Properties parameters = new Properties(); 116 parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, BCConstants.LOAD_EXPANSION_SCREEN_METHOD_SESSION_TIMEOUT); 117 118 String lookupUrl = UrlFactory.parameterizeUrl("/" + BCConstants.BC_SELECTION_ACTION, parameters); 119 120 return new ActionForward(lookupUrl, true); 121 } 122 123 // this is only used to indicate to the rules the user has clicked save or close save-yes 124 // which forces tighter checks (nonZeroRequest amount) when access is cleanup mode 125 if (budgetConstructionForm.getBudgetConstructionDocument().isCleanupModeActionForceCheck()) { 126 budgetConstructionForm.getBudgetConstructionDocument().setCleanupModeActionForceCheck(Boolean.FALSE); 127 } 128 129 // TODO: the catch code comes from KualiDocumentActionBase.loadDocument() 130 // this allows the top portion of the document to be populated and the close button to function 131 // and also displays all the possible error messages for now 132 // we need to update this once KIM is adjusted to handle BC no access cases 133 // and maybe just show the authorization exception message 134 ActionForward forward = null; 135 try { 136 forward = super.execute(mapping, form, request, response); 137 } 138 catch (AuthorizationException e) { 139 forward = mapping.findForward(KFSConstants.MAPPING_BASIC); 140 String docId = budgetConstructionForm.getDocId(); 141 Document doc = null; 142 doc = getDocumentService().getByDocumentHeaderId(docId); 143 if (doc == null) { 144 throw new UnknownDocumentIdException("Document no longer exists. It may have been cancelled before being saved."); 145 } 146 KualiWorkflowDocument workflowDocument = doc.getDocumentHeader().getWorkflowDocument(); 147 // if (!getDocumentHelperService().getDocumentAuthorizer(doc).canOpen(doc, 148 // GlobalVariables.getUserSession().getPerson())) { 149 // throw buildAuthorizationException("open", doc); 150 // } 151 // re-retrieve the document using the current user's session - remove the system user from the WorkflowDcument object 152 if (workflowDocument != doc.getDocumentHeader().getWorkflowDocument()) { 153 LOG.warn("Workflow document changed via canOpen check"); 154 doc.getDocumentHeader().setWorkflowDocument(workflowDocument); 155 } 156 budgetConstructionForm.setDocument(doc); 157 KualiWorkflowDocument workflowDoc = doc.getDocumentHeader().getWorkflowDocument(); 158 budgetConstructionForm.setDocTypeName(workflowDoc.getDocumentType()); 159 // KualiDocumentFormBase.populate() needs this updated in the session 160 GlobalVariables.getUserSession().setWorkflowDocument(workflowDoc); 161 162 budgetConstructionForm.setSecurityNoAccess(true); 163 setBudgetDocumentNoAccessMessage(budgetConstructionForm); 164 budgetConstructionForm.getDocumentActions().put(KNSConstants.KUALI_ACTION_CAN_CLOSE, Boolean.TRUE); 165 166 } 167 168 // apprise user of granted access 169 if (budgetConstructionForm.getMethodToCall().equals(BCConstants.BC_DOCUMENT_METHOD) || budgetConstructionForm.getMethodToCall().equals(BCConstants.BC_DOCUMENT_PULLUP_METHOD) || budgetConstructionForm.getMethodToCall().equals(BCConstants.BC_DOCUMENT_PUSHDOWN_METHOD)) { 170 171 // init the account org hier state on initial load only - this is stored as hiddens 172 if (budgetConstructionForm.getMethodToCall().equals(BCConstants.BC_DOCUMENT_METHOD)) { 173 budgetConstructionForm.setAccountOrgHierLevels(SpringContext.getBean(BudgetDocumentService.class).getPushPullLevelList(budgetConstructionForm.getBudgetConstructionDocument(), GlobalVariables.getUserSession().getPerson())); 174 } 175 176 if (budgetConstructionForm.isSystemViewOnly()) { 177 GlobalVariables.getMessageList().add(BCKeyConstants.MESSAGE_BUDGET_SYSTEM_VIEW_ONLY); 178 } 179 180 if (!budgetConstructionForm.isEditAllowed()) { 181 GlobalVariables.getMessageList().add(BCKeyConstants.MESSAGE_BUDGET_VIEW_ONLY); 182 } 183 184 if (budgetConstructionForm.isEditAllowed()) { 185 if (budgetConstructionForm.isSystemViewOnly()) { 186 GlobalVariables.getMessageList().add(BCKeyConstants.MESSAGE_BUDGET_VIEW_ONLY); 187 } 188 else { 189 190 // tell the user if the document is in not budgetable mode 191 budgetConstructionForm.getBudgetConstructionDocument().setBudgetableDocument(SpringContext.getBean(BudgetDocumentService.class).isBudgetableDocumentNoWagesCheck(budgetConstructionForm.getBudgetConstructionDocument())); 192 // budgetConstructionForm.setBudgetableDocument(SpringContext.getBean(BudgetDocumentService.class).isBudgetableDocumentNoWagesCheck(budgetConstructionForm.getBudgetConstructionDocument())); 193 if (!budgetConstructionForm.isBudgetableDocument()) { 194 GlobalVariables.getMessageList().add(BCKeyConstants.MESSAGE_BUDGET_DOCUMENT_NOT_BUDGETABLE); 195 } 196 197 GlobalVariables.getMessageList().add(BCKeyConstants.MESSAGE_BUDGET_EDIT_ACCESS); 198 } 199 200 if (!budgetConstructionForm.isSystemViewOnly()) { 201 LockService lockService = SpringContext.getBean(LockService.class); 202 HashMap primaryKey = new HashMap(); 203 primaryKey.put(KFSPropertyConstants.DOCUMENT_NUMBER, budgetConstructionForm.getDocument().getDocumentNumber()); 204 205 BudgetConstructionHeader budgetConstructionHeader = (BudgetConstructionHeader) SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(BudgetConstructionHeader.class, primaryKey); 206 if (budgetConstructionHeader != null) { 207 // BudgetConstructionLockStatus bcLockStatus = lockService.lockAccount(budgetConstructionHeader, 208 // GlobalVariables.getUserSession().getPerson().getPrincipalId()); 209 BudgetConstructionLockStatus bcLockStatus = lockService.lockAccountAndCommit(budgetConstructionHeader, GlobalVariables.getUserSession().getPerson().getPrincipalId()); 210 211 if (bcLockStatus.getLockStatus() == LockStatus.SUCCESS) { 212 213 // update the document version number 214 // so the saved lock of header doesn't produce an optimistic lock error 215 // and has the info we just put in the header so doc save doesn't wipe out the lock 216 budgetConstructionForm.getBudgetConstructionDocument().setVersionNumber(bcLockStatus.getBudgetConstructionHeader().getVersionNumber()); 217 budgetConstructionForm.getBudgetConstructionDocument().setBudgetLockUserIdentifier(bcLockStatus.getBudgetConstructionHeader().getBudgetLockUserIdentifier()); 218 } 219 else { 220 if (bcLockStatus.getLockStatus() == LockStatus.BY_OTHER) { 221 String lockerName = SpringContext.getBean(org.kuali.rice.kim.service.PersonService.class).getPerson(bcLockStatus.getAccountLockOwner()).getName(); 222 this.cleanupForLockError(budgetConstructionForm); 223 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, BCKeyConstants.ERROR_BUDGET_DOCUMENT_LOCKED, lockerName); 224 return forward; 225 } 226 else { 227 if (bcLockStatus.getLockStatus() == LockStatus.FLOCK_FOUND) { 228 this.cleanupForLockError(budgetConstructionForm); 229 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, BCKeyConstants.ERROR_BUDGET_FUNDING_LOCKED); 230 return forward; 231 } 232 else { 233 this.cleanupForLockError(budgetConstructionForm); 234 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, BCKeyConstants.ERROR_BUDGET_DOCUMENT_OTHER); 235 return forward; 236 } 237 } 238 } 239 } 240 else { 241 // unlikely 242 throw new BudgetConstructionDocumentAuthorizationException(GlobalVariables.getUserSession().getPerson().getName(), "open", budgetConstructionForm.getDocument().getDocumentHeader().getDocumentNumber(), "(can't find document for locking)", budgetConstructionForm.isPickListMode()); 243 } 244 245 // if editing, check if 2plg adjustment needed and calc benefits 246 // since checkTwoPlugAdjusmtent will only be set in docHandler during initial load 247 // if document is initially view only we want the 2plg adjustment to happen if the user does a pullup to edit 248 if (budgetConstructionForm.isCheckTwoPlugAdjustment() && budgetConstructionForm.getBudgetConstructionDocument().isContainsTwoPlug() && !budgetConstructionForm.getBudgetConstructionDocument().isSalarySettingOnly()) { 249 // do 2plg related benefits calc and adjust 2plg for any diff - reset checkTwoPlugAdjusment 250 budgetConstructionForm.setCheckTwoPlugAdjustment(false); 251 this.adjustForSalarySettingChanges(budgetConstructionForm); 252 } 253 } 254 255 // getting here implies a lock or system view mode, try to build a pullup list 256 // pushdown is only allowed if user has edit access (regardless of system view only mode) 257 if (budgetConstructionForm.getBudgetConstructionDocument().getOrganizationLevelCode() != 0) { 258 if (!budgetConstructionForm.getAccountOrgHierLevels().isEmpty()) { 259 budgetConstructionForm.populatePushPullLevelKeyLabels(budgetConstructionForm.getBudgetConstructionDocument(), budgetConstructionForm.getAccountOrgHierLevels(), false); 260 } 261 } 262 } // FULL_ENTRY 263 264 // pullup is allowed regardless of editMode 265 if (!budgetConstructionForm.getAccountOrgHierLevels().isEmpty()) { 266 budgetConstructionForm.populatePushPullLevelKeyLabels(budgetConstructionForm.getBudgetConstructionDocument(), budgetConstructionForm.getAccountOrgHierLevels(), true); 267 } 268 } 269 270 // cleanup the session edit mode store so we don't side effect organization salary setting 271 if (budgetConstructionForm.isClosingDocument()) { 272 GlobalVariables.getUserSession().removeObject(BCConstants.BC_DOC_AUTHORIZATION_STATUS_SESSIONKEY); 273 } 274 275 return forward; 276 } 277 278 /** 279 * Finds the role type service associated with the document viewer role, than calls method on role type service to set the no 280 * access message 281 * 282 * @param budgetConstructionForm form containing budget document 283 */ 284 protected void setBudgetDocumentNoAccessMessage(BudgetConstructionForm budgetConstructionForm) { 285 KimRoleInfo roleInfo = SpringContext.getBean(RoleManagementService.class).getRoleByName(BCConstants.BUDGET_CONSTRUCTION_NAMESPACE, BCConstants.KimConstants.DOCUMENT_VIEWER_ROLE_NAME); 286 KimTypeInfo typeInfo = SpringContext.getBean(KimTypeInfoService.class).getKimType(roleInfo.getKimTypeId()); 287 288 if (StringUtils.isNotBlank(typeInfo.getKimTypeServiceName())) { 289 KimRoleTypeService roleTypeService = (KimRoleTypeService) SpringContext.getService(typeInfo.getKimTypeServiceName()); 290 if (roleTypeService instanceof BudgetConstructionNoAccessMessageSetting) { 291 ((BudgetConstructionNoAccessMessageSetting) roleTypeService).setNoAccessMessage(budgetConstructionForm.getBudgetConstructionDocument(), GlobalVariables.getUserSession().getPerson(), GlobalVariables.getMessageMap()); 292 } 293 } 294 } 295 296 /** 297 * gwp - no call to super, need to work through command we will use randall - This method might be unnecessary, but putting it 298 * here allows URL to be consistent with Document URLs gwp - i think we still want this method, just need to figure out if we 299 * use command initiate or displayDocSearchView or something else. i expect we will get the account/subaccount or docnumber from 300 * the previous form and assume the document will already exist regardless of creation by genesis or 301 * 302 * @param mapping 303 * @param form 304 * @param request 305 * @param response 306 * @return 307 * @throws IOException 308 * @throws ServletException 309 */ 310 @Override 311 public ActionForward docHandler(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 312 BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form; 313 314 loadDocument(budgetConstructionForm); 315 316 // set flag to have execute perform 2plug adjusment if the doc goes into edit mode later 317 budgetConstructionForm.setCheckTwoPlugAdjustment(true); 318 319 this.initAuthorization(budgetConstructionForm); 320 321 return mapping.findForward(KFSConstants.MAPPING_BASIC); 322 } 323 324 /** 325 * Initially load the document from the DB Coded this to look like KualiDocumentActionBase.loadDocument() 326 * 327 * @param budgetConstructionForm 328 * @throws WorkflowException 329 */ 330 @Override 331 protected void loadDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException { 332 BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) kualiDocumentFormBase; 333 334 BudgetConstructionHeader budgetConstructionHeader; 335 if (budgetConstructionForm.getDocId() != null) { 336 Map<String, Object> primaryKey = new HashMap<String, Object>(); 337 primaryKey.put(KFSPropertyConstants.DOCUMENT_NUMBER, budgetConstructionForm.getDocId()); 338 339 budgetConstructionHeader = (BudgetConstructionHeader) SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(BudgetConstructionHeader.class, primaryKey); 340 341 } 342 else { 343 // use the passed url autoloaded parms to get the record from DB 344 // BudgetConstructionDaoOjb bcHeaderDao; 345 String chartOfAccountsCode = budgetConstructionForm.getChartOfAccountsCode(); 346 String accountNumber = budgetConstructionForm.getAccountNumber(); 347 String subAccountNumber = budgetConstructionForm.getSubAccountNumber(); 348 Integer universityFiscalYear = budgetConstructionForm.getUniversityFiscalYear(); 349 350 budgetConstructionHeader = (BudgetConstructionHeader) SpringContext.getBean(BudgetDocumentService.class).getByCandidateKey(chartOfAccountsCode, accountNumber, subAccountNumber, universityFiscalYear); 351 } 352 353 kualiDocumentFormBase.setDocId(budgetConstructionHeader.getDocumentNumber()); 354 super.loadDocument(kualiDocumentFormBase); 355 356 BudgetConstructionDocument budgetConstructionDocument = (BudgetConstructionDocument) kualiDocumentFormBase.getDocument(); 357 358 // init the benefits calc flags 359 budgetConstructionDocument.setBenefitsCalcNeeded(false); 360 budgetConstructionDocument.setMonthlyBenefitsCalcNeeded(false); 361 362 // init the new line objects 363 budgetConstructionForm.initNewLine(budgetConstructionForm.getNewRevenueLine(), true); 364 budgetConstructionForm.initNewLine(budgetConstructionForm.getNewExpenditureLine(), false); 365 366 // need this here to do totaling on initial load 367 budgetConstructionForm.populatePBGLLines(); 368 budgetConstructionForm.initializePersistedRequestAmounts(); 369 } 370 371 /** 372 * Cleans up state info to handle no access lock errors 373 * 374 * @param budgetConstructionForm 375 */ 376 protected void cleanupForLockError(BudgetConstructionForm budgetConstructionForm) { 377 budgetConstructionForm.setSecurityNoAccess(true); 378 budgetConstructionForm.getDocumentActions().remove(KNSConstants.KUALI_ACTION_CAN_EDIT); 379 budgetConstructionForm.getDocumentActions().remove(KNSConstants.KUALI_ACTION_CAN_SAVE); 380 GlobalVariables.getMessageList().remove(BCKeyConstants.MESSAGE_BUDGET_EDIT_ACCESS); 381 } 382 383 /** 384 * Override to set authorization Maps from session 385 * 386 * @see org.kuali.rice.kns.web.struts.action.KualiTransactionalDocumentActionBase#populateAuthorizationFields(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase) 387 */ 388 @Override 389 protected void populateAuthorizationFields(KualiDocumentFormBase formBase) { 390 BudgetConstructionAuthorizationStatus authorizationStatus = (BudgetConstructionAuthorizationStatus) GlobalVariables.getUserSession().retrieveObject(BCConstants.BC_DOC_AUTHORIZATION_STATUS_SESSIONKEY); 391 392 if (authorizationStatus == null) { 393 // execute handles any session timeout before this is called 394 return; 395 } 396 397 formBase.setDocumentActions(authorizationStatus.getDocumentActions()); 398 formBase.setEditingMode(authorizationStatus.getEditingMode()); 399 } 400 401 /** 402 * Calls authorizer to determine if the user has edit permission and checks if budget construction is active is fiscal year 403 * function table. Then updates the <code>BudgetConstructionEditStatus</code> in session. Finally updates authorization in the 404 * form 405 * 406 * @param budgetConstructionForm current bc action form that will be updated 407 */ 408 protected void initAuthorization(BudgetConstructionForm budgetConstructionForm) { 409 // GlobalVariables.setRequestCache(ROLE_QUALIFICATION_CACHE_NAME, budgetConstructionForm) 410 super.populateAuthorizationFields(budgetConstructionForm); 411 412 BudgetConstructionAuthorizationStatus editStatus = new BudgetConstructionAuthorizationStatus(); 413 editStatus.setDocumentActions(budgetConstructionForm.getDocumentActions()); 414 editStatus.setEditingMode(budgetConstructionForm.getEditingMode()); 415 416 GlobalVariables.getUserSession().addObject(BCConstants.BC_DOC_AUTHORIZATION_STATUS_SESSIONKEY, editStatus); 417 } 418 419 /** 420 * Applies adjustments due to 2plg existence at initial load or detected salary setting changes upon returning from the Quick 421 * Salary Setting screen. The adjustments consist of calculating benefits and adding any expenditure total before/after 422 * difference back into a 2plg row, creating or updating as needed. Then, validation is performed. Sucessful validation removes 423 * the 2plg row if the final, post benefits calc, adjusted amount is zero. This method assumes the set of expenditure rows in 424 * memory currently matches the DB. 425 * 426 * @param bcForm 427 */ 428 protected void adjustForSalarySettingChanges(BudgetConstructionForm bcForm) { 429 430 BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class); 431 BudgetConstructionDocument bcDoc = (BudgetConstructionDocument) bcForm.getDocument(); 432 KualiInteger oldRequestAmount = bcDoc.getExpenditureAccountLineAnnualBalanceAmountTotal(); 433 434 // calc benefits also handles setting persisted amounts and populating reloaded benefit rows 435 budgetDocumentService.calculateBenefits(bcDoc); 436 // bcForm.initializePersistedRequestAmounts(); 437 438 // repop and refresh refs - esp monthly so jsp can properly display state 439 // bcForm.populatePBGLLines(); 440 441 // need 2plg adjustment and save, even if it is zero 442 KualiInteger newRquestAmount = bcForm.getBudgetConstructionDocument().getExpenditureAccountLineAnnualBalanceAmountTotal(); 443 PendingBudgetConstructionGeneralLedger twoPlugRow = budgetDocumentService.updatePendingBudgetGeneralLedgerPlug(bcDoc, newRquestAmount.subtract(oldRequestAmount)); 444 } 445 446 /** 447 * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#close(org.apache.struts.action.ActionMapping, 448 * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) 449 */ 450 @Override 451 public ActionForward close(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 452 453 // return super.close(mapping, form, request, response); 454 BudgetConstructionForm docForm = (BudgetConstructionForm) form; 455 456 // only want to prompt them to save if they already can save 457 if (docForm.getDocumentActions().keySet().contains(KNSConstants.KUALI_ACTION_CAN_SAVE)) { 458 Object question = request.getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME); 459 KualiConfigurationService kualiConfiguration = SpringContext.getBean(KualiConfigurationService.class); 460 461 // logic for close question 462 if (question == null) { 463 // ask question if not already asked 464 return this.performQuestionWithoutInput(mapping, form, request, response, KFSConstants.DOCUMENT_SAVE_BEFORE_CLOSE_QUESTION, kualiConfiguration.getPropertyString(KFSKeyConstants.QUESTION_SAVE_BEFORE_CLOSE), KFSConstants.CONFIRMATION_QUESTION, KFSConstants.MAPPING_CLOSE, ""); 465 } 466 else { 467 Object buttonClicked = request.getParameter(KFSConstants.QUESTION_CLICKED_BUTTON); 468 if ((KFSConstants.DOCUMENT_SAVE_BEFORE_CLOSE_QUESTION.equals(question)) && ConfirmationQuestion.YES.equals(buttonClicked)) { 469 // if yes button clicked - save the doc 470 BudgetConstructionDocument bcDoc = (BudgetConstructionDocument) docForm.getDocument(); 471 472 // force tighter checks when saving in cleanup mode 473 if (!bcDoc.isBudgetableDocument()) { 474 bcDoc.setCleanupModeActionForceCheck(Boolean.TRUE); 475 } 476 477 // SpringContext.getBean(DocumentService.class).updateDocument(docForm.getDocument()); 478 BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class); 479 budgetDocumentService.saveDocument(bcDoc); 480 docForm.initializePersistedRequestAmounts(); 481 if (bcDoc.isBenefitsCalcNeeded() || bcDoc.isMonthlyBenefitsCalcNeeded()) { 482 budgetDocumentService.calculateBenefitsIfNeeded(bcDoc); 483 484 GlobalVariables.getMessageList().add(KFSKeyConstants.MESSAGE_SAVED); 485 return mapping.findForward(KFSConstants.MAPPING_BASIC); 486 } 487 else { 488 // else drop to close logic below 489 } 490 491 } 492 // else drop to close logic below 493 } 494 } 495 496 // do the unlock if they have full access and not system view mode 497 if (docForm.isEditAllowed() && !docForm.isSystemViewOnly()) { 498 LockService lockService = SpringContext.getBean(LockService.class); 499 HashMap primaryKey = new HashMap(); 500 primaryKey.put(KFSPropertyConstants.DOCUMENT_NUMBER, docForm.getDocument().getDocumentNumber()); 501 502 BudgetConstructionHeader budgetConstructionHeader = (BudgetConstructionHeader) SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(BudgetConstructionHeader.class, primaryKey); 503 if (budgetConstructionHeader != null) { 504 LockStatus lockStatus = lockService.unlockAccount(budgetConstructionHeader); 505 } 506 else { 507 // unlikely, but benign problem here 508 } 509 } 510 511 // flag to cleanup the session edit mode store so we don't side effect organization salary setting 512 // used in the bottom of execute() 513 docForm.setClosingDocument(Boolean.TRUE); 514 515 if (docForm.isPickListMode()) { 516 // redisplay with a message 517 GlobalVariables.getMessageList().add(BCKeyConstants.MESSAGE_BUDGET_SUCCESSFUL_CLOSE); 518 docForm.setPickListClose(true); 519 520 // this is a hack to do our own session document cleanup since refreshCaller=QuestionRefresh 521 // prevents proper cleanup in KualiRequestProcessor.processActionPerform() 522 UserSession userSession = (UserSession) request.getSession().getAttribute(KNSConstants.USER_SESSION_KEY); 523 String docFormKey = docForm.getFormKey(); 524 SpringContext.getBean(SessionDocumentService.class).purgeDocumentForm(docForm.getDocument().getDocumentNumber(), docFormKey, userSession, request.getRemoteAddr()); 525 526 return mapping.findForward(KFSConstants.MAPPING_BASIC); 527 528 } 529 else { 530 if (docForm.getReturnFormKey() == null) { 531 532 // assume called from doc search or lost the session - go back to main 533 return returnToSender(request, mapping, docForm); 534 } 535 else { 536 // setup the return parms for the document and anchor and go back to doc select 537 Properties parameters = new Properties(); 538 parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, BCConstants.BC_SELECTION_REFRESH_METHOD); 539 parameters.put(KFSConstants.DOC_FORM_KEY, docForm.getReturnFormKey()); 540 parameters.put(KFSConstants.ANCHOR, docForm.getReturnAnchor()); 541 parameters.put(KFSConstants.REFRESH_CALLER, BCConstants.BC_DOCUMENT_REFRESH_CALLER); 542 543 String lookupUrl = UrlFactory.parameterizeUrl("/" + BCConstants.BC_SELECTION_ACTION, parameters); 544 545 // this is a hack to do our own session document cleanup since refreshCaller=QuestionRefresh 546 // prevents proper cleanup in KualiRequestProcessor.processActionPerform() 547 UserSession userSession = (UserSession) request.getSession().getAttribute(KNSConstants.USER_SESSION_KEY); 548 String docFormKey = docForm.getFormKey(); 549 SpringContext.getBean(SessionDocumentService.class).purgeDocumentForm(docForm.getDocument().getDocumentNumber(), docFormKey, userSession, request.getRemoteAddr()); 550 551 return new ActionForward(lookupUrl, true); 552 } 553 } 554 } 555 556 /** 557 * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#save(org.apache.struts.action.ActionMapping, 558 * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) 559 */ 560 @Override 561 public ActionForward save(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 562 563 BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form; 564 BudgetConstructionDocument bcDocument = (BudgetConstructionDocument) budgetConstructionForm.getDocument(); 565 // DocumentService documentService = SpringContext.getBean(DocumentService.class); 566 BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class); 567 568 // force tighter checks when saving in cleanup mode 569 if (!bcDocument.isBudgetableDocument()) { 570 bcDocument.setCleanupModeActionForceCheck(Boolean.TRUE); 571 } 572 573 budgetDocumentService.saveDocument(bcDocument); 574 budgetConstructionForm.initializePersistedRequestAmounts(); 575 budgetDocumentService.calculateBenefitsIfNeeded(bcDocument); 576 GlobalVariables.getMessageList().add(KFSKeyConstants.MESSAGE_SAVED); 577 578 budgetConstructionForm.setAnnotation(""); 579 580 // redisplay the document along with document saved message 581 return mapping.findForward(KFSConstants.MAPPING_BASIC); 582 } 583 584 /** 585 * Calls the single line benefits impact screen by setting up the required parameters and feeding them to the temporary list 586 * lookup action for the expenditure line selected. This is called from the ShowBenefits button on the BC document screen when 587 * an expenditure line is associated with benefits and benefits calculation is enabled. 588 * 589 * @param mapping 590 * @param form 591 * @param request 592 * @param response 593 * @return 594 * @throws Exception 595 */ 596 public ActionForward performShowBenefits(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 597 598 BudgetConstructionForm tForm = (BudgetConstructionForm) form; 599 BudgetConstructionDocument tDoc = tForm.getBudgetConstructionDocument(); 600 int selectIndex = this.getSelectedLine(request); 601 PendingBudgetConstructionGeneralLedger expLine = tDoc.getPendingBudgetConstructionGeneralLedgerExpenditureLines().get(selectIndex); 602 603 // when we return from the lookup, our next request's method to call is going to be refresh 604 tForm.registerEditableProperty(KNSConstants.DISPATCH_REQUEST_PARAMETER); 605 606 Properties parameters = new Properties(); 607 parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, KFSConstants.START_METHOD); 608 609 String basePath = SpringContext.getBean(KualiConfigurationService.class).getPropertyString(KFSConstants.APPLICATION_URL_KEY); 610 parameters.put(KFSConstants.BACK_LOCATION, basePath + mapping.getPath() + ".do"); 611 612 if (StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) { 613 parameters.put(BCConstants.RETURN_ANCHOR, ((KualiForm) form).getAnchor()); 614 } 615 616 // this hack sets the return anchor we want to return too after the inquiry 617 // do this here so it gets into the session stored form version 618 // refresh checks for this after and resets the anchor 619 if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) { 620 tForm.setBalanceInquiryReturnAnchor(((KualiForm) form).getAnchor()); 621 } 622 623 parameters.put(KNSConstants.DOC_FORM_KEY, GlobalVariables.getUserSession().addObject(form, BCConstants.FORMKEY_PREFIX)); 624 parameters.put(KFSConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, BCConstants.REQUEST_BENEFITS_BO); 625 parameters.put(KFSConstants.HIDE_LOOKUP_RETURN_LINK, "true"); 626 parameters.put(KFSConstants.SUPPRESS_ACTIONS, "true"); 627 parameters.put(BCConstants.SHOW_INITIAL_RESULTS, "true"); 628 parameters.put(BCConstants.TempListLookupMode.TEMP_LIST_LOOKUP_MODE, Integer.toString(BCConstants.TempListLookupMode.SHOW_BENEFITS)); 629 630 parameters.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, expLine.getUniversityFiscalYear().toString()); 631 parameters.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, expLine.getChartOfAccountsCode()); 632 parameters.put(KFSConstants.FINANCIAL_OBJECT_CODE_PROPERTY_NAME, expLine.getFinancialObjectCode()); 633 parameters.put(KFSPropertyConstants.ACCOUNT_LINE_ANNUAL_BALANCE_AMOUNT, expLine.getAccountLineAnnualBalanceAmount().toString()); 634 parameters.put(KNSConstants.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); 635 636 String url = UrlFactory.parameterizeUrl(basePath + "/" + BCConstants.ORG_TEMP_LIST_LOOKUP, parameters); 637 this.setupDocumentExit(); 638 return new ActionForward(url, true); 639 } 640 641 public ActionForward performBalanceInquiryForRevenueLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 642 return performBalanceInquiry(true, mapping, form, request, response); 643 } 644 645 public ActionForward performBalanceInquiryForExpenditureLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 646 return performBalanceInquiry(false, mapping, form, request, response); 647 } 648 649 /** 650 * This method is similar to org.kuali.kfs.sys.web.struts.KualiAccountingDocumentActionBase.performBalanceInquiry() 651 * 652 * @param isRevenue 653 * @param mapping 654 * @param form 655 * @param request 656 * @param response 657 * @return 658 * @throws Exception 659 */ 660 public ActionForward performBalanceInquiry(boolean isRevenue, ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 661 final String docNumber; 662 663 // get the selected line, setup parms and redirect to balance inquiry 664 BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form; 665 BudgetConstructionDocument bcDocument = (BudgetConstructionDocument) budgetConstructionForm.getDocument(); 666 667 // when we return from the lookup, our next request's method to call is going to be refresh 668 budgetConstructionForm.registerEditableProperty(KNSConstants.DISPATCH_REQUEST_PARAMETER); 669 670 PendingBudgetConstructionGeneralLedger pbglLine; 671 if (isRevenue) { 672 pbglLine = bcDocument.getPendingBudgetConstructionGeneralLedgerRevenueLines().get(this.getSelectedLine(request)); 673 } 674 else { 675 pbglLine = bcDocument.getPendingBudgetConstructionGeneralLedgerExpenditureLines().get(this.getSelectedLine(request)); 676 } 677 678 // build out base path for return location, use config service 679 String basePath = SpringContext.getBean(KualiConfigurationService.class).getPropertyString(KFSConstants.APPLICATION_URL_KEY); 680 681 // this hack sets the return anchor we want to return too after the inquiry 682 // do this here so it gets into the session stored form version 683 // refresh checks for this after and resets the anchor 684 if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) { 685 budgetConstructionForm.setBalanceInquiryReturnAnchor(((KualiForm) form).getAnchor()); 686 } 687 688 // build out the actual form key that will be used to retrieve the form on refresh 689 String callerDocFormKey = GlobalVariables.getUserSession().addObject(form, BCConstants.FORMKEY_PREFIX); 690 691 // now add required parameters 692 Properties parameters = new Properties(); 693 parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, KFSConstants.START_METHOD); 694 // need this next param b/c the lookup's return back will overwrite 695 // the original doc form key 696 parameters.put(KFSConstants.BALANCE_INQUIRY_REPORT_MENU_CALLER_DOC_FORM_KEY, callerDocFormKey); 697 parameters.put(KFSConstants.DOC_FORM_KEY, callerDocFormKey); 698 parameters.put(KFSConstants.BACK_LOCATION, basePath + mapping.getPath() + ".do"); 699 700 // anchor, if it exists 701 // this doesn't seem to work with the balance inquiry infrastructure, so added hack above 702 if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) { 703 parameters.put(BCConstants.RETURN_ANCHOR, ((KualiForm) form).getAnchor()); 704 } 705 706 if (StringUtils.isNotBlank(pbglLine.getChartOfAccountsCode())) { 707 parameters.put("chartOfAccountsCode", pbglLine.getChartOfAccountsCode()); 708 } 709 if (StringUtils.isNotBlank(pbglLine.getAccountNumber())) { 710 parameters.put("accountNumber", pbglLine.getAccountNumber()); 711 } 712 if (StringUtils.isNotBlank(pbglLine.getFinancialObjectCode())) { 713 parameters.put("financialObjectCode", pbglLine.getFinancialObjectCode()); 714 } 715 if (StringUtils.isNotBlank(pbglLine.getSubAccountNumber())) { 716 parameters.put("subAccountNumber", pbglLine.getSubAccountNumber()); 717 } 718 if (StringUtils.isNotBlank(pbglLine.getFinancialSubObjectCode())) { 719 parameters.put("financialSubObjectCode", pbglLine.getFinancialSubObjectCode()); 720 } 721 722 String lookupUrl = UrlFactory.parameterizeUrl(basePath + "/" + KFSConstants.BALANCE_INQUIRY_REPORT_MENU_ACTION, parameters); 723 724 this.setupDocumentExit(); 725 return new ActionForward(lookupUrl, true); 726 } 727 728 /** 729 * Calls performMonthlyBudget for the selected revenue line 730 * 731 * @param mapping 732 * @param form 733 * @param request 734 * @param response 735 * @return 736 * @throws Exception 737 */ 738 public ActionForward performMonthlyRevenueBudget(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 739 return performMonthlyBudget(true, mapping, form, request, response); 740 } 741 742 /** 743 * Calls performMonthlyBudget for the selected expenditure line 744 * 745 * @param mapping 746 * @param form 747 * @param request 748 * @param response 749 * @return 750 * @throws Exception 751 */ 752 public ActionForward performMonthlyExpenditureBudget(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 753 return performMonthlyBudget(false, mapping, form, request, response); 754 } 755 756 /** 757 * Forwards the user to the monthly budget screen. Doing this in edit mode causes the document to be validated, saved and 758 * benefits calculated (if needed). 759 * 760 * @param isRevenue 761 * @param mapping 762 * @param form 763 * @param request 764 * @param response 765 * @return 766 * @throws Exception 767 */ 768 public ActionForward performMonthlyBudget(boolean isRevenue, ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 769 final String docNumber; 770 771 // this to checks for 2PLG and turns off SS/monthly RI check if found 772 // the final save after removing 2PLG will catch any monthly discrepencies 773 // also need to save object,subobject key we are operating on so refresh can get the latest row version from DB 774 775 // validate, save, etc first then goto the monthly screen or redisplay if errors 776 BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form; 777 BudgetConstructionDocument bcDocument = (BudgetConstructionDocument) budgetConstructionForm.getDocument(); 778 779 PendingBudgetConstructionGeneralLedger pbglLine; 780 if (isRevenue) { 781 pbglLine = bcDocument.getPendingBudgetConstructionGeneralLedgerRevenueLines().get(this.getSelectedLine(request)); 782 } 783 else { 784 pbglLine = bcDocument.getPendingBudgetConstructionGeneralLedgerExpenditureLines().get(this.getSelectedLine(request)); 785 } 786 787 // when we return from the lookup, our next request's method to call is going to be refresh 788 budgetConstructionForm.registerEditableProperty(KNSConstants.DISPATCH_REQUEST_PARAMETER); 789 790 if (budgetConstructionForm.isEditAllowed() && !budgetConstructionForm.isSystemViewOnly()) { 791 BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class); 792 793 // if the doc contains a 2plg line, turn off RI checking to allow cleanup. 794 // The act of attempting to remove a 2plg (delete) forces a complete RI check. 795 // The document is assumed inconsistent as long as a 2plg exists. 796 if (!isRevenue && bcDocument.isContainsTwoPlug()) { 797 if (pbglLine.getLaborObject() != null && pbglLine.getLaborObject().isDetailPositionRequiredIndicator()) { 798 budgetDocumentService.saveDocumentNoWorkFlow(bcDocument, MonthSpreadDeleteType.EXPENDITURE, false); 799 } 800 else { 801 budgetDocumentService.saveDocumentNoWorkFlow(bcDocument, MonthSpreadDeleteType.EXPENDITURE, true); 802 } 803 } 804 else { 805 budgetDocumentService.saveDocumentNoWorkflow(bcDocument); 806 807 } 808 budgetConstructionForm.initializePersistedRequestAmounts(); 809 budgetDocumentService.calculateBenefitsIfNeeded(bcDocument); 810 811 // repop and refresh refs - esp monthly so jsp can properly display state 812 // budgetConstructionForm.populatePBGLLines(); 813 814 } 815 816 // String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + 817 // request.getContextPath(); 818 String basePath = SpringContext.getBean(KualiConfigurationService.class).getPropertyString(KFSConstants.APPLICATION_URL_KEY); 819 Properties parameters = new Properties(); 820 parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, BCConstants.MONTHLY_BUDGET_METHOD); 821 parameters.put(KFSConstants.BACK_LOCATION, basePath + mapping.getPath() + ".do"); 822 parameters.put("documentNumber", pbglLine.getDocumentNumber()); 823 parameters.put("universityFiscalYear", pbglLine.getUniversityFiscalYear().toString()); 824 parameters.put("chartOfAccountsCode", pbglLine.getChartOfAccountsCode()); 825 parameters.put("accountNumber", pbglLine.getAccountNumber()); 826 parameters.put("subAccountNumber", pbglLine.getSubAccountNumber()); 827 parameters.put("financialObjectCode", pbglLine.getFinancialObjectCode()); 828 parameters.put("financialSubObjectCode", pbglLine.getFinancialSubObjectCode()); 829 parameters.put("financialBalanceTypeCode", pbglLine.getFinancialBalanceTypeCode()); 830 parameters.put("financialObjectTypeCode", pbglLine.getFinancialObjectTypeCode()); 831 parameters.put(BCPropertyConstants.MAIN_WINDOW, (budgetConstructionForm.isMainWindow() ? "true" : "false")); 832 833 // anchor, if it exists 834 if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) { 835 parameters.put(BCConstants.RETURN_ANCHOR, ((KualiForm) form).getAnchor()); 836 } 837 838 // the form object is retrieved and removed upon return by KualiRequestProcessor.processActionForm() 839 parameters.put(BCConstants.RETURN_FORM_KEY, GlobalVariables.getUserSession().addObject(form, BCConstants.FORMKEY_PREFIX)); 840 841 String lookupUrl = UrlFactory.parameterizeUrl(basePath + "/" + BCConstants.MONTHLY_BUDGET_ACTION, parameters); 842 this.setupDocumentExit(); 843 return new ActionForward(lookupUrl, true); 844 } 845 846 /** 847 * Forwards the user to the quick salary setting screen. Doing this in edit mode causes the document to be validated, saved and 848 * benefits calculated (if needed). 849 * 850 * @param mapping 851 * @param form 852 * @param request 853 * @param response 854 * @return 855 * @throws Exception 856 */ 857 public ActionForward performSalarySetting(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 858 final String docNumber; 859 860 // this to checks for 2PLG and turns off monthly RI check if found 861 // the final save after removing 2PLG will catch any monthly discrepencies 862 863 // validate, save, etc first then goto the SalarySetting screen or redisplay if errors 864 BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form; 865 BudgetConstructionDocument bcDocument = (BudgetConstructionDocument) budgetConstructionForm.getDocument(); 866 867 // when we return from the lookup, our next request's method to call is going to be refresh 868 budgetConstructionForm.registerEditableProperty(KNSConstants.DISPATCH_REQUEST_PARAMETER); 869 870 if (budgetConstructionForm.isEditAllowed() && !budgetConstructionForm.isSystemViewOnly()) { 871 BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class); 872 873 // if the doc contains a 2plg line, turn off RI checking to allow cleanup. 874 // The act of attempting to remove a 2plg (delete) forces a complete RI check. 875 // The document is assumed inconsistent as long as a 2plg exists. 876 if (bcDocument.isContainsTwoPlug()) { 877 budgetDocumentService.saveDocumentNoWorkFlow(bcDocument, MonthSpreadDeleteType.EXPENDITURE, false); 878 } 879 else { 880 budgetDocumentService.saveDocumentNoWorkflow(bcDocument); 881 } 882 883 // init persisted property and get the current list of salary setting related rows 884 budgetConstructionForm.initializePersistedRequestAmounts(true); 885 886 budgetDocumentService.calculateBenefitsIfNeeded(bcDocument); 887 888 // repop and refresh refs - esp monthly so jsp can properly display state 889 // budgetConstructionForm.populatePBGLLines(); 890 891 } 892 PendingBudgetConstructionGeneralLedger pbglLine; 893 pbglLine = bcDocument.getPendingBudgetConstructionGeneralLedgerExpenditureLines().get(this.getSelectedLine(request)); 894 895 // String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + 896 // request.getContextPath(); 897 String basePath = SpringContext.getBean(KualiConfigurationService.class).getPropertyString(KFSConstants.APPLICATION_URL_KEY); 898 Properties parameters = new Properties(); 899 parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, BCConstants.QUICK_SALARY_SETTING_METHOD); 900 parameters.put(KFSConstants.BACK_LOCATION, basePath + mapping.getPath() + ".do"); 901 902 parameters.put("documentNumber", pbglLine.getDocumentNumber()); 903 parameters.put("universityFiscalYear", pbglLine.getUniversityFiscalYear().toString()); 904 parameters.put("chartOfAccountsCode", pbglLine.getChartOfAccountsCode()); 905 parameters.put("accountNumber", pbglLine.getAccountNumber()); 906 parameters.put("subAccountNumber", pbglLine.getSubAccountNumber()); 907 parameters.put("financialObjectCode", pbglLine.getFinancialObjectCode()); 908 parameters.put("financialSubObjectCode", pbglLine.getFinancialSubObjectCode()); 909 parameters.put("financialBalanceTypeCode", pbglLine.getFinancialBalanceTypeCode()); 910 parameters.put("financialObjectTypeCode", pbglLine.getFinancialObjectTypeCode()); 911 parameters.put(BCPropertyConstants.MAIN_WINDOW, (budgetConstructionForm.isMainWindow() ? "true" : "false")); 912 913 // anchor, if it exists 914 if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) { 915 parameters.put(BCConstants.RETURN_ANCHOR, ((KualiForm) form).getAnchor()); 916 } 917 918 // the form object is retrieved and removed upon return by KualiRequestProcessor.processActionForm() 919 parameters.put(BCConstants.RETURN_FORM_KEY, GlobalVariables.getUserSession().addObject(form, BCConstants.FORMKEY_PREFIX)); 920 921 String lookupUrl = UrlFactory.parameterizeUrl(basePath + "/" + BCConstants.QUICK_SALARY_SETTING_ACTION, parameters); 922 this.setupDocumentExit(); 923 return new ActionForward(lookupUrl, true); 924 } 925 926 /** 927 * This adds a revenue line to the BC document 928 * 929 * @param mapping 930 * @param form 931 * @param request 932 * @param response 933 * @return 934 * @throws Exception 935 */ 936 public ActionForward insertRevenueLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 937 BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form; 938 939 PendingBudgetConstructionGeneralLedger line = budgetConstructionForm.getNewRevenueLine(); 940 941 boolean rulePassed = true; 942 943 rulePassed &= SpringContext.getBean(KualiRuleService.class).applyRules(new AddPendingBudgetGeneralLedgerLineEvent(BCConstants.NEW_REVENUE_LINE_PROPERTY_NAME, budgetConstructionForm.getDocument(), line, true)); 944 945 if (rulePassed) { 946 // add PBGLLine 947 insertPBGLLine(true, budgetConstructionForm, line); 948 949 // clear the used newRevenueLine 950 budgetConstructionForm.setNewRevenueLine(new PendingBudgetConstructionGeneralLedger()); 951 budgetConstructionForm.initNewLine(budgetConstructionForm.getNewRevenueLine(), true); 952 } 953 954 return mapping.findForward(KFSConstants.MAPPING_BASIC); 955 } 956 957 /** 958 * This adds an expenditure line to the BC document 959 * 960 * @param mapping 961 * @param form 962 * @param request 963 * @param response 964 * @return 965 * @throws Exception 966 */ 967 public ActionForward insertExpenditureLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 968 BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form; 969 970 PendingBudgetConstructionGeneralLedger line = budgetConstructionForm.getNewExpenditureLine(); 971 972 boolean rulePassed = true; 973 974 rulePassed &= SpringContext.getBean(KualiRuleService.class).applyRules(new AddPendingBudgetGeneralLedgerLineEvent(BCConstants.NEW_EXPENDITURE_LINE_PROPERTY_NAME, budgetConstructionForm.getDocument(), line, false)); 975 976 if (rulePassed) { 977 978 // add PBGLLine 979 insertPBGLLine(false, budgetConstructionForm, line); 980 981 // clear the used newExpenditureLine 982 budgetConstructionForm.setNewExpenditureLine(new PendingBudgetConstructionGeneralLedger()); 983 budgetConstructionForm.initNewLine(budgetConstructionForm.getNewExpenditureLine(), false); 984 } 985 986 return mapping.findForward(KFSConstants.MAPPING_BASIC); 987 } 988 989 /** 990 * This inserts a PBGL revenue or expenditure line 991 * 992 * @param isRevenue 993 * @param budgetConstructionForm 994 * @param line 995 */ 996 protected void insertPBGLLine(boolean isRevenue, BudgetConstructionForm budgetConstructionForm, PendingBudgetConstructionGeneralLedger line) { 997 998 BudgetConstructionDocument bcDoc = (BudgetConstructionDocument) budgetConstructionForm.getDocument(); 999 1000 // null subobj must be set to dashes 1001 if (StringUtils.isBlank(line.getFinancialSubObjectCode())) { 1002 line.setFinancialSubObjectCode(KFSConstants.getDashFinancialSubObjectCode()); 1003 } 1004 1005 // check the DB for an existing persisted version of the line 1006 // and reinstate that with a message to the user indicating such 1007 boolean isReinstated = false; 1008 Map<String, Object> primaryKey = new HashMap<String, Object>(); 1009 primaryKey.put(KFSPropertyConstants.DOCUMENT_NUMBER, line.getDocumentNumber()); 1010 primaryKey.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, line.getUniversityFiscalYear()); 1011 primaryKey.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, line.getChartOfAccountsCode()); 1012 primaryKey.put(KFSPropertyConstants.ACCOUNT_NUMBER, line.getAccountNumber()); 1013 primaryKey.put(KFSPropertyConstants.SUB_ACCOUNT_NUMBER, line.getSubAccountNumber()); 1014 primaryKey.put(KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE, line.getFinancialBalanceTypeCode()); 1015 primaryKey.put(KFSPropertyConstants.FINANCIAL_OBJECT_TYPE_CODE, line.getFinancialObjectTypeCode()); 1016 1017 primaryKey.put(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, line.getFinancialObjectCode()); 1018 primaryKey.put(KFSPropertyConstants.FINANCIAL_SUB_OBJECT_CODE, line.getFinancialSubObjectCode()); 1019 1020 PendingBudgetConstructionGeneralLedger dbLine = (PendingBudgetConstructionGeneralLedger) SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(PendingBudgetConstructionGeneralLedger.class, primaryKey); 1021 if (dbLine != null){ 1022 line = dbLine; 1023 SpringContext.getBean(BudgetDocumentService.class).populatePBGLLine(line); 1024 isReinstated = true; 1025 } 1026 1027 // add the line in the proper order - assumes already exists check is done in rules 1028 int insertPoint = bcDoc.addPBGLLine(line, isRevenue); 1029 1030 if (isReinstated){ 1031 String errorKey; 1032 if (isRevenue){ 1033 errorKey = KNSConstants.DOCUMENT_PROPERTY_NAME + "." + BCPropertyConstants.PENDING_BUDGET_CONSTRUCTION_GENERAL_LEDGER_REVENUE_LINES + "[" + insertPoint + "]." + KFSPropertyConstants.ACCOUNT_LINE_ANNUAL_BALANCE_AMOUNT; 1034 } 1035 else { 1036 errorKey = KNSConstants.DOCUMENT_PROPERTY_NAME + "." + BCPropertyConstants.PENDING_BUDGET_CONSTRUCTION_GENERAL_LEDGER_EXPENDITURE_LINES + "[" + insertPoint + "]." + KFSPropertyConstants.ACCOUNT_LINE_ANNUAL_BALANCE_AMOUNT; 1037 } 1038 GlobalVariables.getMessageMap().putError(errorKey, BCKeyConstants.ERROR_BUDGET_LINE_REINSTATED, dbLine.getFinancialObjectCode() + "," + dbLine.getFinancialSubObjectCode()); 1039 } 1040 1041 // adjust totals 1042 if (line.getAccountLineAnnualBalanceAmount() != null && line.getAccountLineAnnualBalanceAmount() != KualiInteger.ZERO) { 1043 if (isRevenue) { 1044 bcDoc.setRevenueAccountLineAnnualBalanceAmountTotal(bcDoc.getRevenueAccountLineAnnualBalanceAmountTotal().add(line.getAccountLineAnnualBalanceAmount())); 1045 } 1046 else { 1047 bcDoc.setExpenditureAccountLineAnnualBalanceAmountTotal(bcDoc.getExpenditureAccountLineAnnualBalanceAmountTotal().add(line.getAccountLineAnnualBalanceAmount())); 1048 } 1049 } 1050 if (line.getFinancialBeginningBalanceLineAmount() != null && line.getFinancialBeginningBalanceLineAmount() != KualiInteger.ZERO) { 1051 if (isRevenue) { 1052 bcDoc.setRevenueFinancialBeginningBalanceLineAmountTotal(bcDoc.getRevenueFinancialBeginningBalanceLineAmountTotal().add(line.getFinancialBeginningBalanceLineAmount())); 1053 } 1054 else { 1055 bcDoc.setExpenditureFinancialBeginningBalanceLineAmountTotal(bcDoc.getExpenditureFinancialBeginningBalanceLineAmountTotal().add(line.getFinancialBeginningBalanceLineAmount())); 1056 } 1057 } 1058 } 1059 1060 /** 1061 * Deletes an existing PendingBudgetConstructionGeneralLedger revenue line if rules passed. Any associated monthly budget 1062 * (BudgetConstructionMonthly) is also deleted. 1063 * 1064 * @param mapping 1065 * @param form 1066 * @param request 1067 * @param response 1068 * @return 1069 * @throws Exception 1070 */ 1071 public ActionForward deleteRevenueLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1072 1073 BudgetConstructionForm tForm = (BudgetConstructionForm) form; 1074 BudgetConstructionDocument tDoc = tForm.getBudgetConstructionDocument(); 1075 1076 boolean rulePassed = true; 1077 int deleteIndex = this.getLineToDelete(request); 1078 1079 // check business rule if there is a persisted request amount, otherwise the line can just be removed 1080 PendingBudgetConstructionGeneralLedger revLine = tDoc.getPendingBudgetConstructionGeneralLedgerRevenueLines().get(deleteIndex); 1081 if (revLine.getPersistedAccountLineAnnualBalanceAmount() == null) { 1082 rulePassed = true; 1083 } 1084 else { 1085 // check deletion rules and delete if passed 1086 String errorPath = KFSConstants.DOCUMENT_PROPERTY_NAME + "." + BCPropertyConstants.PENDING_BUDGET_CONSTRUCTION_GENERAL_LEDGER_REVENUE_LINES + "[" + deleteIndex + "]"; 1087 rulePassed &= SpringContext.getBean(KualiRuleService.class).applyRules(new DeletePendingBudgetGeneralLedgerLineEvent(errorPath, tDoc, revLine, true)); 1088 } 1089 1090 if (rulePassed) { 1091 deletePBGLLine(true, tForm, deleteIndex, revLine); 1092 } 1093 1094 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1095 } 1096 1097 /** 1098 * Deletes an existing PendingBudgetConstructionGeneralLedger expenditure line if rules passed Any associated monthly budget 1099 * (BudgetConstructionMonthly) is also deleted. Check for the special case where the line is a 2PLG line, in which case the 1100 * document is validated and RI checks are forced even if there are no current differences between persisted and request 1101 * amounts. 1102 * 1103 * @param mapping 1104 * @param form 1105 * @param request 1106 * @param response 1107 * @return 1108 * @throws Exception 1109 */ 1110 public ActionForward deleteExpenditureLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1111 1112 BudgetConstructionForm tForm = (BudgetConstructionForm) form; 1113 BudgetConstructionDocument tDoc = tForm.getBudgetConstructionDocument(); 1114 1115 boolean rulePassed = true; 1116 int deleteIndex = this.getLineToDelete(request); 1117 1118 // check business rule if there is a persisted request amount, otherwise the line can just be removed 1119 PendingBudgetConstructionGeneralLedger expLine = tDoc.getPendingBudgetConstructionGeneralLedgerExpenditureLines().get(deleteIndex); 1120 if (expLine.getPersistedAccountLineAnnualBalanceAmount() == null) { 1121 rulePassed = true; 1122 } 1123 else { 1124 // check regular deletion rules and delete if passed 1125 String errorPath = KFSConstants.DOCUMENT_PROPERTY_NAME + "." + BCPropertyConstants.PENDING_BUDGET_CONSTRUCTION_GENERAL_LEDGER_EXPENDITURE_LINES + "[" + deleteIndex + "]"; 1126 rulePassed &= SpringContext.getBean(KualiRuleService.class).applyRules(new DeletePendingBudgetGeneralLedgerLineEvent(errorPath, tDoc, expLine, false)); 1127 } 1128 1129 if (rulePassed) { 1130 1131 // if the line is a 2PLG line do document validation, which forces RI checks in no current change situation 1132 if (expLine.getFinancialObjectCode().equalsIgnoreCase(KFSConstants.BudgetConstructionConstants.OBJECT_CODE_2PLG)) { 1133 SpringContext.getBean(BudgetDocumentService.class).validateDocument(tDoc); 1134 } 1135 // gets here if line is not 2PLG or doc is valid from 2plg perspective 1136 deletePBGLLine(false, tForm, deleteIndex, expLine); 1137 } 1138 1139 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1140 } 1141 1142 /** 1143 * Deletes an existing PendingBudgetConstructionGeneralLedger revenue or expenditure line along with any associated monthly 1144 * budget (BudgetConstructionMonthly) 1145 * 1146 * @param isRevenue 1147 * @param budgetConstructionForm 1148 * @param deleteIndex 1149 */ 1150 protected void deletePBGLLine(boolean isRevenue, BudgetConstructionForm budgetConstructionForm, int deleteIndex, PendingBudgetConstructionGeneralLedger line) { 1151 1152 BudgetConstructionDocument bcDoc = budgetConstructionForm.getBudgetConstructionDocument(); 1153 1154 // adjust totals 1155 if (line.getAccountLineAnnualBalanceAmount() != null && line.getAccountLineAnnualBalanceAmount() != KualiInteger.ZERO) { 1156 if (isRevenue) { 1157 bcDoc.setRevenueAccountLineAnnualBalanceAmountTotal(bcDoc.getRevenueAccountLineAnnualBalanceAmountTotal().subtract(line.getAccountLineAnnualBalanceAmount())); 1158 } 1159 else { 1160 bcDoc.setExpenditureAccountLineAnnualBalanceAmountTotal(bcDoc.getExpenditureAccountLineAnnualBalanceAmountTotal().subtract(line.getAccountLineAnnualBalanceAmount())); 1161 } 1162 } 1163 if (line.getFinancialBeginningBalanceLineAmount() != null && line.getFinancialBeginningBalanceLineAmount() != KualiInteger.ZERO) { 1164 if (isRevenue) { 1165 bcDoc.setRevenueFinancialBeginningBalanceLineAmountTotal(bcDoc.getRevenueFinancialBeginningBalanceLineAmountTotal().subtract(line.getFinancialBeginningBalanceLineAmount())); 1166 } 1167 else { 1168 bcDoc.setExpenditureFinancialBeginningBalanceLineAmountTotal(bcDoc.getExpenditureFinancialBeginningBalanceLineAmountTotal().subtract(line.getFinancialBeginningBalanceLineAmount())); 1169 } 1170 } 1171 1172 // remove the line 1173 if (isRevenue) { 1174 bcDoc.getPendingBudgetConstructionGeneralLedgerRevenueLines().remove(deleteIndex); 1175 } 1176 else { 1177 if (line.getFinancialObjectCode().equalsIgnoreCase(KFSConstants.BudgetConstructionConstants.OBJECT_CODE_2PLG)) { 1178 bcDoc.setContainsTwoPlug(true); 1179 } 1180 bcDoc.getPendingBudgetConstructionGeneralLedgerExpenditureLines().remove(deleteIndex); 1181 } 1182 1183 } 1184 1185 /* 1186 * public ActionForward returnFromMonthly(ActionMapping mapping, ActionForm form, HttpServletRequest request, 1187 * HttpServletResponse response) throws Exception { BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) 1188 * form; String documentNumber = request.getParameter("documentNumber"); BudgetConstructionDocument budgetConstructionDocument = 1189 * (BudgetConstructionDocument) SpringContext.getBean(DocumentService.class).getByDocumentHeaderId(documentNumber); 1190 * budgetConstructionForm.setDocument(budgetConstructionDocument); KualiWorkflowDocument workflowDoc = 1191 * budgetConstructionDocument.getDocumentHeader().getWorkflowDocument(); 1192 * budgetConstructionForm.setDocTypeName(workflowDoc.getDocumentType()); // KualiDocumentFormBase.populate() needs this updated 1193 * in the session GlobalVariables.getUserSession().setWorkflowDocument(workflowDoc); return 1194 * mapping.findForward(KFSConstants.MAPPING_BASIC); } 1195 */ 1196 1197 /** 1198 * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#refresh(org.apache.struts.action.ActionMapping, 1199 * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) 1200 */ 1201 @Override 1202 public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1203 BudgetConstructionForm budgetConstructionForm = (BudgetConstructionForm) form; 1204 budgetConstructionForm.setDerivedValuesOnForm(request); 1205 1206 // Do specific refresh stuff here based on refreshCaller parameter 1207 // typical refresh callers would be monthlyBudget or salarySetting or lookupable 1208 String refreshCaller = request.getParameter(KFSConstants.REFRESH_CALLER); 1209 1210 if (refreshCaller != null && refreshCaller.equalsIgnoreCase(BCConstants.MONTHLY_BUDGET_REFRESH_CALLER)) { 1211 1212 // monthly process applies any changes to the DB and the form session object 1213 // including any override to the request amount which also changes the request total 1214 // it also sets up calc monthly benefits if the line is involved in benefits 1215 BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class); 1216 budgetDocumentService.calculateBenefitsIfNeeded(budgetConstructionForm.getBudgetConstructionDocument()); 1217 1218 } 1219 if (refreshCaller != null && refreshCaller.equalsIgnoreCase(BCConstants.QUICK_SALARY_SETTING_REFRESH_CALLER)) { 1220 1221 1222 BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class); 1223 1224 // if editing - reload expenditure and check for changes to detail salary lines and 2plg request amount 1225 boolean diffFound = false; 1226 if (budgetConstructionForm.isEditAllowed() && !budgetConstructionForm.isSystemViewOnly()) { 1227 BudgetConstructionDocument currentBCDoc = budgetConstructionForm.getBudgetConstructionDocument(); 1228 1229 // get the current set of salary setting related rows from DB and compare against preSalarySettingRows 1230 1231 List<PendingBudgetConstructionGeneralLedger> dbSalarySettingRows = budgetDocumentService.getPBGLSalarySettingRows(currentBCDoc); 1232 for (PendingBudgetConstructionGeneralLedger dbSalarySettingRow : dbSalarySettingRows) { 1233 if (budgetConstructionForm.getPreSalarySettingRows().containsKey(dbSalarySettingRow.getFinancialObjectCode() + dbSalarySettingRow.getFinancialSubObjectCode())) { 1234 1235 // update the existing row if a difference is found 1236 KualiInteger dbReqAmount = dbSalarySettingRow.getAccountLineAnnualBalanceAmount(); 1237 KualiInteger preReqAmount = budgetConstructionForm.getPreSalarySettingRows().get(dbSalarySettingRow.getFinancialObjectCode() + dbSalarySettingRow.getFinancialSubObjectCode()).getAccountLineAnnualBalanceAmount(); 1238 Long dbVersionNumber = dbSalarySettingRow.getVersionNumber(); 1239 Long preReqVersionNumber = budgetConstructionForm.getPreSalarySettingRows().get(dbSalarySettingRow.getFinancialObjectCode() + dbSalarySettingRow.getFinancialSubObjectCode()).getVersionNumber(); 1240 if ((dbVersionNumber.compareTo(preReqVersionNumber) != 0) || (dbReqAmount.compareTo(preReqAmount) != 0)) { 1241 budgetDocumentService.addOrUpdatePBGLRow(currentBCDoc, dbSalarySettingRow); 1242 1243 // only flag for existing line diff when the request amount changes 1244 // changes in versionNumber implies offsetting updates of some sort 1245 if (dbReqAmount.compareTo(preReqAmount) != 0) { 1246 diffFound = true; 1247 } 1248 } 1249 } 1250 else { 1251 1252 // update the req amount and version or add the new row to the current doc as needed 1253 // insert the new DB row to the set in memory 1254 budgetDocumentService.addOrUpdatePBGLRow(currentBCDoc, dbSalarySettingRow); 1255 diffFound = true; 1256 } 1257 } 1258 1259 if (diffFound) { 1260 this.adjustForSalarySettingChanges(budgetConstructionForm); 1261 1262 } 1263 } 1264 1265 } 1266 1267 if (refreshCaller != null && refreshCaller.equalsIgnoreCase(KFSConstants.KUALI_LOOKUPABLE_IMPL)) { 1268 final List REFRESH_FIELDS = Collections.unmodifiableList(Arrays.asList(new String[] { "financialObject", "financialSubObject" })); 1269 SpringContext.getBean(PersistenceService.class).retrieveReferenceObjects(budgetConstructionForm.getNewRevenueLine(), REFRESH_FIELDS); 1270 SpringContext.getBean(PersistenceService.class).retrieveReferenceObjects(budgetConstructionForm.getNewExpenditureLine(), REFRESH_FIELDS); 1271 } 1272 1273 // balance inquiry anchor is set before doing a balance inquiry 1274 if (budgetConstructionForm.getBalanceInquiryReturnAnchor() != null) { 1275 budgetConstructionForm.setAnchor(budgetConstructionForm.getBalanceInquiryReturnAnchor()); 1276 budgetConstructionForm.setBalanceInquiryReturnAnchor(null); 1277 } 1278 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1279 } 1280 1281 /** 1282 * 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 1283 * all of the descriptions and labels for each of the pbgl line values. 1284 * 1285 * @param mapping 1286 * @param form 1287 * @param request 1288 * @param response 1289 * @return ActionForward 1290 * @throws Exception 1291 */ 1292 public ActionForward showDetails(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1293 BudgetConstructionForm tForm = (BudgetConstructionForm) form; 1294 tForm.setHideDetails(false); 1295 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1296 } 1297 1298 /** 1299 * This action toggles the value of the hide field in the user interface to "hide" so that when the page is rendered, the UI 1300 * displays values without all of the descriptions and labels for each of the pbgl lines. 1301 * 1302 * @param mapping 1303 * @param form 1304 * @param request 1305 * @param response 1306 * @return ActionForward 1307 * @throws Exception 1308 */ 1309 public ActionForward hideDetails(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1310 BudgetConstructionForm tForm = (BudgetConstructionForm) form; 1311 tForm.setHideDetails(true); 1312 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1313 } 1314 1315 public ActionForward toggleAdjustmentMeasurement(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1316 BudgetConstructionForm docForm = (BudgetConstructionForm) form; 1317 1318 boolean currentStatus = docForm.isHideAdjustmentMeasurement(); 1319 docForm.setHideAdjustmentMeasurement(!currentStatus); 1320 1321 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1322 } 1323 1324 public ActionForward adjustRevenueLinePercent(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1325 BudgetConstructionForm docForm = (BudgetConstructionForm) form; 1326 BudgetConstructionDocument bcDoc = docForm.getBudgetConstructionDocument(); 1327 PendingBudgetConstructionGeneralLedger revLine = bcDoc.getPendingBudgetConstructionGeneralLedgerRevenueLines().get(this.getSelectedLine(request)); 1328 1329 if (revLine.getAdjustmentAmount() != null) { 1330 this.adjustRequest(revLine); 1331 docForm.populatePBGLLines(); 1332 } 1333 1334 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1335 } 1336 1337 public ActionForward adjustExpenditureLinePercent(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1338 BudgetConstructionForm docForm = (BudgetConstructionForm) form; 1339 BudgetConstructionDocument bcDoc = docForm.getBudgetConstructionDocument(); 1340 PendingBudgetConstructionGeneralLedger expLine = bcDoc.getPendingBudgetConstructionGeneralLedgerExpenditureLines().get(this.getSelectedLine(request)); 1341 1342 if (expLine.getAdjustmentAmount() != null) { 1343 this.adjustRequest(expLine); 1344 docForm.populatePBGLLines(); 1345 } 1346 1347 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1348 } 1349 1350 public ActionForward adjustAllRevenueLinesPercent(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1351 BudgetConstructionForm docForm = (BudgetConstructionForm) form; 1352 BudgetConstructionDocument bcDoc = docForm.getBudgetConstructionDocument(); 1353 List<PendingBudgetConstructionGeneralLedger> revenueLines = bcDoc.getPendingBudgetConstructionGeneralLedgerRevenueLines(); 1354 1355 KualiDecimal adjustmentAmount = docForm.getRevenueAdjustmentAmount(); 1356 if (adjustmentAmount != null) { 1357 1358 // not sure we need this check since the tool isn't displayed in view mode 1359 boolean isEditable = docForm.isEditAllowed() && !docForm.isSystemViewOnly(); 1360 for (PendingBudgetConstructionGeneralLedger revenueLine : revenueLines) { 1361 if (isEditable) { 1362 revenueLine.setAdjustmentAmount(adjustmentAmount); 1363 this.adjustRequest(revenueLine); 1364 } 1365 } 1366 if (isEditable){ 1367 docForm.populatePBGLLines(); 1368 } 1369 } 1370 1371 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1372 } 1373 1374 public ActionForward adjustAllExpenditureLinesPercent(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1375 BudgetConstructionForm docForm = (BudgetConstructionForm) form; 1376 BudgetConstructionDocument bcDoc = docForm.getBudgetConstructionDocument(); 1377 List<PendingBudgetConstructionGeneralLedger> expenditureLines = bcDoc.getPendingBudgetConstructionGeneralLedgerExpenditureLines(); 1378 1379 KualiDecimal adjustmentAmount = docForm.getExpenditureAdjustmentAmount(); 1380 if (adjustmentAmount != null) { 1381 1382 // not sure we need this check since the tool isn't displayed in view mode 1383 boolean isEditable = docForm.isEditAllowed() && !docForm.isSystemViewOnly(); 1384 // (!benecalcDisabled && !empty item.laborObject && item.laborObject.financialObjectFringeOrSalaryCode == 'F') 1385 for (PendingBudgetConstructionGeneralLedger expenditureLine : expenditureLines) { 1386 boolean isLineEditable = (isEditable && (docForm.isBenefitsCalculationDisabled() || (expenditureLine.getLaborObject() == null) || !expenditureLine.getLaborObject().getFinancialObjectFringeOrSalaryCode().equalsIgnoreCase(BCConstants.LABOR_OBJECT_FRINGE_CODE))); 1387 if (isLineEditable) { 1388 expenditureLine.setAdjustmentAmount(adjustmentAmount); 1389 this.adjustRequest(expenditureLine); 1390 } 1391 } 1392 if (isEditable){ 1393 docForm.populatePBGLLines(); 1394 } 1395 } 1396 1397 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1398 } 1399 1400 /** 1401 * Handles the document (account) pullup action, resetting the cached editingMode as appropriate for the new level. 1402 * 1403 * @param mapping 1404 * @param form 1405 * @param request 1406 * @param response 1407 * @return 1408 * @throws Exception 1409 */ 1410 public ActionForward performAccountPullup(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1411 BudgetConstructionForm tForm = (BudgetConstructionForm) form; 1412 1413 boolean doAllowPullup = false; 1414 boolean lockNeeded = false; 1415 boolean prePullReadOnlyAccess; 1416 1417 BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class); 1418 1419 // if system view only or view only - reload to get the latest status 1420 // and check that the document is still below the selected POV 1421 if (!tForm.isEditAllowed() || tForm.isSystemViewOnly()) { 1422 1423 prePullReadOnlyAccess = true; 1424 1425 // now reload the document and get latest status info 1426 loadDocument(tForm); 1427 this.initAuthorization(tForm); 1428 if (tForm.getBudgetConstructionDocument().getOrganizationLevelCode() < Integer.parseInt(tForm.getPullupKeyCode())) { 1429 doAllowPullup = true; 1430 1431 // if not system view only mode, we are in document view mode - we'll need a lock before the pullup 1432 // since by definition pullup puts the account at a full_entry level 1433 // and we need exclusive access to perform the pullup 1434 if (!tForm.isSystemViewOnly()) { 1435 lockNeeded = true; 1436 } 1437 } 1438 else { 1439 // document has been moved and is either at the desired level or above 1440 doAllowPullup = false; 1441 lockNeeded = false; 1442 1443 // document has been moved above the desired level - let populate through an authorization exception 1444 if (tForm.getBudgetConstructionDocument().getOrganizationLevelCode() > Integer.parseInt(tForm.getPullupKeyCode())) { 1445 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_MESSAGES, BCKeyConstants.ERROR_BUDGET_PULLUP_DOCUMENT, "Document has already been moved above the selected level."); 1446 } 1447 } 1448 } 1449 else { 1450 // we are in document full_entry 1451 // assume we already have a lock, allow the pullup 1452 // and we need to ensure the user can finish editing work if after pullup system goes to system view only 1453 prePullReadOnlyAccess = false; 1454 doAllowPullup = true; 1455 } 1456 1457 if (lockNeeded || doAllowPullup) { 1458 1459 // get a fresh header to use for lock and/or pullup 1460 HashMap primaryKey = new HashMap(); 1461 primaryKey.put(KFSPropertyConstants.DOCUMENT_NUMBER, tForm.getDocument().getDocumentNumber()); 1462 BudgetConstructionHeader budgetConstructionHeader = (BudgetConstructionHeader) SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(BudgetConstructionHeader.class, primaryKey); 1463 if (budgetConstructionHeader == null) { 1464 GlobalVariables.getMessageMap().putError(BCConstants.BUDGET_CONSTRUCTION_SYSTEM_INFORMATION_TAB_ERRORS, BCKeyConstants.ERROR_BUDGET_PULLUP_DOCUMENT, "Fatal, Document not found."); 1465 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1466 } 1467 1468 if (lockNeeded) { 1469 // only successful lock allows pullup here 1470 doAllowPullup = false; 1471 1472 LockService lockService = SpringContext.getBean(LockService.class); 1473 BudgetConstructionLockStatus bcLockStatus = lockService.lockAccount(budgetConstructionHeader, GlobalVariables.getUserSession().getPerson().getPrincipalId()); 1474 LockStatus lockStatus = bcLockStatus.getLockStatus(); 1475 switch (lockStatus) { 1476 case SUCCESS: 1477 doAllowPullup = true; 1478 break; 1479 case BY_OTHER: 1480 String lockerName = SpringContext.getBean(org.kuali.rice.kim.service.PersonService.class).getPerson(bcLockStatus.getAccountLockOwner()).getName(); 1481 GlobalVariables.getMessageMap().putError(BCConstants.BUDGET_CONSTRUCTION_SYSTEM_INFORMATION_TAB_ERRORS, BCKeyConstants.ERROR_BUDGET_PULLUP_DOCUMENT, "Locked by " + lockerName); 1482 break; 1483 case FLOCK_FOUND: 1484 GlobalVariables.getMessageMap().putError(BCConstants.BUDGET_CONSTRUCTION_SYSTEM_INFORMATION_TAB_ERRORS, BCKeyConstants.ERROR_BUDGET_PULLUP_DOCUMENT, "Funding lock found."); 1485 break; 1486 default: 1487 GlobalVariables.getMessageMap().putError(BCConstants.BUDGET_CONSTRUCTION_SYSTEM_INFORMATION_TAB_ERRORS, BCKeyConstants.ERROR_BUDGET_PULLUP_DOCUMENT, "Optimistic lock or other failure during lock attempt."); 1488 break; 1489 } 1490 } 1491 1492 // attempt pullup 1493 if (doAllowPullup) { 1494 budgetConstructionHeader.setOrganizationLevelCode(Integer.parseInt(tForm.getPullupKeyCode())); 1495 budgetConstructionHeader.setOrganizationLevelChartOfAccountsCode(tForm.getAccountOrgHierLevels().get(Integer.parseInt(tForm.getPullupKeyCode())).getOrganizationChartOfAccountsCode()); 1496 budgetConstructionHeader.setOrganizationLevelOrganizationCode(tForm.getAccountOrgHierLevels().get(Integer.parseInt(tForm.getPullupKeyCode())).getOrganizationCode()); 1497 SpringContext.getBean(BusinessObjectService.class).save(budgetConstructionHeader); 1498 1499 // finally refresh the doc with the changed header info 1500 tForm.getBudgetConstructionDocument().setVersionNumber(budgetConstructionHeader.getVersionNumber()); 1501 tForm.getBudgetConstructionDocument().setOrganizationLevelCode(budgetConstructionHeader.getOrganizationLevelCode()); 1502 tForm.getBudgetConstructionDocument().setOrganizationLevelChartOfAccountsCode(budgetConstructionHeader.getOrganizationLevelChartOfAccountsCode()); 1503 tForm.getBudgetConstructionDocument().setOrganizationLevelOrganizationCode(budgetConstructionHeader.getOrganizationLevelOrganizationCode()); 1504 1505 // refresh the lock info even though the user may be pulling while in edit mode 1506 tForm.getBudgetConstructionDocument().setBudgetLockUserIdentifier(budgetConstructionHeader.getBudgetLockUserIdentifier()); 1507 1508 // refresh organization - so UI shows new level description 1509 tForm.getBudgetConstructionDocument().refreshReferenceObject("organizationLevelOrganization"); 1510 1511 this.initAuthorization(tForm); 1512 1513 // if before pullup, system was 'not system view only' goes to 'system view only' after pull 1514 // need to manually remove the system view only editingMode here to allow the user to save work since still 1515 // full_entry 1516 if (tForm.isEditAllowed() && !prePullReadOnlyAccess) { 1517 if (tForm.isSystemViewOnly()) { 1518 tForm.getEditingMode().remove(BCConstants.EditModes.SYSTEM_VIEW_ONLY); 1519 } 1520 } 1521 } 1522 } 1523 1524 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1525 } 1526 1527 /** 1528 * Handles the document (account) pushdown action, resetting the cached editingMode as appropriate for the new level. 1529 * 1530 * @param mapping 1531 * @param form 1532 * @param request 1533 * @param response 1534 * @return 1535 * @throws Exception 1536 */ 1537 public ActionForward performAccountPushdown(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1538 1539 boolean doAllowPushdown = false; 1540 boolean unlockNeeded = false; 1541 boolean prePushSystemViewOnly; 1542 BudgetConstructionForm tForm = (BudgetConstructionForm) form; 1543 BudgetConstructionDocument bcDocument = tForm.getBudgetConstructionDocument(); 1544 BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class); 1545 1546 // This method is called only if user has edit access and there is somewhere to push to. 1547 // If not system view only and the intended push level is view, we need to validate and save 1548 // Otherwise new level is still allowing editing, just push and keep current lock 1549 if (!tForm.isSystemViewOnly()) { 1550 prePushSystemViewOnly = false; 1551 1552 // check editing mode at the intended level 1553 if (!hasEditPermission(bcDocument, tForm.getPushdownKeyCode(), GlobalVariables.getUserSession().getPerson())) { 1554 budgetDocumentService.saveDocumentNoWorkflow(bcDocument); 1555 tForm.initializePersistedRequestAmounts(); 1556 budgetDocumentService.calculateBenefitsIfNeeded(bcDocument); 1557 1558 // repop and refresh refs - esp monthly so jsp can properly display state 1559 // tForm.populatePBGLLines(); 1560 1561 unlockNeeded = true; 1562 } 1563 doAllowPushdown = true; 1564 } 1565 else { 1566 prePushSystemViewOnly = true; 1567 1568 // reload document to get most up-to-date status and recheck that we still have FULL_ENTRY access 1569 // anything else means the document was moved by someone else and we may no longer even have read access 1570 loadDocument(tForm); 1571 this.initAuthorization(tForm); 1572 if (tForm.isEditAllowed()) { 1573 doAllowPushdown = true; 1574 } 1575 else { 1576 // document has moved 1577 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_MESSAGES, BCKeyConstants.ERROR_BUDGET_PUSHDOWN_DOCUMENT, "Full Access Control Lost."); 1578 } 1579 } 1580 1581 // gets here if editing and pushing to view and doc is valid and persisted 1582 // or we are pushing from edit to edit 1583 // or we are in system view only 1584 if (doAllowPushdown) { 1585 1586 HashMap primaryKey = new HashMap(); 1587 primaryKey.put(KFSPropertyConstants.DOCUMENT_NUMBER, tForm.getDocument().getDocumentNumber()); 1588 1589 BudgetConstructionHeader budgetConstructionHeader = (BudgetConstructionHeader) SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(BudgetConstructionHeader.class, primaryKey); 1590 if (budgetConstructionHeader != null) { 1591 budgetConstructionHeader.setOrganizationLevelCode(Integer.parseInt(tForm.getPushdownKeyCode())); 1592 if (Integer.parseInt(tForm.getPushdownKeyCode()) == 0) { 1593 budgetConstructionHeader.setOrganizationLevelChartOfAccountsCode(null); 1594 budgetConstructionHeader.setOrganizationLevelOrganizationCode(null); 1595 } 1596 else { 1597 budgetConstructionHeader.setOrganizationLevelChartOfAccountsCode(tForm.getAccountOrgHierLevels().get(Integer.parseInt(tForm.getPushdownKeyCode())).getOrganizationChartOfAccountsCode()); 1598 budgetConstructionHeader.setOrganizationLevelOrganizationCode(tForm.getAccountOrgHierLevels().get(Integer.parseInt(tForm.getPushdownKeyCode())).getOrganizationCode()); 1599 } 1600 } 1601 1602 // unlock if needed (which stores) - otherwise store the new level 1603 if (unlockNeeded) { 1604 1605 LockService lockService = SpringContext.getBean(LockService.class); 1606 lockService.unlockAccount(budgetConstructionHeader); 1607 } 1608 else { 1609 SpringContext.getBean(BusinessObjectService.class).save(budgetConstructionHeader); 1610 1611 } 1612 1613 // finally refresh the doc with the changed header info 1614 tForm.getBudgetConstructionDocument().setVersionNumber(budgetConstructionHeader.getVersionNumber()); 1615 tForm.getBudgetConstructionDocument().setOrganizationLevelCode(budgetConstructionHeader.getOrganizationLevelCode()); 1616 tForm.getBudgetConstructionDocument().setOrganizationLevelChartOfAccountsCode(budgetConstructionHeader.getOrganizationLevelChartOfAccountsCode()); 1617 tForm.getBudgetConstructionDocument().setOrganizationLevelOrganizationCode(budgetConstructionHeader.getOrganizationLevelOrganizationCode()); 1618 tForm.getBudgetConstructionDocument().setBudgetLockUserIdentifier(budgetConstructionHeader.getBudgetLockUserIdentifier()); 1619 1620 // refresh organization - so UI shows new level description 1621 tForm.getBudgetConstructionDocument().refreshReferenceObject("organizationLevelOrganization"); 1622 1623 this.initAuthorization(tForm); 1624 1625 // if before push, system is 'not system view only' goes to 'system view only' after push 1626 // need to manually remove the system view only editingMode here to allow the user to save work if still full_entry 1627 if (tForm.isEditAllowed()) { 1628 if (tForm.isSystemViewOnly() && !prePushSystemViewOnly) { 1629 tForm.getEditingMode().remove(BCConstants.EditModes.SYSTEM_VIEW_ONLY); 1630 } 1631 } 1632 1633 } 1634 1635 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1636 } 1637 1638 /** 1639 * Checks whether the current user would have access for the given budget document for the given organization level code 1640 * 1641 * @param document current bc document 1642 * @param orgLevelCode organization level code for access check 1643 * @param user user to check access for 1644 * @return true if user would have edit permission, false otherwise 1645 */ 1646 protected boolean hasEditPermission(BudgetConstructionDocument document, String orgLevelCode, Person user) { 1647 TransactionalDocumentAuthorizer documentAuthorizer = (TransactionalDocumentAuthorizer) SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(document); 1648 1649 AttributeSet roleQualifiers = new AttributeSet(); 1650 roleQualifiers.put(BCPropertyConstants.ORGANIZATION_LEVEL_CODE, orgLevelCode); 1651 1652 List<BudgetConstructionAccountOrganizationHierarchy> accountOrganizationHierarchy = (List<BudgetConstructionAccountOrganizationHierarchy>) SpringContext.getBean(BudgetDocumentService.class).retrieveOrBuildAccountOrganizationHierarchy(document.getUniversityFiscalYear(), document.getChartOfAccountsCode(), document.getAccountNumber()); 1653 for (BudgetConstructionAccountOrganizationHierarchy accountOrganization : accountOrganizationHierarchy) { 1654 if (accountOrganization.getOrganizationLevelCode().intValue() == Integer.parseInt(orgLevelCode)) { 1655 roleQualifiers.put(BCPropertyConstants.ORGANIZATION_CHART_OF_ACCOUNTS_CODE, accountOrganization.getOrganizationChartOfAccountsCode()); 1656 roleQualifiers.put(KfsKimAttributes.ORGANIZATION_CODE, accountOrganization.getOrganizationCode()); 1657 } 1658 } 1659 1660 return documentAuthorizer.isAuthorizedByTemplate(document, KNSConstants.KNS_NAMESPACE, KimConstants.PermissionTemplateNames.EDIT_DOCUMENT, user.getPrincipalId(), null, roleQualifiers); 1661 } 1662 1663 public ActionForward performReportDump(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1664 1665 BudgetConstructionForm tForm = (BudgetConstructionForm) form; 1666 BudgetConstructionDocument bcDocument = tForm.getBudgetConstructionDocument(); 1667 1668 // when we return from the lookup, our next request's method to call is going to be refresh 1669 tForm.registerEditableProperty(KNSConstants.DISPATCH_REQUEST_PARAMETER); 1670 1671 if (tForm.isEditAllowed() && !tForm.isSystemViewOnly()) { 1672 BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class); 1673 1674 budgetDocumentService.saveDocumentNoWorkflow(bcDocument); 1675 budgetDocumentService.calculateBenefitsIfNeeded(bcDocument); 1676 tForm.initializePersistedRequestAmounts(); 1677 1678 // repop and refresh refs - esp monthly so jsp can properly display state 1679 // tForm.populatePBGLLines(); 1680 } 1681 1682 // gets here if rules passed and doc detail gets persisted and refreshed 1683 String basePath = SpringContext.getBean(KualiConfigurationService.class).getPropertyString(KFSConstants.APPLICATION_URL_KEY); 1684 Properties parameters = new Properties(); 1685 parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, BCConstants.MONTHLY_BUDGET_METHOD); 1686 parameters.put(KFSConstants.BACK_LOCATION, basePath + mapping.getPath() + ".do"); 1687 parameters.put("documentNumber", tForm.getDocument().getDocumentNumber()); 1688 parameters.put("universityFiscalYear", tForm.getUniversityFiscalYear().toString()); 1689 parameters.put("chartOfAccountsCode", tForm.getChartOfAccountsCode()); 1690 parameters.put("accountNumber", tForm.getAccountNumber()); 1691 parameters.put("subAccountNumber", tForm.getSubAccountNumber()); 1692 parameters.put(BCPropertyConstants.MAIN_WINDOW, (tForm.isMainWindow() ? "true" : "false")); 1693 1694 // anchor, if it exists 1695 if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) { 1696 parameters.put(BCConstants.RETURN_ANCHOR, ((KualiForm) form).getAnchor()); 1697 } 1698 1699 // the form object is retrieved and removed upon return by KualiRequestProcessor.processActionForm() 1700 parameters.put(BCConstants.RETURN_FORM_KEY, GlobalVariables.getUserSession().addObject(form, BCConstants.FORMKEY_PREFIX)); 1701 1702 String lookupUrl = UrlFactory.parameterizeUrl(basePath + "/" + BCConstants.REPORT_RUNNER_ACTION, parameters); 1703 this.setupDocumentExit(); 1704 return new ActionForward(lookupUrl, true); 1705 } 1706 1707 public ActionForward performPercentChange(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1708 1709 BudgetConstructionForm tForm = (BudgetConstructionForm) form; 1710 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_MESSAGES, KFSKeyConstants.ERROR_UNIMPLEMENTED, "Percent Change"); 1711 1712 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1713 } 1714 1715 public ActionForward performRevMonthSpread(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1716 return this.performMonthSpread(mapping, form, request, response, true); 1717 } 1718 1719 public ActionForward performExpMonthSpread(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1720 return this.performMonthSpread(mapping, form, request, response, false); 1721 } 1722 1723 public ActionForward performMonthSpread(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, boolean isRevenue) throws Exception { 1724 1725 // no check for full_entry and system edit mode since this control is not displayed for this case 1726 1727 // need to validate, save and calc benefits first 1728 // this is different than client/server model - need to always keep DB consistent 1729 BudgetConstructionForm tForm = (BudgetConstructionForm) form; 1730 BudgetConstructionDocument bcDocument = tForm.getBudgetConstructionDocument(); 1731 1732 BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class); 1733 1734 // validate and save without checking monthly RI since the spread will keep things consistent 1735 if (isRevenue) { 1736 budgetDocumentService.saveDocumentNoWorkFlow(bcDocument, MonthSpreadDeleteType.REVENUE, false); 1737 } 1738 else { 1739 budgetDocumentService.saveDocumentNoWorkFlow(bcDocument, MonthSpreadDeleteType.EXPENDITURE, false); 1740 } 1741 tForm.initializePersistedRequestAmounts(); 1742 // budgetDocumentService.calculateBenefitsIfNeeded(bcDocument); 1743 1744 BudgetConstructionMonthlyBudgetsCreateDeleteService monthlyBudgetService = SpringContext.getBean(BudgetConstructionMonthlyBudgetsCreateDeleteService.class); 1745 1746 if (isRevenue) { 1747 monthlyBudgetService.spreadBudgetConstructionMonthlyBudgetsRevenue(bcDocument.getDocumentNumber(), bcDocument.getUniversityFiscalYear(), bcDocument.getChartOfAccountsCode(), bcDocument.getAccountNumber(), bcDocument.getSubAccountNumber()); 1748 } 1749 else { 1750 // service returns true if benefit eligible monthly lines exist 1751 if (monthlyBudgetService.spreadBudgetConstructionMonthlyBudgetsExpenditure(bcDocument.getDocumentNumber(), bcDocument.getUniversityFiscalYear(), bcDocument.getChartOfAccountsCode(), bcDocument.getAccountNumber(), bcDocument.getSubAccountNumber())) { 1752 bcDocument.setMonthlyBenefitsCalcNeeded(true); 1753 // budgetDocumentService.calculateBenefitsIfNeeded(bcDocument); 1754 } 1755 } 1756 budgetDocumentService.calculateBenefitsIfNeeded(bcDocument); 1757 1758 // repop and refresh refs - esp monthly so jsp can properly display state 1759 tForm.populatePBGLLines(); 1760 1761 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1762 } 1763 1764 public ActionForward performRevMonthDelete(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1765 return this.performMonthDelete(mapping, form, request, response, true); 1766 } 1767 1768 public ActionForward performExpMonthDelete(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1769 return this.performMonthDelete(mapping, form, request, response, false); 1770 } 1771 1772 public ActionForward performMonthDelete(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, boolean isRevenue) throws Exception { 1773 1774 // no check for full_entry and system edit mode since this control is not displayed for this case 1775 1776 // need to validate, save and calc benefits first 1777 // this is different than client/server model - need to always keep DB consistent 1778 BudgetConstructionForm tForm = (BudgetConstructionForm) form; 1779 BudgetConstructionDocument bcDocument = tForm.getBudgetConstructionDocument(); 1780 1781 BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class); 1782 1783 // validate and save without checking monthly RI since the delete will make RI check moot 1784 if (isRevenue) { 1785 budgetDocumentService.saveDocumentNoWorkFlow(bcDocument, MonthSpreadDeleteType.REVENUE, false); 1786 } 1787 else { 1788 budgetDocumentService.saveDocumentNoWorkFlow(bcDocument, MonthSpreadDeleteType.EXPENDITURE, false); 1789 } 1790 tForm.initializePersistedRequestAmounts(); 1791 // budgetDocumentService.calculateBenefitsIfNeeded(bcDocument); 1792 1793 BudgetConstructionMonthlyBudgetsCreateDeleteService monthlyBudgetService = SpringContext.getBean(BudgetConstructionMonthlyBudgetsCreateDeleteService.class); 1794 1795 if (isRevenue) { 1796 monthlyBudgetService.deleteBudgetConstructionMonthlyBudgetsRevenue(bcDocument.getDocumentNumber(), bcDocument.getUniversityFiscalYear(), bcDocument.getChartOfAccountsCode(), bcDocument.getAccountNumber(), bcDocument.getSubAccountNumber()); 1797 } 1798 else { 1799 monthlyBudgetService.deleteBudgetConstructionMonthlyBudgetsExpenditure(bcDocument.getDocumentNumber(), bcDocument.getUniversityFiscalYear(), bcDocument.getChartOfAccountsCode(), bcDocument.getAccountNumber(), bcDocument.getSubAccountNumber()); 1800 } 1801 budgetDocumentService.calculateBenefitsIfNeeded(bcDocument); 1802 1803 // repop and refresh refs - esp monthly so jsp can properly display state 1804 tForm.populatePBGLLines(); 1805 1806 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1807 } 1808 1809 public ActionForward performCalculateBenefits(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 1810 1811 // no check for full_entry and system edit mode since this control is not displayed for this case 1812 BudgetConstructionForm tForm = (BudgetConstructionForm) form; 1813 BudgetConstructionDocument bcDocument = (BudgetConstructionDocument) tForm.getDocument(); 1814 1815 // allow benecalc if account is not salary only and benefits calc not disabled 1816 if (!tForm.isBenefitsCalculationDisabled() && !bcDocument.isSalarySettingOnly()) { 1817 BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class); 1818 1819 budgetDocumentService.saveDocumentNoWorkflow(bcDocument); 1820 tForm.initializePersistedRequestAmounts(); 1821 budgetDocumentService.calculateBenefits(bcDocument); 1822 1823 // repop and refresh refs - esp monthly so jsp can properly display state 1824 // tForm.populatePBGLLines(); 1825 1826 } 1827 1828 return mapping.findForward(KFSConstants.MAPPING_BASIC); 1829 } 1830 1831 protected void adjustRequest(PendingBudgetConstructionGeneralLedger pbglLine) { 1832 1833 KualiInteger baseAmount = pbglLine.getFinancialBeginningBalanceLineAmount(); 1834 if (baseAmount.isNonZero()) { 1835 KualiDecimal percent = pbglLine.getAdjustmentAmount(); 1836 BigDecimal adjustedAmount = baseAmount.multiply(percent).divide(KFSConstants.ONE_HUNDRED); 1837 1838 KualiInteger requestAmount = new KualiInteger(adjustedAmount).add(baseAmount); 1839 pbglLine.setAccountLineAnnualBalanceAmount(requestAmount); 1840 } 1841 1842 } 1843 }