001 /** 002 * Copyright 2004-2012 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.hr.time.detail.web; 017 018 import java.sql.Date; 019 import java.sql.Timestamp; 020 import java.text.SimpleDateFormat; 021 import java.util.ArrayList; 022 import java.util.Collection; 023 import java.util.Collections; 024 import java.util.HashSet; 025 import java.util.List; 026 import java.util.Map; 027 import java.util.Set; 028 029 import javax.servlet.http.HttpServletRequest; 030 import javax.servlet.http.HttpServletResponse; 031 032 import org.apache.commons.lang.StringUtils; 033 import org.apache.struts.action.ActionForm; 034 import org.apache.struts.action.ActionForward; 035 import org.apache.struts.action.ActionMapping; 036 import org.joda.time.DateTime; 037 import org.joda.time.Interval; 038 import org.kuali.hr.time.assignment.Assignment; 039 import org.kuali.hr.time.calendar.Calendar; 040 import org.kuali.hr.time.calendar.CalendarEntries; 041 import org.kuali.hr.time.calendar.TkCalendar; 042 import org.kuali.hr.time.roles.TkUserRoles; 043 import org.kuali.hr.time.roles.UserRoles; 044 import org.kuali.hr.time.service.base.TkServiceLocator; 045 import org.kuali.hr.time.task.Task; 046 import org.kuali.hr.time.timeblock.TimeBlock; 047 import org.kuali.hr.time.timeblock.TimeBlockHistory; 048 import org.kuali.hr.time.timesheet.TimesheetDocument; 049 import org.kuali.hr.time.timesheet.web.TimesheetAction; 050 import org.kuali.hr.time.timesheet.web.TimesheetActionForm; 051 import org.kuali.hr.time.timesummary.AssignmentRow; 052 import org.kuali.hr.time.timesummary.EarnCodeSection; 053 import org.kuali.hr.time.timesummary.EarnGroupSection; 054 import org.kuali.hr.time.timesummary.TimeSummary; 055 import org.kuali.hr.time.util.TKContext; 056 import org.kuali.hr.time.util.TKUser; 057 import org.kuali.hr.time.util.TKUtils; 058 import org.kuali.hr.time.util.TkConstants; 059 import org.kuali.hr.time.util.TkTimeBlockAggregate; 060 import org.kuali.hr.time.workflow.TimesheetDocumentHeader; 061 import org.kuali.rice.kew.service.KEWServiceLocator; 062 import org.kuali.rice.krad.exception.AuthorizationException; 063 import org.kuali.rice.krad.util.GlobalVariables; 064 065 public class TimeDetailAction extends TimesheetAction { 066 067 @Override 068 protected void checkTKAuthorization(ActionForm form, String methodToCall) throws AuthorizationException { 069 super.checkTKAuthorization(form, methodToCall); // Checks for read access first. 070 TKUser user = TKContext.getUser(); 071 UserRoles roles = TkUserRoles.getUserRoles(GlobalVariables.getUserSession().getPrincipalId()); 072 TimesheetDocument doc = TKContext.getCurrentTimesheetDocument(); 073 074 // Check for write access to Timeblock. 075 if (StringUtils.equals(methodToCall, "addTimeBlock") || StringUtils.equals(methodToCall, "deleteTimeBlock") || StringUtils.equals(methodToCall, "updateTimeBlock")) { 076 if (!roles.isDocumentWritable(doc)) { 077 throw new AuthorizationException(roles.getPrincipalId(), "TimeDetailAction", ""); 078 } 079 } 080 } 081 082 @Override 083 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 084 ActionForward forward = super.execute(mapping, form, request, response); 085 if (forward.getRedirect()) { 086 return forward; 087 } 088 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 089 tdaf.setAssignmentDescriptions(TkServiceLocator.getAssignmentService().getAssignmentDescriptions(TKContext.getCurrentTimesheetDocument(), false)); 090 091 // Handle User preference / timezone information (pushed up from TkCalendar to avoid duplication) 092 // Set calendar 093 CalendarEntries payCalendarEntry = tdaf.getPayCalendarDates(); 094 Calendar payCalendar = TkServiceLocator.getCalendarService().getCalendar(payCalendarEntry.getHrCalendarId()); 095 096 //List<TimeBlock> timeBlocks = TkServiceLocator.getTimeBlockService().getTimeBlocks(Long.parseLong(tdaf.getTimesheetDocument().getDocumentHeader().getTimesheetDocumentId())); 097 List<TimeBlock> timeBlocks = TKContext.getCurrentTimesheetDocument().getTimeBlocks(); 098 099 this.assignStypeClassMapForTimeSummary(tdaf,timeBlocks); 100 101 List<Interval> intervals = TKUtils.getFullWeekDaySpanForCalendarEntry(payCalendarEntry); 102 TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(timeBlocks, payCalendarEntry, payCalendar, true, intervals); 103 TkCalendar cal = TkCalendar.getCalendar(aggregate); 104 cal.assignAssignmentStyle(tdaf.getAssignStyleClassMap()); 105 tdaf.setTkCalendar(cal); 106 107 this.populateCalendarAndPayPeriodLists(request, tdaf); 108 109 tdaf.setTimeBlockString(ActionFormUtils.getTimeBlocksJson(aggregate.getFlattenedTimeBlockList())); 110 111 tdaf.setOvertimeEarnCodes(TkServiceLocator.getEarnCodeService().getOvertimeEarnCodesStrs(TKContext.getCurrentTimesheetDocument().getAsOfDate())); 112 113 if (StringUtils.equals(TKContext.getCurrentTimesheetDocument().getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId())) { 114 tdaf.setWorkingOnItsOwn("true"); 115 } 116 117 tdaf.setDocEditable("false"); 118 if (TKContext.getUser().isSystemAdmin()) { 119 tdaf.setDocEditable("true"); 120 } else { 121 boolean docFinal = TKContext.getCurrentTimesheetDocument().getDocumentHeader().getDocumentStatus().equals(TkConstants.ROUTE_STATUS.FINAL); 122 if (!docFinal) { 123 if(StringUtils.equals(TKContext.getCurrentTimesheetDocument().getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId()) 124 || TKContext.getUser().isSystemAdmin() 125 || TKContext.getUser().isLocationAdmin() 126 || TKContext.getUser().isDepartmentAdmin() 127 || TKContext.getUser().isReviewer() 128 || TKContext.getUser().isApprover()) { 129 tdaf.setDocEditable("true"); 130 } 131 132 //if the timesheet has been approved by at least one of the approvers, the employee should not be able to edit it 133 if (StringUtils.equals(TKContext.getCurrentTimesheetDocument().getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId()) 134 && TKContext.getCurrentTimesheetDocument().getDocumentHeader().getDocumentStatus().equals(TkConstants.ROUTE_STATUS.ENROUTE)) { 135 Collection actions = KEWServiceLocator.getActionTakenService().findByDocIdAndAction(TKContext.getCurrentTimesheetDocument().getDocumentHeader().getDocumentId(), TkConstants.DOCUMENT_ACTIONS.APPROVE); 136 if(!actions.isEmpty()) { 137 tdaf.setDocEditable("false"); 138 } 139 } 140 } 141 } 142 143 return forward; 144 } 145 146 // use lists of time blocks and leave blocks to build the style class map and assign css class to associated summary rows 147 private void assignStypeClassMapForTimeSummary(TimeDetailActionForm tdaf, List<TimeBlock> timeBlocks) throws Exception { 148 TimeSummary ts = TkServiceLocator.getTimeSummaryService().getTimeSummary(TKContext.getCurrentTimesheetDocument()); 149 tdaf.setAssignStyleClassMap(ActionFormUtils.buildAssignmentStyleClassMap(timeBlocks)); 150 Map<String, String> aMap = tdaf.getAssignStyleClassMap(); 151 // set css classes for each assignment row 152 for (EarnGroupSection earnGroupSection : ts.getSections()) { 153 for (EarnCodeSection section : earnGroupSection.getEarnCodeSections()) { 154 for (AssignmentRow assignRow : section.getAssignmentsRows()) { 155 if (assignRow.getAssignmentKey() != null && aMap.containsKey(assignRow.getAssignmentKey())) { 156 assignRow.setCssClass(aMap.get(assignRow.getAssignmentKey())); 157 } else { 158 assignRow.setCssClass(""); 159 } 160 } 161 } 162 163 } 164 tdaf.setTimeSummary(ts); 165 ActionFormUtils.validateHourLimit(tdaf); 166 ActionFormUtils.addWarningTextFromEarnGroup(tdaf); 167 } 168 169 private void populateCalendarAndPayPeriodLists(HttpServletRequest request, TimeDetailActionForm tdaf) { 170 List<TimesheetDocumentHeader> documentHeaders = (List<TimesheetDocumentHeader>) TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeadersForPrincipalId(GlobalVariables.getUserSession().getPrincipalId()); 171 SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); 172 if(tdaf.getCalendarYears().isEmpty()) { 173 // get calendar year drop down list contents 174 Set<String> yearSet = new HashSet<String>(); 175 176 for(TimesheetDocumentHeader tdh : documentHeaders) { 177 yearSet.add(sdf.format(tdh.getPayBeginDate())); 178 } 179 List<String> yearList = new ArrayList<String>(yearSet); 180 Collections.sort(yearList); 181 Collections.reverse(yearList); // newest on top 182 tdaf.setCalendarYears(yearList); 183 } 184 // if selected calendar year is passed in 185 if(request.getParameter("selectedCY")!= null) { 186 tdaf.setSelectedCalendarYear(request.getParameter("selectedCY").toString()); 187 } 188 // if there is no selected calendr year, use the year of current pay calendar entry 189 if(StringUtils.isEmpty(tdaf.getSelectedCalendarYear())) { 190 tdaf.setSelectedCalendarYear(sdf.format(tdaf.getPayCalendarDates().getBeginPeriodDate())); 191 } 192 if(tdaf.getPayPeriodsMap().isEmpty()) { 193 List<CalendarEntries> payPeriodList = new ArrayList<CalendarEntries>(); 194 for(TimesheetDocumentHeader tdh : documentHeaders) { 195 if(sdf.format(tdh.getPayBeginDate()).equals(tdaf.getSelectedCalendarYear())) { 196 CalendarEntries pe = TkServiceLocator.getCalendarEntriesService().getCalendarEntriesByBeginAndEndDate(tdh.getPayBeginDate(), tdh.getPayEndDate()); 197 payPeriodList.add(pe); 198 } 199 } 200 tdaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(payPeriodList)); 201 } 202 if(request.getParameter("selectedPP")!= null) { 203 tdaf.setSelectedPayPeriod(request.getParameter("selectedPP").toString()); 204 } 205 if(StringUtils.isEmpty(tdaf.getSelectedPayPeriod())) { 206 tdaf.setSelectedPayPeriod(tdaf.getPayCalendarDates().getHrCalendarEntriesId()); 207 } 208 } 209 210 211 /** 212 * This method involves creating an object-copy of every TimeBlock on the 213 * time sheet for overtime re-calculation. 214 * 215 * @throws Exception 216 */ 217 public ActionForward deleteTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 218 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 219 //Grab timeblock to be deleted from form 220 List<TimeBlock> timeBlocks = tdaf.getTimesheetDocument().getTimeBlocks(); 221 TimeBlock deletedTimeBlock = null; 222 for (TimeBlock tb : timeBlocks) { 223 if (tb.getTkTimeBlockId().compareTo(tdaf.getTkTimeBlockId()) == 0) { 224 deletedTimeBlock = tb; 225 break; 226 } 227 } 228 //Remove from the list of timeblocks 229 List<TimeBlock> referenceTimeBlocks = new ArrayList<TimeBlock>(tdaf.getTimesheetDocument().getTimeBlocks().size()); 230 for (TimeBlock b : tdaf.getTimesheetDocument().getTimeBlocks()) { 231 referenceTimeBlocks.add(b.copy()); 232 } 233 234 // simple pointer, for clarity 235 List<TimeBlock> newTimeBlocks = tdaf.getTimesheetDocument().getTimeBlocks(); 236 newTimeBlocks.remove(deletedTimeBlock); 237 238 //Delete timeblock 239 TkServiceLocator.getTimeBlockService().deleteTimeBlock(deletedTimeBlock); 240 // Add a row to the history table 241 TimeBlockHistory tbh = new TimeBlockHistory(deletedTimeBlock); 242 tbh.setActionHistory(TkConstants.ACTIONS.DELETE_TIME_BLOCK); 243 TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh); 244 //reset time block 245 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks); 246 TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.ADD_TIME_BLOCK, newTimeBlocks, tdaf.getPayCalendarDates(), tdaf.getTimesheetDocument(), TKContext.getPrincipalId()); 247 TkServiceLocator.getTimeBlockService().saveTimeBlocks(referenceTimeBlocks, newTimeBlocks); 248 249 return mapping.findForward("basic"); 250 } 251 252 /** 253 * This method involves creating an object-copy of every TimeBlock on the 254 * time sheet for overtime re-calculation. 255 * 256 * @throws Exception 257 */ 258 public ActionForward addTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 259 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 260 this.changeTimeBlocks(tdaf); 261 262 ActionFormUtils.validateHourLimit(tdaf); 263 ActionFormUtils.addWarningTextFromEarnGroup(tdaf); 264 265 return mapping.findForward("basic"); 266 } 267 268 private void removeOldTimeBlock(TimeDetailActionForm tdaf) { 269 if (tdaf.getTkTimeBlockId() != null) { 270 TimeBlock tb = TkServiceLocator.getTimeBlockService().getTimeBlock(tdaf.getTkTimeBlockId()); 271 if (tb != null) { 272 TimeBlockHistory tbh = new TimeBlockHistory(tb); 273 TkServiceLocator.getTimeBlockService().deleteTimeBlock(tb); 274 275 // mark the original timeblock as deleted in the history table 276 tbh.setActionHistory(TkConstants.ACTIONS.DELETE_TIME_BLOCK); 277 TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh); 278 279 // delete the timeblock from the memory 280 tdaf.getTimesheetDocument().getTimeBlocks().remove(tb); 281 } 282 } 283 } 284 285 286 // add/update time blocks 287 private void changeTimeBlocks(TimeDetailActionForm tdaf) { 288 Timestamp overtimeBeginTimestamp = null; 289 Timestamp overtimeEndTimestamp = null; 290 291 // This is for updating a timeblock or changing 292 // If tkTimeBlockId is not null and the new timeblock is valid, delete the existing timeblock and a new one will be created after submitting the form. 293 if (tdaf.getTkTimeBlockId() != null) { 294 TimeBlock tb = TkServiceLocator.getTimeBlockService().getTimeBlock(tdaf.getTkTimeBlockId()); 295 if (StringUtils.isNotEmpty(tdaf.getOvertimePref())) { 296 overtimeBeginTimestamp = tb.getBeginTimestamp(); 297 overtimeEndTimestamp = tb.getEndTimestamp(); 298 } 299 this.removeOldTimeBlock(tdaf); 300 } 301 302 Assignment assignment = TkServiceLocator.getAssignmentService().getAssignment(tdaf.getTimesheetDocument(), tdaf.getSelectedAssignment()); 303 304 305 // Surgery point - Need to construct a Date/Time with Appropriate Timezone. 306 Timestamp startTime = TKUtils.convertDateStringToTimestamp(tdaf.getStartDate(), tdaf.getStartTime()); 307 Timestamp endTime = TKUtils.convertDateStringToTimestamp(tdaf.getEndDate(), tdaf.getEndTime()); 308 309 // We need a cloned reference set so we know whether or not to 310 // persist any potential changes without making hundreds of DB calls. 311 List<TimeBlock> referenceTimeBlocks = new ArrayList<TimeBlock>(tdaf.getTimesheetDocument().getTimeBlocks().size()); 312 for (TimeBlock tb : tdaf.getTimesheetDocument().getTimeBlocks()) { 313 referenceTimeBlocks.add(tb.copy()); 314 } 315 316 // This is just a reference, for code clarity, the above list is actually 317 // separate at the object level. 318 List<TimeBlock> newTimeBlocks = tdaf.getTimesheetDocument().getTimeBlocks(); 319 DateTime startTemp = new DateTime(startTime); 320 DateTime endTemp = new DateTime(endTime); 321 // KPME-1446 add spanningweeks to the calls below 322 if (StringUtils.equals(tdaf.getAcrossDays(), "y") 323 && !(endTemp.getDayOfYear() - startTemp.getDayOfYear() <= 1 324 && endTemp.getHourOfDay() == 0)) { 325 newTimeBlocks.addAll(TkServiceLocator.getTimeBlockService().buildTimeBlocksSpanDates(assignment, 326 tdaf.getSelectedEarnCode(), tdaf.getTimesheetDocument(), startTime, 327 endTime, tdaf.getHours(), tdaf.getAmount(), false, Boolean.parseBoolean(tdaf.getLunchDeleted()), tdaf.getSpanningWeeks())); 328 } else { 329 newTimeBlocks.addAll(TkServiceLocator.getTimeBlockService().buildTimeBlocks(assignment, 330 tdaf.getSelectedEarnCode(), tdaf.getTimesheetDocument(), startTime, 331 endTime, tdaf.getHours(), tdaf.getAmount(), false, Boolean.parseBoolean(tdaf.getLunchDeleted()))); 332 } 333 334 //reset time block 335 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks); 336 337 // apply overtime pref 338 for (TimeBlock tb : newTimeBlocks) { 339 if (tb.getBeginTimestamp().equals(overtimeBeginTimestamp) && tb.getEndTimestamp().equals(overtimeEndTimestamp) && StringUtils.isNotEmpty(tdaf.getOvertimePref())) { 340 tb.setOvertimePref(tdaf.getOvertimePref()); 341 } 342 343 } 344 345 TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.ADD_TIME_BLOCK, newTimeBlocks, tdaf.getPayCalendarDates(), tdaf.getTimesheetDocument(), TKContext.getPrincipalId()); 346 TkServiceLocator.getTimeBlockService().saveTimeBlocks(referenceTimeBlocks, newTimeBlocks); 347 } 348 349 public ActionForward updateTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 350 351 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 352 Assignment assignment = TkServiceLocator.getAssignmentService().getAssignment(tdaf.getTimesheetDocument(), tdaf.getSelectedAssignment()); 353 354 //Grab timeblock to be updated from form 355 List<TimeBlock> timeBlocks = tdaf.getTimesheetDocument().getTimeBlocks(); 356 TimeBlock updatedTimeBlock = null; 357 for (TimeBlock tb : timeBlocks) { 358 if (tb.getTkTimeBlockId().compareTo(tdaf.getTkTimeBlockId()) == 0) { 359 updatedTimeBlock = tb; 360 tb.setJobNumber(assignment.getJobNumber()); 361 tb.setWorkArea(assignment.getWorkArea()); 362 tb.setTask(assignment.getTask()); 363 tb.setTkWorkAreaId(assignment.getWorkAreaObj().getTkWorkAreaId()); 364 tb.setHrJobId(assignment.getJob().getHrJobId()); 365 String tkTaskId = "0"; 366 for (Task task : assignment.getWorkAreaObj().getTasks()) { 367 if (task.getTask().compareTo(assignment.getTask()) == 0) { 368 tkTaskId = task.getTkTaskId(); 369 break; 370 } 371 } 372 tb.setTkTaskId(tkTaskId); 373 break; 374 } 375 } 376 377 TkServiceLocator.getTimeBlockService().updateTimeBlock(updatedTimeBlock); 378 379 TimeBlockHistory tbh = new TimeBlockHistory(updatedTimeBlock); 380 tbh.setActionHistory(TkConstants.ACTIONS.UPDATE_TIME_BLOCK); 381 TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh); 382 tdaf.setMethodToCall("addTimeBlock"); 383 return mapping.findForward("basic"); 384 } 385 386 387 public ActionForward actualTimeInquiry(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 388 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 389 return mapping.findForward("ati"); 390 } 391 392 public ActionForward deleteLunchDeduction(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 393 394 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 395 String timeHourDetailId = tdaf.getTkTimeHourDetailId(); 396 TkServiceLocator.getTimeBlockService().deleteLunchDeduction(timeHourDetailId); 397 398 List<TimeBlock> newTimeBlocks = tdaf.getTimesheetDocument().getTimeBlocks(); 399 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks); 400 401 return mapping.findForward("basic"); 402 } 403 404 public ActionForward gotoCurrentPayPeriod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 405 String viewPrincipal = TKUser.getCurrentTargetPerson().getPrincipalId(); 406 Date currentDate = TKUtils.getTimelessDate(null); 407 CalendarEntries pce = TkServiceLocator.getCalendarService().getCurrentCalendarDates(viewPrincipal, currentDate); 408 TimesheetDocument td = TkServiceLocator.getTimesheetService().openTimesheetDocument(viewPrincipal, pce); 409 setupDocumentOnFormContext((TimesheetActionForm)form, td); 410 return mapping.findForward("basic"); 411 } 412 413 //Triggered by changes of pay period drop down list, reload the whole page based on the selected pay period 414 public ActionForward changeCalendarYear(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 415 416 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 417 if(request.getParameter("selectedCY") != null) { 418 tdaf.setSelectedCalendarYear(request.getParameter("selectedCY").toString()); 419 } 420 return mapping.findForward("basic"); 421 } 422 423 //Triggered by changes of pay period drop down list, reload the whole page based on the selected pay period 424 public ActionForward changePayPeriod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 425 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 426 if(request.getParameter("selectedPP") != null) { 427 tdaf.setSelectedPayPeriod(request.getParameter("selectedPP").toString()); 428 CalendarEntries pce = TkServiceLocator.getCalendarEntriesService() 429 .getCalendarEntries(request.getParameter("selectedPP").toString()); 430 if(pce != null) { 431 String viewPrincipal = TKUser.getCurrentTargetPerson().getPrincipalId(); 432 TimesheetDocument td = TkServiceLocator.getTimesheetService().openTimesheetDocument(viewPrincipal, pce); 433 setupDocumentOnFormContext((TimesheetActionForm)form, td); 434 } 435 } 436 return mapping.findForward("basic"); 437 } 438 439 }