001: /*
002: * Copyright 2006-2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.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/ecl1.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.module.kra.budget.web.struts.action;
017:
018: import java.util.ArrayList;
019: import java.util.List;
020: import java.util.Map;
021:
022: import javax.servlet.http.HttpServletRequest;
023: import javax.servlet.http.HttpServletResponse;
024:
025: import org.apache.commons.lang.StringUtils;
026: import org.apache.struts.action.ActionForm;
027: import org.apache.struts.action.ActionForward;
028: import org.apache.struts.action.ActionMapping;
029: import org.kuali.core.authorization.AuthorizationConstants;
030: import org.kuali.core.bo.AdHocRoutePerson;
031: import org.kuali.core.bo.AdHocRouteWorkgroup;
032: import org.kuali.core.bo.user.AuthenticationUserId;
033: import org.kuali.core.question.ConfirmationQuestion;
034: import org.kuali.core.service.DocumentAuthorizationService;
035: import org.kuali.core.service.KualiConfigurationService;
036: import org.kuali.core.service.KualiRuleService;
037: import org.kuali.core.service.PersistenceService;
038: import org.kuali.core.service.UniversalUserService;
039: import org.kuali.core.util.GlobalVariables;
040: import org.kuali.kfs.KFSConstants;
041: import org.kuali.kfs.context.SpringContext;
042: import org.kuali.kfs.service.ParameterService;
043: import org.kuali.module.kra.KraConstants;
044: import org.kuali.module.kra.KraKeyConstants;
045: import org.kuali.module.kra.bo.AdhocPerson;
046: import org.kuali.module.kra.bo.AdhocWorkgroup;
047: import org.kuali.module.kra.budget.bo.Budget;
048: import org.kuali.module.kra.budget.bo.BudgetNonpersonnel;
049: import org.kuali.module.kra.budget.document.BudgetDocument;
050: import org.kuali.module.kra.budget.rules.event.EnterModularEvent;
051: import org.kuali.module.kra.budget.rules.event.RunAuditEvent;
052: import org.kuali.module.kra.budget.service.BudgetIndirectCostService;
053: import org.kuali.module.kra.budget.service.BudgetModularService;
054: import org.kuali.module.kra.budget.service.BudgetNonpersonnelService;
055: import org.kuali.module.kra.budget.service.BudgetPersonnelService;
056: import org.kuali.module.kra.budget.service.BudgetTypeCodeService;
057: import org.kuali.module.kra.budget.web.struts.form.BudgetCostShareFormHelper;
058: import org.kuali.module.kra.budget.web.struts.form.BudgetForm;
059: import org.kuali.module.kra.budget.web.struts.form.BudgetIndirectCostFormHelper;
060: import org.kuali.module.kra.budget.web.struts.form.BudgetNonpersonnelFormHelper;
061: import org.kuali.module.kra.budget.web.struts.form.BudgetOverviewFormHelper;
062: import org.kuali.module.kra.web.struts.action.ResearchDocumentActionBase;
063:
064: /**
065: * This class handles Actions for Research Administration.
066: */
067:
068: public class BudgetAction extends ResearchDocumentActionBase {
069:
070: private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger
071: .getLogger(BudgetAction.class);
072:
073: public ActionForward execute(ActionMapping mapping,
074: ActionForm form, HttpServletRequest request,
075: HttpServletResponse response) throws Exception {
076: ActionForward forward = super .execute(mapping, form, request,
077: response);
078:
079: BudgetForm budgetForm = (BudgetForm) form;
080:
081: if (budgetForm.isAuditActivated()) {
082: SpringContext.getBean(KualiRuleService.class).applyRules(
083: new RunAuditEvent(budgetForm.getBudgetDocument()));
084: }
085:
086: if (!GlobalVariables.getErrorMap().isEmpty()
087: && !allowsNavigate(GlobalVariables.getErrorMap())) {
088: return mapping.findForward(KFSConstants.MAPPING_BASIC);
089: }
090:
091: budgetForm.sortCollections();
092:
093: return forward;
094: }
095:
096: @Override
097: /**
098: * Overriding headerTab to customize how clearing tab state works on Budget. Specifically, additional attributes (selected task
099: * and period) should be cleared any time header navigation occurs.
100: */
101: public ActionForward headerTab(ActionMapping mapping,
102: ActionForm form, HttpServletRequest request,
103: HttpServletResponse response) throws Exception {
104:
105: BudgetForm budgetForm = (BudgetForm) form;
106:
107: // This is so that tab states are not shared between pages.
108: budgetForm.newTabState(true, true);
109:
110: return super .headerTab(mapping, form, request, response);
111: }
112:
113: public ActionForward route(ActionMapping mapping, ActionForm form,
114: HttpServletRequest request, HttpServletResponse response)
115: throws Exception {
116:
117: BudgetForm budgetForm = (BudgetForm) form;
118:
119: Object question = request
120: .getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME);
121: KualiConfigurationService kualiConfiguration = SpringContext
122: .getBean(KualiConfigurationService.class);
123:
124: // Logic for DocCancelQuestion.
125: if (question == null) {
126: // Ask for confirmation.
127: return this .performQuestionWithoutInput(mapping, form,
128: request, response,
129: KFSConstants.DOCUMENT_DELETE_QUESTION,
130: KraConstants.QUESTION_ROUTE_DOCUMENT_TO_COMPLETE,
131: KFSConstants.CONFIRMATION_QUESTION, "route", "0");
132: }
133:
134: Object buttonClicked = request
135: .getParameter(KFSConstants.QUESTION_CLICKED_BUTTON);
136:
137: if ((KFSConstants.DOCUMENT_DELETE_QUESTION.equals(question))
138: && ConfirmationQuestion.YES.equals(buttonClicked)) {
139: budgetForm
140: .setAdHocRoutePersons(convertToAdHocRoutePersons(budgetForm
141: .getBudgetDocument().getAdhocPersons()));
142: budgetForm
143: .setAdHocRouteWorkgroups(convertToAdHocRouteWorkgroups(budgetForm
144: .getBudgetDocument().getAdhocWorkgroups()));
145: return super .route(mapping, form, request, response);
146: }
147:
148: return mapping.findForward(KFSConstants.MAPPING_BASIC);
149:
150: }
151:
152: /**
153: * This method will save the document, but only after being successfully validated.
154: *
155: * @param mapping
156: * @param form
157: * @param request
158: * @param response
159: * @throws Exception
160: */
161: public ActionForward save(ActionMapping mapping, ActionForm form,
162: HttpServletRequest request, HttpServletResponse response)
163: throws Exception {
164: BudgetForm budgetForm = (BudgetForm) form;
165: budgetForm.setMethodToCall(KFSConstants.SAVE_METHOD);
166:
167: // Check if user has permission to save
168: budgetForm.populateAuthorizationFields(SpringContext.getBean(
169: DocumentAuthorizationService.class)
170: .getDocumentAuthorizer(budgetForm.getBudgetDocument()));
171: if (!"TRUE".equals(budgetForm.getEditingMode().get(
172: AuthorizationConstants.EditMode.VIEW_ONLY))) {
173: super .save(mapping, form, request, response);
174: }
175:
176: if (budgetForm.isAuditActivated()) {
177: budgetForm.newTabState(true, true);
178: return mapping.findForward("auditmode");
179: }
180: return mapping.findForward(KFSConstants.MAPPING_BASIC);
181: }
182:
183: /**
184: * This method will load the document, which was previously saved
185: *
186: * @param mapping
187: * @param form
188: * @param request
189: * @param response
190: * @return
191: * @throws Exception
192: */
193: public ActionForward load(ActionMapping mapping, ActionForm form,
194: HttpServletRequest request, HttpServletResponse response)
195: throws Exception {
196:
197: BudgetForm budgetForm = (BudgetForm) form;
198: budgetForm.setDocId(budgetForm.getBudgetDocument()
199: .getDocumentNumber());
200: this .loadDocument(budgetForm);
201:
202: return mapping.findForward(KFSConstants.MAPPING_BASIC);
203: }
204:
205: public ActionForward update(ActionMapping mapping, ActionForm form,
206: HttpServletRequest request, HttpServletResponse response)
207: throws Exception {
208: return mapping.findForward(KFSConstants.MAPPING_BASIC);
209: }
210:
211: public ActionForward overview(ActionMapping mapping,
212: ActionForm form, HttpServletRequest request,
213: HttpServletResponse response) throws Exception {
214:
215: this .load(mapping, form, request, response);
216:
217: BudgetForm budgetForm = (BudgetForm) form;
218:
219: budgetForm
220: .setBudgetOverviewFormHelper(new BudgetOverviewFormHelper(
221: budgetForm));
222:
223: return mapping.findForward("overview");
224: }
225:
226: public ActionForward parameters(ActionMapping mapping,
227: ActionForm form, HttpServletRequest request,
228: HttpServletResponse response) throws Exception {
229:
230: this .load(mapping, form, request, response);
231:
232: BudgetForm budgetForm = (BudgetForm) form;
233:
234: // Set default task name
235: String DEFAULT_BUDGET_TASK_NAME = SpringContext.getBean(
236: ParameterService.class).getParameterValue(
237: BudgetDocument.class,
238: KraConstants.DEFAULT_BUDGET_TASK_NAME);
239: budgetForm.getNewTask().setBudgetTaskName(
240: DEFAULT_BUDGET_TASK_NAME
241: + " "
242: + (budgetForm.getBudgetDocument()
243: .getTaskListSize() + 1));
244:
245: // New task defaults to on campus
246: budgetForm.getNewTask().setBudgetTaskOnCampus(true);
247:
248: // Set default budget types
249: setupBudgetTypes(budgetForm);
250:
251: // pre-fetch academic year subdivision names for later use
252: setupAcademicYearSubdivisionConstants(budgetForm);
253:
254: return mapping.findForward("parameters");
255: }
256:
257: public ActionForward template(ActionMapping mapping,
258: ActionForm form, HttpServletRequest request,
259: HttpServletResponse response) throws Exception {
260:
261: this .load(mapping, form, request, response);
262:
263: BudgetForm budgetForm = (BudgetForm) form;
264:
265: return mapping.findForward("template");
266: }
267:
268: public ActionForward personnel(ActionMapping mapping,
269: ActionForm form, HttpServletRequest request,
270: HttpServletResponse response) throws Exception {
271:
272: this .load(mapping, form, request, response);
273: BudgetForm budgetForm = (BudgetForm) form;
274:
275: // This is so that tab states are not shared between pages.
276: budgetForm.newTabState(true, true);
277:
278: budgetForm
279: .setDeleteValues(new String[budgetForm
280: .getBudgetDocument().getBudget().getPersonnel()
281: .size()]);
282:
283: SpringContext.getBean(BudgetPersonnelService.class)
284: .reconcileAndCalculatePersonnel(
285: budgetForm.getBudgetDocument());
286:
287: return mapping.findForward("personnel");
288: }
289:
290: public ActionForward nonpersonnel(ActionMapping mapping,
291: ActionForm form, HttpServletRequest request,
292: HttpServletResponse response) throws Exception {
293:
294: this .load(mapping, form, request, response);
295: BudgetForm budgetForm = (BudgetForm) form;
296:
297: setupNonpersonnelCategories(budgetForm);
298: PersistenceService persistenceService = SpringContext
299: .getBean(PersistenceService.class);
300: persistenceService.retrieveReferenceObject(budgetForm
301: .getBudgetDocument().getBudget(), "nonpersonnelItems");
302: budgetForm
303: .setBudgetNonpersonnelFormHelper(new BudgetNonpersonnelFormHelper(
304: budgetForm));
305:
306: return mapping.findForward("nonpersonnel");
307: }
308:
309: public ActionForward modular(ActionMapping mapping,
310: ActionForm form, HttpServletRequest request,
311: HttpServletResponse response) throws Exception {
312:
313: this .load(mapping, form, request, response);
314: BudgetForm budgetForm = (BudgetForm) form;
315: Budget budget = budgetForm.getBudgetDocument().getBudget();
316:
317: // TODO Shouldn't be necessary but was added to fix KULERA-945: "Navigating from Nonpersonnel to Modular may cause
318: // exception"
319: for (BudgetNonpersonnel budgetNonpersonnel : budget
320: .getNonpersonnelItems()) {
321: budgetNonpersonnel
322: .refreshReferenceObject("nonpersonnelObjectCode");
323: }
324:
325: SpringContext.getBean(BudgetModularService.class)
326: .generateModularBudget(budget,
327: budgetForm.getNonpersonnelCategories());
328:
329: SpringContext.getBean(KualiRuleService.class).applyRules(
330: new EnterModularEvent(budgetForm.getDocument()));
331:
332: return mapping.findForward("modular");
333: }
334:
335: public ActionForward indirectcost(ActionMapping mapping,
336: ActionForm form, HttpServletRequest request,
337: HttpServletResponse response) throws Exception {
338:
339: this .load(mapping, form, request, response);
340:
341: BudgetForm budgetForm = (BudgetForm) form;
342:
343: // Make sure our IDC object is properly formed. This will also perform initial calculations for BudgetTaskPeriodIndirectCost
344: // objects.
345: SpringContext.getBean(BudgetIndirectCostService.class)
346: .refreshIndirectCost(budgetForm.getBudgetDocument());
347:
348: // This will populate task and period totals in HashMaps so they can be pulled in the view.
349: budgetForm
350: .setBudgetIndirectCostFormHelper(new BudgetIndirectCostFormHelper(
351: budgetForm));
352:
353: return mapping.findForward("indirectcost");
354: }
355:
356: public ActionForward costshare(ActionMapping mapping,
357: ActionForm form, HttpServletRequest request,
358: HttpServletResponse response) throws Exception {
359:
360: this .load(mapping, form, request, response);
361:
362: BudgetForm budgetForm = (BudgetForm) form;
363:
364: setupBudgetCostSharePermissionDisplay(budgetForm);
365:
366: SpringContext.getBean(BudgetIndirectCostService.class)
367: .refreshIndirectCost(budgetForm.getBudgetDocument());
368: budgetForm
369: .setBudgetIndirectCostFormHelper(new BudgetIndirectCostFormHelper(
370: budgetForm));
371: budgetForm
372: .setBudgetCostShareFormHelper(new BudgetCostShareFormHelper(
373: budgetForm));
374: budgetForm.getNewInstitutionCostShare().setPermissionIndicator(
375: true);
376:
377: return mapping.findForward("costshare");
378: }
379:
380: public ActionForward output(ActionMapping mapping, ActionForm form,
381: HttpServletRequest request, HttpServletResponse response)
382: throws Exception {
383:
384: this .load(mapping, form, request, response);
385:
386: BudgetForm budgetForm = (BudgetForm) form;
387:
388: return mapping.findForward("output");
389: }
390:
391: public ActionForward auditmode(ActionMapping mapping,
392: ActionForm form, HttpServletRequest request,
393: HttpServletResponse response) throws Exception {
394:
395: this .load(mapping, form, request, response);
396:
397: BudgetForm budgetForm = (BudgetForm) form;
398:
399: return mapping.findForward("auditmode");
400: }
401:
402: public ActionForward permissions(ActionMapping mapping,
403: ActionForm form, HttpServletRequest request,
404: HttpServletResponse response) throws Exception {
405:
406: this .load(mapping, form, request, response);
407:
408: BudgetForm budgetForm = (BudgetForm) form;
409:
410: budgetForm.setInitiator(SpringContext.getBean(
411: UniversalUserService.class).getUniversalUser(
412: new AuthenticationUserId(budgetForm.getDocument()
413: .getDocumentHeader().getWorkflowDocument()
414: .getInitiatorNetworkId())));
415:
416: budgetForm.getBudgetDocument().populateDocumentForRouting();
417: budgetForm.getBudgetDocument().getDocumentHeader()
418: .getWorkflowDocument().saveRoutingData();
419:
420: return mapping.findForward("permissions");
421: }
422:
423: /**
424: * This method will setup the message that will get displayed to the user when they are asked to confirm a delete.
425: *
426: * @param confirmationContext
427: * @param kualiConfiguration
428: * @return The message to display to the user in the question prompt window.
429: * @throws Exception
430: */
431: protected String buildBudgetConfirmationQuestion(
432: String confirmationContext,
433: KualiConfigurationService kualiConfiguration)
434: throws Exception {
435: return StringUtils
436: .replace(
437: kualiConfiguration
438: .getPropertyString(KraKeyConstants.QUESTION_KRA_DELETE_CONFIRMATION),
439: "{0}", confirmationContext);
440: }
441:
442: /**
443: * This method...
444: *
445: * @param budgetForm
446: * @throws Exception
447: */
448: public static void setupNonpersonnelCategories(BudgetForm budgetForm)
449: throws Exception {
450: List allNonpersonnelCategories = SpringContext.getBean(
451: BudgetNonpersonnelService.class)
452: .getAllNonpersonnelCategories();
453: budgetForm.setNonpersonnelCategories(allNonpersonnelCategories);
454: }
455:
456: /**
457: * This method gets the default budget types from the reference table and sets it in the BudgetForm
458: *
459: * @param budgetForm
460: * @throws Exception
461: */
462: protected static void setupBudgetTypes(BudgetForm budgetForm)
463: throws Exception {
464:
465: budgetForm.getBudgetDocument().getBudget()
466: .refreshReferenceObject("budgetAgency");
467: budgetForm.setSupportsModular(SpringContext.getBean(
468: BudgetModularService.class).agencySupportsModular(
469: budgetForm.getBudgetDocument().getBudget()
470: .getBudgetAgency()));
471:
472: List allBudgetTypes = (List) SpringContext.getBean(
473: BudgetTypeCodeService.class)
474: .getDefaultBudgetTypeCodes();
475: budgetForm.setBudgetTypeCodes(allBudgetTypes);
476: }
477:
478: /**
479: * This method gets the names of the academic year subdivisions and sets them in the BudgetForm
480: *
481: * @param budgetForm
482: * @throws Exception
483: */
484: protected static void setupAcademicYearSubdivisionConstants(
485: BudgetForm budgetForm) throws Exception {
486: List<String> academicYearSubdivisionNames = SpringContext
487: .getBean(ParameterService.class)
488: .getParameterValues(
489: BudgetDocument.class,
490: KraConstants.KRA_BUDGET_ACADEMIC_YEAR_SUBDIVISION_NAMES);
491: budgetForm
492: .setAcademicYearSubdivisionNames(academicYearSubdivisionNames);
493: budgetForm
494: .setNumberOfAcademicYearSubdivisions(Integer
495: .parseInt(SpringContext
496: .getBean(ParameterService.class)
497: .getParameterValue(
498: BudgetDocument.class,
499: KraConstants.KRA_BUDGET_NUMBER_OF_ACADEMIC_YEAR_SUBDIVISIONS)));
500: }
501:
502: private static List<AdHocRoutePerson> convertToAdHocRoutePersons(
503: List<AdhocPerson> adHocPermissions) {
504: List<AdHocRoutePerson> adHocRoutePersons = new ArrayList<AdHocRoutePerson>();
505: for (AdhocPerson adHocPermission : adHocPermissions) {
506: SpringContext.getBean(PersistenceService.class)
507: .refreshAllNonUpdatingReferences(adHocPermission);
508: AdHocRoutePerson adHocRoutePerson = new AdHocRoutePerson();
509: adHocRoutePerson.setId(adHocPermission.getUser()
510: .getPersonUserIdentifier());
511: adHocRoutePerson.setActionRequested("F");
512: adHocRoutePersons.add(adHocRoutePerson);
513: }
514: return adHocRoutePersons;
515: }
516:
517: private static List<AdHocRouteWorkgroup> convertToAdHocRouteWorkgroups(
518: List<AdhocWorkgroup> adHocWorkgroups) {
519: List<AdHocRouteWorkgroup> adHocRouteWorkgroups = new ArrayList<AdHocRouteWorkgroup>();
520: for (AdhocWorkgroup adHocWorkgroup : adHocWorkgroups) {
521: SpringContext.getBean(PersistenceService.class)
522: .refreshAllNonUpdatingReferences(adHocWorkgroup);
523: AdHocRouteWorkgroup adHocRouteWorkgroup = new AdHocRouteWorkgroup();
524: adHocRouteWorkgroup
525: .setId(adHocWorkgroup.getWorkgroupName());
526: adHocRouteWorkgroup.setActionRequested("F");
527: adHocRouteWorkgroups.add(adHocRouteWorkgroup);
528: }
529: return adHocRouteWorkgroups;
530: }
531:
532: protected static void setupBudgetCostSharePermissionDisplay(
533: BudgetForm budgetForm) {
534: String costSharePermissionCode = SpringContext.getBean(
535: ParameterService.class).getParameterValue(
536: BudgetDocument.class,
537: KraConstants.BUDGET_COST_SHARE_PERMISSION_CODE);
538: if (costSharePermissionCode
539: .equals(KraConstants.COST_SHARE_PERMISSION_CODE_OPTIONAL)) {
540: budgetForm.setDisplayCostSharePermission(true);
541: }
542: }
543:
544: /**
545: * We want to allow navigation for a couple of specific errors. So find these here.
546: *
547: * @param map
548: * @return boolean
549: */
550: protected static boolean allowsNavigate(Map map) {
551: int counter = 0;
552: if (map.containsKey("document.budget.modular.tooLarge")) {
553: counter += 1;
554: }
555: return map.size() == counter;
556: }
557: }
|