001    /**
002     * Copyright 2004-2013 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.util;
017    
018    import java.math.BigDecimal;
019    import java.sql.Time;
020    import java.sql.Timestamp;
021    import java.util.ArrayList;
022    import java.util.Collections;
023    import java.util.Comparator;
024    import java.util.List;
025    import java.util.ListIterator;
026    
027    import org.apache.commons.collections.CollectionUtils;
028    import org.joda.time.DateTime;
029    import org.joda.time.DateTimeZone;
030    import org.joda.time.Interval;
031    import org.joda.time.LocalDateTime;
032    import org.joda.time.LocalTime;
033    import org.kuali.hr.lm.leaveblock.LeaveBlock;
034    import org.kuali.hr.lm.util.LeaveBlockAggregate;
035    import org.kuali.hr.time.assignment.Assignment;
036    import org.kuali.hr.time.calendar.Calendar;
037    import org.kuali.hr.time.calendar.CalendarEntries;
038    import org.kuali.hr.time.flsa.FlsaDay;
039    import org.kuali.hr.time.flsa.FlsaWeek;
040    import org.kuali.hr.time.service.base.TkServiceLocator;
041    import org.kuali.hr.time.timeblock.TimeBlock;
042    import org.kuali.hr.time.timeblock.TimeHourDetail;
043    import org.kuali.hr.time.timesheet.TimesheetDocument;
044    import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
045    
046    public class TkTimeBlockAggregate {
047            private List<List<TimeBlock>> dayTimeBlockList = new ArrayList<List<TimeBlock>>();
048            private List<List<LeaveBlock>> dayLeaveBlockList = new ArrayList<List<LeaveBlock>>();
049            private CalendarEntries payCalendarEntry;
050            private Calendar payCalendar;
051    
052        /**
053         * Defaults to using SYSTEM time zone.
054         *
055         * @param timeBlocks
056         * @param payCalendarEntry
057         */
058            public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, CalendarEntries payCalendarEntry){
059                    this(timeBlocks, payCalendarEntry, TkServiceLocator.getCalendarService().getCalendar(payCalendarEntry.getHrCalendarId()));
060            }
061    
062        /**
063         * Defaults to using SYSTEM time zone.
064         *
065         * @param timeBlocks
066         * @param payCalendarEntry
067         * @param payCalendar
068         */
069            public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, CalendarEntries payCalendarEntry, Calendar payCalendar) {
070            this(timeBlocks, payCalendarEntry, payCalendar, false);
071        }
072    
073        /**
074         * Provides the option to refer to the time zone adjusted time for the current
075         * user.
076         * @param timeBlocks
077         * @param payCalendarEntry
078         * @param payCalendar
079         * @param useUserTimeZone
080         */
081        public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, CalendarEntries payCalendarEntry, Calendar payCalendar, boolean useUserTimeZone) {
082            this(timeBlocks, payCalendarEntry, payCalendar, useUserTimeZone, 
083                            useUserTimeZone ? TKUtils.getDaySpanForCalendarEntry(payCalendarEntry) : TKUtils.getDaySpanForCalendarEntry(payCalendarEntry, TKUtils.getSystemDateTimeZone()));
084            }
085    
086        public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, CalendarEntries payCalendarEntry, Calendar payCalendar, boolean useUserTimeZone, List<Interval> dayIntervals) {
087            this.payCalendarEntry = payCalendarEntry;
088                    this.payCalendar = payCalendar;
089                    
090                    for(Interval dayInt : dayIntervals){
091                            List<TimeBlock> dayTimeBlocks = new ArrayList<TimeBlock>();
092                            for(TimeBlock timeBlock : timeBlocks){
093    
094                    // Assumption: Timezones can only be switched at pay period end boundaries.
095                    // If the above assumption becomes false, the logic below will need to
096                    // accommodate virtual chopping of time blocks to have them fit nicely
097                    // in the "days" that are displayed to users.
098    
099                                    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                for (int i = 0; i < tbAggregate.getDayTimeBlockList().size(); i++) {
463                    List<LeaveBlock> leaveBlocks = lbAggregate.getDayLeaveBlockList().get(i);
464                    if (CollectionUtils.isNotEmpty(leaveBlocks)) {
465                        for (LeaveBlock lb : leaveBlocks) {
466                            //convert leave block to generic time block and add to list
467                            //conveniently, we only really need the hours amount
468                            TimeBlock timeBlock = new TimeBlock();
469                            timeBlock.setHours(lb.getLeaveAmount().negate());
470                            timeBlock.setBeginTimestamp(new Timestamp(lb.getLeaveDate().getTime()));
471                            timeBlock.setEndTimestamp(new Timestamp(new DateTime(lb.getLeaveDate()).plusMinutes(timeBlock.getHours().intValue()).getMillis()));
472                            timeBlock.setAssignmentKey(lb.getAssignmentKey());
473                            timeBlock.setEarnCode(lb.getEarnCode());
474                            timeBlock.setPrincipalId(lb.getPrincipalId());
475                            timeBlock.setWorkArea(lb.getWorkArea());
476                            TimeHourDetail timeHourDetail = new TimeHourDetail();
477                            timeHourDetail.setEarnCode(timeBlock.getEarnCode());
478                            timeHourDetail.setHours(timeBlock.getHours());
479                            timeHourDetail.setAmount(BigDecimal.ZERO);
480                            timeBlock.addTimeHourDetail(timeHourDetail);
481                            tbAggregate.getDayTimeBlockList().get(i).add(timeBlock);
482                        }
483                    }
484    
485                }
486            }
487            return tbAggregate;
488        }
489    
490    }