View Javadoc

1   /**
2    * Copyright 2004-2012 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.hr.time.timesheet.service;
17  
18  import java.math.BigDecimal;
19  import java.sql.Timestamp;
20  import java.util.ArrayList;
21  import java.util.Date;
22  import java.util.LinkedList;
23  import java.util.List;
24  
25  import org.apache.commons.lang.StringUtils;
26  import org.apache.log4j.Logger;
27  import org.kuali.hr.job.Job;
28  import org.kuali.hr.time.assignment.Assignment;
29  import org.kuali.hr.time.calendar.CalendarEntries;
30  import org.kuali.hr.time.holidaycalendar.HolidayCalendar;
31  import org.kuali.hr.time.holidaycalendar.HolidayCalendarDateEntry;
32  import org.kuali.hr.time.principal.PrincipalHRAttributes;
33  import org.kuali.hr.time.service.base.TkServiceLocator;
34  import org.kuali.hr.time.timeblock.TimeBlock;
35  import org.kuali.hr.time.timesheet.TimesheetDocument;
36  import org.kuali.hr.time.util.TKContext;
37  import org.kuali.hr.time.util.TKUser;
38  import org.kuali.hr.time.util.TKUtils;
39  import org.kuali.hr.time.util.TkConstants;
40  import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
41  import org.kuali.rice.kew.api.WorkflowDocument;
42  import org.kuali.rice.kew.api.WorkflowDocumentFactory;
43  import org.kuali.rice.kew.api.exception.WorkflowException;
44  import org.kuali.rice.kew.service.KEWServiceLocator;
45  
46  public class TimesheetServiceImpl implements TimesheetService {
47  
48      @SuppressWarnings("unused")
49      private static final Logger LOG = Logger.getLogger(TimesheetServiceImpl.class);
50  
51      @Override
52      public void routeTimesheet(String principalId, TimesheetDocument timesheetDocument) {
53          routeTimesheet(TkConstants.DOCUMENT_ACTIONS.ROUTE, principalId, timesheetDocument);
54      }
55  
56      @Override
57      public void routeTimesheet(String action, String principalId, TimesheetDocument timesheetDocument) {
58          timesheetAction(action, principalId, timesheetDocument);
59      }
60  
61      @Override
62      public void approveTimesheet(String principalId, TimesheetDocument timesheetDocument) {
63          timesheetAction(TkConstants.DOCUMENT_ACTIONS.APPROVE, principalId, timesheetDocument);
64      }
65  
66      @Override
67      public void approveTimesheet(String principalId, TimesheetDocument timesheetDocument, String action) {
68          timesheetAction(action, principalId, timesheetDocument);
69      }
70  
71      @Override
72      public void disapproveTimesheet(String principalId, TimesheetDocument timesheetDocument) {
73          timesheetAction(TkConstants.DOCUMENT_ACTIONS.DISAPPROVE, principalId, timesheetDocument);
74      }
75  
76      protected void timesheetAction(String action, String principalId, TimesheetDocument timesheetDocument) {
77          WorkflowDocument wd = null;
78          if (timesheetDocument != null) {
79                  String rhid = timesheetDocument.getDocumentId();
80                  wd = WorkflowDocumentFactory.loadDocument(principalId, rhid);
81  
82                  if (StringUtils.equals(action, TkConstants.DOCUMENT_ACTIONS.ROUTE)) {
83                      wd.route("Routing for Approval");
84                  } else if (StringUtils.equals(action, TkConstants.BATCH_JOB_ACTIONS.BATCH_JOB_ROUTE)) {
85                      wd.route("Batch job routing for Approval");
86                  } else if (StringUtils.equals(action, TkConstants.DOCUMENT_ACTIONS.APPROVE)) {
87                      if (TKContext.getUser().getCurrentTargetRoles().isSystemAdmin() &&
88                              !TKContext.getUser().getCurrentTargetRoles().isApproverForTimesheet(timesheetDocument)) {
89                          wd.superUserBlanketApprove("Superuser approving timesheet.");
90                      } else {
91                          wd.approve("Approving timesheet.");
92                      }
93                  } else if (StringUtils.equals(action, TkConstants.BATCH_JOB_ACTIONS.BATCH_JOB_APPROVE)) {
94                      wd.superUserBlanketApprove("Batch job superuser approving timesheet.");
95                  } else if (StringUtils.equals(action, TkConstants.DOCUMENT_ACTIONS.DISAPPROVE)) {
96                      if (TKContext.getUser().getCurrentTargetRoles().isSystemAdmin()
97                              && !TKContext.getUser().getCurrentTargetRoles().isApproverForTimesheet(timesheetDocument)) {
98                          wd.superUserDisapprove("Superuser disapproving timesheet.");
99                      } else {
100                         wd.disapprove("Disapproving timesheet.");
101                     }
102                 }
103 
104                 String kewStatus = KEWServiceLocator.getRouteHeaderService().getDocumentStatus(timesheetDocument.getDocumentId());                		
105                 if (!kewStatus.equals(timesheetDocument.getDocumentHeader().getDocumentStatus())) {
106                     timesheetDocument.getDocumentHeader().setDocumentStatus(kewStatus);
107                     TkServiceLocator.getTimesheetDocumentHeaderService().saveOrUpdate(timesheetDocument.getDocumentHeader());
108                 }
109                 
110         }
111     }
112 
113     @Override
114     public TimesheetDocument openTimesheetDocument(String principalId, CalendarEntries calendarDates) throws WorkflowException {
115         TimesheetDocument timesheetDocument = null;
116 
117         Date begin = calendarDates.getBeginPeriodDateTime();
118         Date end = calendarDates.getEndPeriodDateTime();
119 
120         TimesheetDocumentHeader header = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(principalId, begin, end);
121 
122         if (header == null) {
123             List<Assignment> activeAssignments = TkServiceLocator.getAssignmentService().getAssignmentsByPayEntry(principalId, calendarDates);
124             //TkServiceLocator.getAssignmentService().getAssignments(principalId, TKUtils.getTimelessDate(payCalendarDates.getEndPeriodDate()));
125             if (activeAssignments.size() == 0) {
126                 throw new RuntimeException("No active assignments for " + principalId + " for " + calendarDates.getEndPeriodDate());
127             }
128             timesheetDocument = this.initiateWorkflowDocument(principalId, begin, end, TimesheetDocument.TIMESHEET_DOCUMENT_TYPE, TimesheetDocument.TIMESHEET_DOCUMENT_TITLE);
129             timesheetDocument.setPayCalendarEntry(calendarDates);
130             this.loadTimesheetDocumentData(timesheetDocument, principalId, calendarDates);
131 
132             this.loadHolidaysOnTimesheet(timesheetDocument, principalId, begin, end);
133         } else {
134             timesheetDocument = this.getTimesheetDocument(header.getDocumentId());
135             timesheetDocument.setPayCalendarEntry(calendarDates);
136         }
137 
138         timesheetDocument.setTimeSummary(TkServiceLocator.getTimeSummaryService().getTimeSummary(timesheetDocument));
139         return timesheetDocument;
140     }
141 
142     public void loadHolidaysOnTimesheet(TimesheetDocument timesheetDocument, String principalId, Date beginDate, Date endDate) {
143         PrincipalHRAttributes principalCalendar = TkServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(principalId, new java.sql.Date(beginDate.getTime()));
144         if (principalCalendar != null) {
145             HolidayCalendar holidayCalendar = TkServiceLocator.getHolidayCalendarService().getHolidayCalendarByGroup(principalCalendar.getHolidayCalendarGroup());
146             if (holidayCalendar != null) {
147                 List<HolidayCalendarDateEntry> lstHolidays = TkServiceLocator.getHolidayCalendarService().getHolidayCalendarDateEntriesForPayPeriod(holidayCalendar.getHrHolidayCalendarId(),
148                         beginDate, endDate);
149                 for (HolidayCalendarDateEntry holiday : lstHolidays) {
150                     Assignment holidayAssign = TkServiceLocator.getHolidayCalendarService().getAssignmentToApplyHolidays(timesheetDocument, TKUtils.getTimelessDate(endDate));
151                     if (holidayAssign != null) {
152                         BigDecimal holidayCalcHours = TkServiceLocator.getHolidayCalendarService().calculateHolidayHours(holidayAssign.getJob(), holiday.getHolidayHours());
153                         TimeBlock timeBlock = TkServiceLocator.getTimeBlockService().createTimeBlock(timesheetDocument, new Timestamp(holiday.getHolidayDate().getTime()),
154                                 new Timestamp(holiday.getHolidayDate().getTime()), holidayAssign, TkConstants.HOLIDAY_EARN_CODE, holidayCalcHours, BigDecimal.ZERO, false, false);
155                         timesheetDocument.getTimeBlocks().add(timeBlock);
156                     }
157                 }
158 
159                 //If holidays are loaded will need to save them to the database
160                 if (!lstHolidays.isEmpty()) {
161                     TkServiceLocator.getTimeBlockService().saveTimeBlocks(new LinkedList<TimeBlock>(), timesheetDocument.getTimeBlocks());
162                 }
163             }
164         }
165 
166     }
167 
168     protected TimesheetDocument initiateWorkflowDocument(String principalId, Date payBeginDate, Date payEndDate, String documentType, String title) throws WorkflowException {
169         TimesheetDocument timesheetDocument = null;
170         WorkflowDocument workflowDocument = null;
171 
172         workflowDocument = WorkflowDocumentFactory.createDocument(principalId, documentType, title);
173 
174         String status = workflowDocument.getStatus().getCode();
175         TimesheetDocumentHeader documentHeader = new TimesheetDocumentHeader(workflowDocument.getDocumentId(), principalId, payBeginDate, payEndDate, status);
176 
177         documentHeader.setDocumentId(workflowDocument.getDocumentId().toString());
178         documentHeader.setDocumentStatus("I");
179 
180         TkServiceLocator.getTimesheetDocumentHeaderService().saveOrUpdate(documentHeader);
181         timesheetDocument = new TimesheetDocument(documentHeader);
182 
183         TkServiceLocator.getTkSearchableAttributeService().updateSearchableAttribute(timesheetDocument, payEndDate);
184 
185         return timesheetDocument;
186     }
187 
188     public List<TimeBlock> getPrevDocumentTimeBlocks(String principalId, Date payBeginDate) {
189         TimesheetDocumentHeader prevTdh = TkServiceLocator.getTimesheetDocumentHeaderService().getPreviousDocumentHeader(principalId, payBeginDate);
190         if (prevTdh == null) {
191             return new ArrayList<TimeBlock>();
192         }
193         return TkServiceLocator.getTimeBlockService().getTimeBlocks(prevTdh.getDocumentId());
194     }
195 
196     @Override
197     public TimesheetDocument getTimesheetDocument(String documentId) {
198         TimesheetDocument timesheetDocument = null;
199         TimesheetDocumentHeader tdh = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(documentId);
200 
201         if (tdh != null) {
202             timesheetDocument = new TimesheetDocument(tdh);
203             CalendarEntries pce = TkServiceLocator.getCalendarService().getCalendarDatesByPayEndDate(tdh.getPrincipalId(), tdh.getPayEndDate(), null);
204             loadTimesheetDocumentData(timesheetDocument, tdh.getPrincipalId(), pce);
205 
206             timesheetDocument.setPayCalendarEntry(pce);
207         } else {
208             throw new RuntimeException("Could not find TimesheetDocumentHeader for DocumentID: " + documentId);
209         }
210         return timesheetDocument;
211     }
212 
213     protected void loadTimesheetDocumentData(TimesheetDocument tdoc, String principalId, CalendarEntries payCalEntry) {
214         List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignmentsByPayEntry(principalId, payCalEntry);
215         List<Job> jobs = TkServiceLocator.getJobService().getJobs(principalId, TKUtils.getTimelessDate(payCalEntry.getEndPeriodDate()));
216         List<TimeBlock> timeBlocks = TkServiceLocator.getTimeBlockService().getTimeBlocks(tdoc.getDocumentHeader().getDocumentId());
217 
218         tdoc.setAssignments(assignments);
219         tdoc.setJobs(jobs);
220         tdoc.setTimeBlocks(timeBlocks);
221     }
222 
223     public boolean isSynchronousUser() {
224         List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignments(TKUser.getCurrentTargetPerson().getPrincipalId(), TKUtils.getCurrentDate());
225         boolean isSynchronousUser = true;
226         for (Assignment assignment : assignments) {
227             isSynchronousUser &= assignment.isSynchronous();
228         }
229         return isSynchronousUser;
230     }
231 
232     //this is an admin function used for testing
233     public void deleteTimesheet(String documentId) {
234         TkServiceLocator.getTimeBlockService().deleteTimeBlocksAssociatedWithDocumentId(documentId);
235         TkServiceLocator.getTimesheetDocumentHeaderService().deleteTimesheetHeader(documentId);
236     }
237 
238     public TimeBlock resetWorkedHours(TimeBlock timeBlock) {
239         if (timeBlock.getBeginTime() != null && timeBlock.getEndTime() != null && StringUtils.equals(timeBlock.getEarnCodeType(), TkConstants.EARN_CODE_TIME)) {
240             BigDecimal hours = TKUtils.getHoursBetween(timeBlock.getBeginTime().getTime(), timeBlock.getEndTime().getTime());
241             timeBlock.setHours(hours);
242         }
243         return timeBlock;
244     }
245 
246     @Override
247     public void resetTimeBlock(List<TimeBlock> timeBlocks) {
248         for (TimeBlock tb : timeBlocks) {
249             resetWorkedHours(tb);
250         }
251         TkServiceLocator.getTimeBlockService().resetTimeHourDetail(timeBlocks);
252     }
253 
254 }