View Javadoc

1   /**
2    * Copyright 2004-2013 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.util;
17  
18  import java.math.BigDecimal;
19  import java.sql.Time;
20  import java.sql.Timestamp;
21  import java.util.ArrayList;
22  import java.util.Collections;
23  import java.util.Comparator;
24  import java.util.List;
25  import java.util.ListIterator;
26  
27  import org.apache.commons.collections.CollectionUtils;
28  import org.joda.time.DateTime;
29  import org.joda.time.DateTimeZone;
30  import org.joda.time.Interval;
31  import org.joda.time.LocalDateTime;
32  import org.joda.time.LocalTime;
33  import org.kuali.hr.lm.leaveblock.LeaveBlock;
34  import org.kuali.hr.lm.util.LeaveBlockAggregate;
35  import org.kuali.hr.time.assignment.Assignment;
36  import org.kuali.hr.time.calendar.Calendar;
37  import org.kuali.hr.time.calendar.CalendarEntries;
38  import org.kuali.hr.time.flsa.FlsaDay;
39  import org.kuali.hr.time.flsa.FlsaWeek;
40  import org.kuali.hr.time.service.base.TkServiceLocator;
41  import org.kuali.hr.time.timeblock.TimeBlock;
42  import org.kuali.hr.time.timeblock.TimeHourDetail;
43  import org.kuali.hr.time.timesheet.TimesheetDocument;
44  import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
45  
46  public class TkTimeBlockAggregate {
47  	private List<List<TimeBlock>> dayTimeBlockList = new ArrayList<List<TimeBlock>>();
48  	private List<List<LeaveBlock>> dayLeaveBlockList = new ArrayList<List<LeaveBlock>>();
49  	private CalendarEntries payCalendarEntry;
50  	private Calendar payCalendar;
51  
52      /**
53       * Defaults to using SYSTEM time zone.
54       *
55       * @param timeBlocks
56       * @param payCalendarEntry
57       */
58  	public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, CalendarEntries payCalendarEntry){
59  		this(timeBlocks, payCalendarEntry, TkServiceLocator.getCalendarService().getCalendar(payCalendarEntry.getHrCalendarId()));
60  	}
61  
62      /**
63       * Defaults to using SYSTEM time zone.
64       *
65       * @param timeBlocks
66       * @param payCalendarEntry
67       * @param payCalendar
68       */
69  	public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, CalendarEntries payCalendarEntry, Calendar payCalendar) {
70          this(timeBlocks, payCalendarEntry, payCalendar, false);
71      }
72  
73      /**
74       * Provides the option to refer to the time zone adjusted time for the current
75       * user.
76       * @param timeBlocks
77       * @param payCalendarEntry
78       * @param payCalendar
79       * @param useUserTimeZone
80       */
81      public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, CalendarEntries payCalendarEntry, Calendar payCalendar, boolean useUserTimeZone) {
82          this(timeBlocks, payCalendarEntry, payCalendar, useUserTimeZone, 
83          		useUserTimeZone ? TKUtils.getDaySpanForCalendarEntry(payCalendarEntry) : TKUtils.getDaySpanForCalendarEntry(payCalendarEntry, TKUtils.getSystemDateTimeZone()));
84  	}
85  
86      public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, CalendarEntries payCalendarEntry, Calendar payCalendar, boolean useUserTimeZone, List<Interval> dayIntervals) {
87      	this.payCalendarEntry = payCalendarEntry;
88  		this.payCalendar = payCalendar;
89  		
90  		for(Interval dayInt : dayIntervals){
91  			List<TimeBlock> dayTimeBlocks = new ArrayList<TimeBlock>();
92  			for(TimeBlock timeBlock : timeBlocks){
93  
94                  // Assumption: Timezones can only be switched at pay period end boundaries.
95                  // If the above assumption becomes false, the logic below will need to
96                  // accommodate virtual chopping of time blocks to have them fit nicely
97                  // in the "days" that are displayed to users.
98  
99  				DateTime beginTime = useUserTimeZone ? timeBlock.getBeginTimeDisplay() : new DateTime(timeBlock.getBeginTimestamp(), TKUtils.getSystemDateTimeZone());
100 				DateTime endTime = useUserTimeZone ? timeBlock.getEndTimeDisplay() :  new DateTime(timeBlock.getEndTimestamp(), TKUtils.getSystemDateTimeZone());
101 				if(dayInt.contains(beginTime)){
102 					if(dayInt.contains(endTime) || endTime.compareTo(dayInt.getEnd()) == 0){
103 						// determine if the time block needs to be pushed forward / backward
104 						if(beginTime.getHourOfDay() < dayInt.getStart().getHourOfDay()) {
105 							timeBlock.setPushBackward(true);
106 						}
107 
108 						dayTimeBlocks.add(timeBlock);
109 					}
110 				}
111 			}
112 			dayTimeBlockList.add(dayTimeBlocks);
113 		}
114 		
115     }
116     
117     /**
118      * Defaults to using SYSTEM time zone.
119      *
120      * @param timeBlocks
121      * @param leaveBlocks
122      * @param payCalendarEntry
123      */
124 	public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, List<LeaveBlock> leaveBlocks, CalendarEntries payCalendarEntry){
125 		this(timeBlocks, leaveBlocks, payCalendarEntry, TkServiceLocator.getCalendarService().getCalendar(payCalendarEntry.getHrCalendarId()));
126 	}
127 
128     /**
129      * Defaults to using SYSTEM time zone.
130      *
131      * @param timeBlocks
132      * @param leaveBlocks
133      * @param payCalendarEntry
134      * @param payCalendar
135      */
136 	public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, List<LeaveBlock> leaveBlocks, CalendarEntries payCalendarEntry, Calendar payCalendar) {
137         this(timeBlocks, leaveBlocks, payCalendarEntry, payCalendar, false);
138     }
139 
140     /**
141      * Provides the option to refer to the time zone adjusted time for the current
142      * user.
143      * @param timeBlocks
144      * @param payCalendarEntry
145      * @param payCalendar
146      * @param useUserTimeZone
147      */
148     public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, List<LeaveBlock> leaveBlocks, CalendarEntries payCalendarEntry, Calendar payCalendar, boolean useUserTimeZone) {
149         this(timeBlocks, leaveBlocks, payCalendarEntry, payCalendar, useUserTimeZone, 
150         		useUserTimeZone ? TKUtils.getDaySpanForCalendarEntry(payCalendarEntry) : TKUtils.getDaySpanForCalendarEntry(payCalendarEntry, TKUtils.getSystemDateTimeZone()));
151 	}
152 
153     public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, List<LeaveBlock> leaveBlocks, CalendarEntries payCalendarEntry, Calendar payCalendar, boolean useUserTimeZone, List<Interval> dayIntervals) {
154     	this.payCalendarEntry = payCalendarEntry;
155 		this.payCalendar = payCalendar;
156 		
157 		for(Interval dayInt : dayIntervals){
158 			List<TimeBlock> dayTimeBlocks = new ArrayList<TimeBlock>();
159 			for(TimeBlock timeBlock : timeBlocks){
160 
161                 // Assumption: Timezones can only be switched at pay period end boundaries.
162                 // If the above assumption becomes false, the logic below will need to
163                 // accommodate virtual chopping of time blocks to have them fit nicely
164                 // in the "days" that are displayed to users.
165 
166 				DateTime beginTime = useUserTimeZone ? timeBlock.getBeginTimeDisplay() : new DateTime(timeBlock.getBeginTimestamp(), TKUtils.getSystemDateTimeZone());
167 				DateTime endTime = useUserTimeZone ? timeBlock.getEndTimeDisplay() :  new DateTime(timeBlock.getEndTimestamp(), TKUtils.getSystemDateTimeZone());
168 				if(dayInt.contains(beginTime)){
169 					if(dayInt.contains(endTime) || endTime.compareTo(dayInt.getEnd()) == 0){
170 						// determine if the time block needs to be pushed forward / backward
171 						if(beginTime.getHourOfDay() < dayInt.getStart().getHourOfDay()) {
172 							timeBlock.setPushBackward(true);
173 						}
174 
175 						dayTimeBlocks.add(timeBlock);
176 					}
177 				}
178 			}
179 			dayTimeBlockList.add(dayTimeBlocks);
180 			
181 			List<LeaveBlock> dayLeaveBlocks = new ArrayList<LeaveBlock>();
182 			for(LeaveBlock leaveBlock : leaveBlocks){
183 
184                 // Assumption: Timezones can only be switched at pay period end boundaries.
185                 // If the above assumption becomes false, the logic below will need to
186                 // accommodate virtual chopping of leave blocks to have them fit nicely
187                 // in the "days" that are displayed to users.
188 				
189 				DateTimeZone dateTimeZone = TkServiceLocator.getTimezoneService().getUserTimezoneWithFallback();
190 				DateTime beginTime = new DateTime(leaveBlock.getLeaveDate(), useUserTimeZone ? dateTimeZone : TKUtils.getSystemDateTimeZone());
191 				DateTime endTime = new DateTime(leaveBlock.getLeaveDate(), useUserTimeZone ? dateTimeZone : TKUtils.getSystemDateTimeZone());
192 				if(dayInt.contains(beginTime)){
193 					if(dayInt.contains(endTime) || endTime.compareTo(dayInt.getEnd()) == 0){
194 						dayLeaveBlocks.add(leaveBlock);
195 					}
196 				}
197 			}
198 			dayLeaveBlockList.add(dayLeaveBlocks);
199 		}
200     }
201     
202 	public List<TimeBlock> getFlattenedTimeBlockList(){
203 		List<TimeBlock> lstTimeBlocks = new ArrayList<TimeBlock>();
204 		for(List<TimeBlock> timeBlocks : dayTimeBlockList){
205 			lstTimeBlocks.addAll(timeBlocks);
206 		}
207 
208 		Collections.sort(lstTimeBlocks, new Comparator<TimeBlock>() { // Sort the Time Blocks
209 			public int compare(TimeBlock tb1, TimeBlock tb2) {
210 				if (tb1 != null && tb2 != null)
211 					return tb1.getBeginTimestamp().compareTo(tb2.getBeginTimestamp());
212 				return 0;
213 			}
214 		});
215 
216 		return lstTimeBlocks;
217 	}
218 	
219 	public List<LeaveBlock> getFlattenedLeaveBlockList(){
220 		List<LeaveBlock> lstLeaveBlocks = new ArrayList<LeaveBlock>();
221 		for(List<LeaveBlock> leaveBlocks : dayLeaveBlockList){
222 			lstLeaveBlocks.addAll(leaveBlocks);
223 		}
224 
225 		Collections.sort(lstLeaveBlocks, new Comparator<LeaveBlock>() { // Sort the Leave Blocks
226 			public int compare(LeaveBlock lb1, LeaveBlock lb2) {
227 				if (lb1 != null && lb2 != null)
228 					return lb1.getLeaveDate().compareTo(lb2.getLeaveDate());
229 				return 0;
230 			}
231 		});
232 
233 		return lstLeaveBlocks;
234 	}
235 
236 	/**
237 	 * Provides a way to access all of the time blocks for a given week.
238 	 *
239 	 * Outer list is 0 indexed list representing days in a week.
240 	 * Inner List are all of the time blocks for that day.
241 	 *
242 	 * Ex.
243 	 *
244 	 * List<List<TimeBlock>> week0 = getWeekTimeBlocks(0);
245 	 * List<TimeBlock> day0 = week0.get(0);
246 	 *
247 	 * @param week
248 	 * @return
249 	 */
250 	public List<List<TimeBlock>> getWeekTimeBlocks(int week){
251 		int startIndex = week*7;
252 		int endIndex = (week*7)+7;
253 		endIndex = endIndex > dayTimeBlockList.size() ? dayTimeBlockList.size() : endIndex;
254 
255         // Need to sort each day by clock time.
256         List<List<TimeBlock>> wList = dayTimeBlockList.subList(startIndex, endIndex);
257         for (List<TimeBlock> dList : wList) {
258             Collections.sort(dList, new Comparator<TimeBlock>() { // Sort the Time Blocks
259                 public int compare(TimeBlock tb1, TimeBlock tb2) {
260                     if (tb1 != null && tb2 != null)
261                         return tb1.getBeginTimestamp().compareTo(tb2.getBeginTimestamp());
262                     return 0;
263                 }
264             });
265         }
266 
267 		return wList;
268 	}
269 	
270 	/**
271 	 * Provides a way to access all of the leave blocks for a given week.
272 	 *
273 	 * Outer list is 0 indexed list representing days in a week.
274 	 * Inner List are all of the leave blocks for that day.
275 	 *
276 	 * Ex.
277 	 *
278 	 * List<List<LeaveBlock>> week0 = getWeekLeaveBlocks(0);
279 	 * List<LeaveBlock> day0 = week0.get(0);
280 	 *
281 	 * @param week
282 	 * @return
283 	 */
284 	public List<List<LeaveBlock>> getWeekLeaveBlocks(int week){
285 		int startIndex = week*7;
286 		int endIndex = (week*7)+7;
287 		endIndex = endIndex > dayLeaveBlockList.size() ? dayLeaveBlockList.size() : endIndex;
288 
289         // Need to sort each day by clock time.
290         List<List<LeaveBlock>> wList = dayLeaveBlockList.subList(startIndex, endIndex);
291         for (List<LeaveBlock> dList : wList) {
292             Collections.sort(dList, new Comparator<LeaveBlock>() { // Sort the Leave Blocks
293                 public int compare(LeaveBlock lb1, LeaveBlock lb2) {
294                     if (lb1 != null && lb2 != null)
295                         return lb1.getLeaveDate().compareTo(lb2.getLeaveDate());
296                     return 0;
297                 }
298             });
299         }
300 
301 		return wList;
302 	}
303 
304 	/**
305 	 * When consuming these weeks, you must be aware that you could be on a
306 	 * virtual day, ie noon to noon schedule and have your FLSA time start
307 	 * before the virtual day start,
308 	 * but still have a full 7 days for your week.
309      *
310      * @param zone The TimeZone to use when constructing this relative sorting.
311 	 */
312 	public List<FlsaWeek> getFlsaWeeks(DateTimeZone zone){
313 		int flsaDayConstant = payCalendar.getFlsaBeginDayConstant();
314 		Time flsaBeginTime  = payCalendar.getFlsaBeginTime();
315 
316 		// We can use these to build our interval, we have to make sure we
317 		// place them on the proper day when we construct it.
318 		LocalTime flsaBeginLocalTime = LocalTime.fromDateFields(flsaBeginTime);
319 
320 		// Defines both the start date and the start virtual time.
321 		// We will add 1 day to this to move over all days.
322 		//
323 		// FLSA time is set.  This is an FLSA start date.
324         LocalDateTime startLDT = payCalendarEntry.getBeginLocalDateTime();
325 //		DateTime startDate = new DateTime(payCalendarEntry.getBeginPeriodDateTime());
326 //		startDate = startDate.toLocalDate().toDateTime(flsaBeginLocalTime,TKUtils.getSystemDateTimeZone());
327 
328 		List<FlsaWeek> flsaWeeks = new ArrayList<FlsaWeek>();
329 		List<TimeBlock> flattenedTimeBlocks = getFlattenedTimeBlockList();
330 		List<LeaveBlock> flattenedLeaveBlocks = getFlattenedLeaveBlockList();
331 		FlsaWeek currentWeek = new FlsaWeek(flsaDayConstant, flsaBeginLocalTime, LocalTime.fromDateFields(payCalendarEntry.getBeginPeriodDateTime()));
332 		FlsaDay flsaDay = new FlsaDay(startLDT, flattenedTimeBlocks, flattenedLeaveBlocks, zone);
333 		currentWeek.addFlsaDay(flsaDay);
334 		flsaWeeks.add(currentWeek);
335 
336 		for (int i = 1; i < dayTimeBlockList.size(); i++) {
337 			LocalDateTime currentDate = startLDT.plusDays(i);
338 			flsaDay = new FlsaDay(currentDate, flattenedTimeBlocks, flattenedLeaveBlocks, zone);
339 
340 			if (currentDate.getDayOfWeek() == flsaDayConstant) {
341 				currentWeek = new FlsaWeek(flsaDayConstant, flsaBeginLocalTime, flsaBeginLocalTime);
342 				flsaWeeks.add(currentWeek);	
343 			}
344 			
345 			currentWeek.addFlsaDay(flsaDay);
346 		}
347 
348 		return flsaWeeks;
349 	}
350 	
351 	public List<List<FlsaWeek>> getFlsaWeeks(DateTimeZone zone, String principalId) {
352 		List<List<FlsaWeek>> flsaWeeks = new ArrayList<List<FlsaWeek>>();
353 		
354 		List<FlsaWeek> currentWeeks = getFlsaWeeks(zone);
355 		
356 		for (ListIterator<FlsaWeek> weekIterator = currentWeeks.listIterator(); weekIterator.hasNext(); ) {
357 			List<FlsaWeek> flsaWeek = new ArrayList<FlsaWeek>();
358 			
359 			int index = weekIterator.nextIndex();
360 			FlsaWeek currentWeek = weekIterator.next();
361 			
362 			if (index == 0 && !currentWeek.isFirstWeekFull()) {
363 				CalendarEntries previousCalendarEntry = TkServiceLocator.getCalendarEntriesService().getPreviousCalendarEntriesByCalendarId(payCalendar.getHrCalendarId(), payCalendarEntry);
364 				if (previousCalendarEntry != null) {
365 					TimesheetDocumentHeader timesheetDocumentHeader = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(principalId, previousCalendarEntry.getBeginPeriodDateTime(), previousCalendarEntry.getEndPeriodDateTime());
366 					if (timesheetDocumentHeader != null) { 
367 		                TimesheetDocument timesheetDocument = TkServiceLocator.getTimesheetService().getTimesheetDocument(timesheetDocumentHeader.getDocumentId());
368 		                List<String> assignmentKeys = new ArrayList<String>();
369 		                for(Assignment assignment : timesheetDocument.getAssignments()) {
370 		                	assignmentKeys.add(assignment.getAssignmentKey());
371 		                }
372 		                
373 						List<TimeBlock> timeBlocks = TkServiceLocator.getTimeBlockService().getTimeBlocks(timesheetDocumentHeader.getDocumentId());
374 						List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForTimeCalendar(principalId, previousCalendarEntry.getBeginPeriodDateTime(), previousCalendarEntry.getEndPeriodDateTime(), assignmentKeys);
375 						if (CollectionUtils.isNotEmpty(timeBlocks)) {
376 							TkTimeBlockAggregate previousAggregate = new TkTimeBlockAggregate(timeBlocks, leaveBlocks, previousCalendarEntry, payCalendar, true);
377 							List<FlsaWeek> previousWeek = previousAggregate.getFlsaWeeks(zone);
378 							if (CollectionUtils.isNotEmpty(previousWeek)) {
379 								flsaWeek.add(previousWeek.get(previousWeek.size() - 1));
380 							}
381 						}
382 					 }
383 				}
384 			}
385 			
386 			flsaWeek.add(currentWeek);
387 			
388 			if (index == currentWeeks.size() - 1 && !currentWeek.isLastWeekFull()) {
389 				CalendarEntries nextCalendarEntry = TkServiceLocator.getCalendarEntriesService().getNextCalendarEntriesByCalendarId(payCalendar.getHrCalendarId(), payCalendarEntry);
390 				if (nextCalendarEntry != null) {
391 					TimesheetDocumentHeader timesheetDocumentHeader = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(principalId, nextCalendarEntry.getBeginPeriodDateTime(), nextCalendarEntry.getEndPeriodDateTime());
392 					if (timesheetDocumentHeader != null) {
393 		                TimesheetDocument timesheetDocument = TkServiceLocator.getTimesheetService().getTimesheetDocument(timesheetDocumentHeader.getDocumentId());
394 		                List<String> assignmentKeys = new ArrayList<String>();
395 		                for(Assignment assignment : timesheetDocument.getAssignments()) {
396 		                	assignmentKeys.add(assignment.getAssignmentKey());
397 		                }
398 		                
399 						List<TimeBlock> timeBlocks = TkServiceLocator.getTimeBlockService().getTimeBlocks(timesheetDocumentHeader.getDocumentId());
400 						List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForTimeCalendar(principalId, nextCalendarEntry.getBeginPeriodDateTime(), nextCalendarEntry.getEndPeriodDateTime(), assignmentKeys);
401 						if (CollectionUtils.isNotEmpty(timeBlocks)) {
402 							TkTimeBlockAggregate nextAggregate = new TkTimeBlockAggregate(timeBlocks, leaveBlocks, nextCalendarEntry, payCalendar, true);
403 							List<FlsaWeek> nextWeek = nextAggregate.getFlsaWeeks(zone);
404 							if (CollectionUtils.isNotEmpty(nextWeek)) {
405 								flsaWeek.add(nextWeek.get(0));
406 							}
407 						}
408 					 }
409 				}
410 			}
411 			
412 			flsaWeeks.add(flsaWeek);
413 		}
414 		
415 		return flsaWeeks;
416 	}
417 
418 	/**
419 	 * @return the total number of weeks that this object represents.
420 	 */
421 	public int numberOfAggregatedWeeks() {
422 		int weeks = 0;
423 
424 		if (this.dayTimeBlockList.size() > 0) {
425 			weeks = this.dayTimeBlockList.size() / 7;
426 			if (this.dayTimeBlockList.size() % 7 > 0)
427 				weeks++;
428 		}
429 
430 		return weeks;
431 	}
432 
433 	public List<List<TimeBlock>> getDayTimeBlockList() {
434 		return dayTimeBlockList;
435 	}
436 	
437 	public List<List<LeaveBlock>> getDayLeaveBlockList() {
438 		return dayLeaveBlockList;
439 	}
440 
441 	public CalendarEntries getPayCalendarEntry() {
442 		return payCalendarEntry;
443 	}
444 
445 	public void setPayCalendarEntry(CalendarEntries payCalendarEntry) {
446 		this.payCalendarEntry = payCalendarEntry;
447 	}
448 
449 	public Calendar getPayCalendar() {
450 		return payCalendar;
451 	}
452 
453 	public void setPayCalendar(Calendar payCalendar) {
454 		this.payCalendar = payCalendar;
455 	}
456 
457     //Very much a hack to add valid leave blocks to a time block aggregate...
458     public static TkTimeBlockAggregate combineTimeAndLeaveAggregates(TkTimeBlockAggregate tbAggregate, LeaveBlockAggregate lbAggregate) {
459         if (tbAggregate != null
460                 && lbAggregate != null
461                 && tbAggregate.getDayTimeBlockList().size() == lbAggregate.getDayLeaveBlockList().size()) {
462             DateTimeZone dtz = TkServiceLocator.getTimezoneService().getUserTimezoneWithFallback();
463             for (int i = 0; i < tbAggregate.getDayTimeBlockList().size(); i++) {
464                 List<LeaveBlock> leaveBlocks = lbAggregate.getDayLeaveBlockList().get(i);
465                 if (CollectionUtils.isNotEmpty(leaveBlocks)) {
466                     for (LeaveBlock lb : leaveBlocks) {
467                         //convert leave block to generic time block and add to list
468                         //conveniently, we only really need the hours amount
469                         TimeBlock timeBlock = new TimeBlock();
470                         timeBlock.setHours(lb.getLeaveAmount().negate());
471                         //DateTime beginTime = new DateTime(lb.getLeaveDate().getTime());
472                         //beginTime = beginTime.
473                         DateTime beginTime = new DateTime(lb.getLeaveDate()).toLocalDate().toDateTimeAtStartOfDay().withZoneRetainFields(dtz);
474                         timeBlock.setBeginTimestamp(new Timestamp(beginTime.getMillis()));
475                         timeBlock.setEndTimestamp(new Timestamp(beginTime.plusMinutes(timeBlock.getHours().intValue()).getMillis()));
476                         timeBlock.setAssignmentKey(lb.getAssignmentKey());
477                         timeBlock.setEarnCode(lb.getEarnCode());
478                         timeBlock.setPrincipalId(lb.getPrincipalId());
479                         timeBlock.setWorkArea(lb.getWorkArea());
480                         TimeHourDetail timeHourDetail = new TimeHourDetail();
481                         timeHourDetail.setEarnCode(timeBlock.getEarnCode());
482                         timeHourDetail.setHours(timeBlock.getHours());
483                         timeHourDetail.setAmount(BigDecimal.ZERO);
484                         timeBlock.addTimeHourDetail(timeHourDetail);
485                         tbAggregate.getDayTimeBlockList().get(i).add(timeBlock);
486                     }
487                 }
488 
489             }
490         }
491         return tbAggregate;
492     }
493 
494 }