1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  package org.kuali.hr.time.util;
17  
18  import java.sql.Time;
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.Comparator;
22  import java.util.List;
23  import java.util.ListIterator;
24  
25  import org.apache.commons.collections.CollectionUtils;
26  import org.joda.time.DateTime;
27  import org.joda.time.DateTimeZone;
28  import org.joda.time.Interval;
29  import org.joda.time.LocalDateTime;
30  import org.joda.time.LocalTime;
31  import org.kuali.hr.time.calendar.Calendar;
32  import org.kuali.hr.time.calendar.CalendarEntries;
33  import org.kuali.hr.time.flsa.FlsaDay;
34  import org.kuali.hr.time.flsa.FlsaWeek;
35  import org.kuali.hr.time.service.base.TkServiceLocator;
36  import org.kuali.hr.time.timeblock.TimeBlock;
37  import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
38  
39  public class TkTimeBlockAggregate {
40  	public List<List<TimeBlock>> dayTimeBlockList = new ArrayList<List<TimeBlock>>();
41  	private CalendarEntries payCalendarEntry;
42  	private Calendar payCalendar;
43  
44      
45  
46  
47  
48  
49  
50  	public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, CalendarEntries payCalendarEntry){
51  		this(timeBlocks, payCalendarEntry, TkServiceLocator.getCalendarService().getCalendar(payCalendarEntry.getHrCalendarId()));
52  	}
53  
54      
55  
56  
57  
58  
59  
60  
61  	public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, CalendarEntries payCalendarEntry, Calendar payCalendar) {
62          this(timeBlocks, payCalendarEntry, payCalendar, false);
63      }
64  
65      
66  
67  
68  
69  
70  
71  
72  
73      public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, CalendarEntries payCalendarEntry, Calendar payCalendar, boolean useUserTimeZone) {
74  		this.payCalendarEntry = payCalendarEntry;
75  		this.payCalendar = payCalendar;
76  
77  		List<Interval> dayIntervals = TKUtils.getDaySpanForCalendarEntry(payCalendarEntry);
78  		for(Interval dayInt : dayIntervals){
79  			List<TimeBlock> dayTimeBlocks = new ArrayList<TimeBlock>();
80  			for(TimeBlock timeBlock : timeBlocks){
81  
82                  
83                  
84                  
85                  
86  
87  				DateTime beginTime = useUserTimeZone ? timeBlock.getBeginTimeDisplay() : new DateTime(timeBlock.getBeginTimestamp(), TKUtils.getSystemDateTimeZone());
88  				DateTime endTime = useUserTimeZone ? timeBlock.getEndTimeDisplay() :  new DateTime(timeBlock.getEndTimestamp(), TKUtils.getSystemDateTimeZone());
89  				if(dayInt.contains(beginTime)){
90  					if(dayInt.contains(endTime) || endTime.compareTo(dayInt.getEnd()) == 0){
91  						
92  						if(beginTime.getHourOfDay() < dayInt.getStart().getHourOfDay()) {
93  							timeBlock.setPushBackward(true);
94  						}
95  
96  						dayTimeBlocks.add(timeBlock);
97  					}
98  				}
99  			}
100 			dayTimeBlockList.add(dayTimeBlocks);
101 		}
102 	}
103 
104     public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, CalendarEntries payCalendarEntry, Calendar payCalendar, boolean useUserTimeZone, List<Interval> dayIntervals) {
105     	this.payCalendarEntry = payCalendarEntry;
106 		this.payCalendar = payCalendar;
107 		
108 		for(Interval dayInt : dayIntervals){
109 			List<TimeBlock> dayTimeBlocks = new ArrayList<TimeBlock>();
110 			for(TimeBlock timeBlock : timeBlocks){
111 
112                 
113                 
114                 
115                 
116 
117 				DateTime beginTime = useUserTimeZone ? timeBlock.getBeginTimeDisplay() : new DateTime(timeBlock.getBeginTimestamp(), TKUtils.getSystemDateTimeZone());
118 				DateTime endTime = useUserTimeZone ? timeBlock.getEndTimeDisplay() :  new DateTime(timeBlock.getEndTimestamp(), TKUtils.getSystemDateTimeZone());
119 				if(dayInt.contains(beginTime)){
120 					if(dayInt.contains(endTime) || endTime.compareTo(dayInt.getEnd()) == 0){
121 						
122 						if(beginTime.getHourOfDay() < dayInt.getStart().getHourOfDay()) {
123 							timeBlock.setPushBackward(true);
124 						}
125 
126 						dayTimeBlocks.add(timeBlock);
127 					}
128 				}
129 			}
130 			dayTimeBlockList.add(dayTimeBlocks);
131 		}
132 		
133     }
134     
135     
136 	public List<TimeBlock> getFlattenedTimeBlockList(){
137 		List<TimeBlock> lstTimeBlocks = new ArrayList<TimeBlock>();
138 		for(List<TimeBlock> timeBlocks : dayTimeBlockList){
139 			lstTimeBlocks.addAll(timeBlocks);
140 		}
141 
142 		Collections.sort(lstTimeBlocks, new Comparator<TimeBlock>() { 
143 			public int compare(TimeBlock tb1, TimeBlock tb2) {
144 				if (tb1 != null && tb2 != null)
145 					return tb1.getBeginTimestamp().compareTo(tb2.getBeginTimestamp());
146 				return 0;
147 			}
148 		});
149 
150 		return lstTimeBlocks;
151 	}
152 
153 	
154 
155 
156 
157 
158 
159 
160 
161 
162 
163 
164 
165 
166 
167 	public List<List<TimeBlock>> getWeekTimeBlocks(int week){
168 		int startIndex = week*7;
169 		int endIndex = (week*7)+7;
170 		endIndex = endIndex > dayTimeBlockList.size() ? dayTimeBlockList.size() : endIndex;
171 
172         
173         List<List<TimeBlock>> wList = dayTimeBlockList.subList(startIndex, endIndex);
174         for (List<TimeBlock> dList : wList) {
175             Collections.sort(dList, new Comparator<TimeBlock>() { 
176                 public int compare(TimeBlock tb1, TimeBlock tb2) {
177                     if (tb1 != null && tb2 != null)
178                         return tb1.getBeginTimestamp().compareTo(tb2.getBeginTimestamp());
179                     return 0;
180                 }
181             });
182         }
183 
184 		return wList;
185 	}
186 
187 	
188 
189 
190 
191 
192 
193 
194 
195 	public List<FlsaWeek> getFlsaWeeks(DateTimeZone zone){
196 		int flsaDayConstant = payCalendar.getFlsaBeginDayConstant();
197 		Time flsaBeginTime  = payCalendar.getFlsaBeginTime();
198 
199 		
200 		
201 		LocalTime flsaBeginLocalTime = LocalTime.fromDateFields(flsaBeginTime);
202 
203 		
204 		
205 		
206 		
207         LocalDateTime startLDT = payCalendarEntry.getBeginLocalDateTime();
208 
209 
210 
211 		List<FlsaWeek> flsaWeeks = new ArrayList<FlsaWeek>();
212 		List<TimeBlock> flatSortedBlockList = getFlattenedTimeBlockList();
213 		FlsaWeek currentWeek = new FlsaWeek(flsaDayConstant, flsaBeginLocalTime, LocalTime.fromDateFields(payCalendarEntry.getBeginPeriodDateTime()));
214 		FlsaDay flsaDay = new FlsaDay(startLDT, flatSortedBlockList, zone);
215 		currentWeek.addFlsaDay(flsaDay);
216 		flsaWeeks.add(currentWeek);
217 
218 		for (int i = 1; i < dayTimeBlockList.size(); i++) {
219 			LocalDateTime currentDate = startLDT.plusDays(i);
220 			flsaDay = new FlsaDay(currentDate, flatSortedBlockList, zone);
221 
222 			if (currentDate.getDayOfWeek() == flsaDayConstant) {
223 				currentWeek = new FlsaWeek(flsaDayConstant, flsaBeginLocalTime, flsaBeginLocalTime);
224 				flsaWeeks.add(currentWeek);	
225 			}
226 			
227 			currentWeek.addFlsaDay(flsaDay);
228 		}
229 
230 		return flsaWeeks;
231 	}
232 	
233 	public List<List<FlsaWeek>> getFlsaWeeks(DateTimeZone zone, String principalId) {
234 		List<List<FlsaWeek>> flsaWeeks = new ArrayList<List<FlsaWeek>>();
235 		
236 		List<FlsaWeek> currentWeeks = getFlsaWeeks(zone);
237 		
238 		for (ListIterator<FlsaWeek> weekIterator = currentWeeks.listIterator(); weekIterator.hasNext(); ) {
239 			List<FlsaWeek> flsaWeek = new ArrayList<FlsaWeek>();
240 			
241 			int index = weekIterator.nextIndex();
242 			FlsaWeek currentWeek = weekIterator.next();
243 			
244 			if (index == 0 && !currentWeek.isFirstWeekFull()) {
245 				CalendarEntries previousCalendarEntry = TkServiceLocator.getCalendarEntriesService().getPreviousCalendarEntriesByCalendarId(payCalendar.getHrCalendarId(), payCalendarEntry);
246 				if (previousCalendarEntry != null) {
247 					TimesheetDocumentHeader timesheetDocumentHeader = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(principalId, previousCalendarEntry.getBeginPeriodDateTime(), previousCalendarEntry.getEndPeriodDateTime());
248 					if (timesheetDocumentHeader != null) { 
249 						List<TimeBlock> timeBlocks = TkServiceLocator.getTimeBlockService().getTimeBlocks(timesheetDocumentHeader.getDocumentId());
250 						if (CollectionUtils.isNotEmpty(timeBlocks)) {
251 							TkTimeBlockAggregate previousAggregate = new TkTimeBlockAggregate(timeBlocks, previousCalendarEntry, payCalendar, true);
252 							List<FlsaWeek> previousWeek = previousAggregate.getFlsaWeeks(zone);
253 							if (CollectionUtils.isNotEmpty(previousWeek)) {
254 								flsaWeek.add(previousWeek.get(previousWeek.size() - 1));
255 							}
256 						}
257 					 }
258 				}
259 			}
260 			
261 			flsaWeek.add(currentWeek);
262 			
263 			if (index == currentWeeks.size() - 1 && !currentWeek.isLastWeekFull()) {
264 				CalendarEntries nextCalendarEntry = TkServiceLocator.getCalendarEntriesService().getNextCalendarEntriesByCalendarId(payCalendar.getHrCalendarId(), payCalendarEntry);
265 				if (nextCalendarEntry != null) {
266 					TimesheetDocumentHeader timesheetDocumentHeader = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(principalId, nextCalendarEntry.getBeginPeriodDateTime(), nextCalendarEntry.getEndPeriodDateTime());
267 					if (timesheetDocumentHeader != null) { 
268 						List<TimeBlock> timeBlocks = TkServiceLocator.getTimeBlockService().getTimeBlocks(timesheetDocumentHeader.getDocumentId());
269 						if (CollectionUtils.isNotEmpty(timeBlocks)) {
270 							TkTimeBlockAggregate nextAggregate = new TkTimeBlockAggregate(timeBlocks, nextCalendarEntry, payCalendar, true);
271 							List<FlsaWeek> nextWeek = nextAggregate.getFlsaWeeks(zone);
272 							if (CollectionUtils.isNotEmpty(nextWeek)) {
273 								flsaWeek.add(nextWeek.get(0));
274 							}
275 						}
276 					 }
277 				}
278 			}
279 			
280 			flsaWeeks.add(flsaWeek);
281 		}
282 		
283 		return flsaWeeks;
284 	}
285 
286 	
287 
288 
289 	public int numberOfAggregatedWeeks() {
290 		int weeks = 0;
291 
292 		if (this.dayTimeBlockList.size() > 0) {
293 			weeks = this.dayTimeBlockList.size() / 7;
294 			if (this.dayTimeBlockList.size() % 7 > 0)
295 				weeks++;
296 		}
297 
298 		return weeks;
299 	}
300 
301 	public List<List<TimeBlock>> getDayTimeBlockList() {
302 		return dayTimeBlockList;
303 	}
304 
305 	public CalendarEntries getPayCalendarEntry() {
306 		return payCalendarEntry;
307 	}
308 
309 	public void setPayCalendarEntry(CalendarEntries payCalendarEntry) {
310 		this.payCalendarEntry = payCalendarEntry;
311 	}
312 
313 	public Calendar getPayCalendar() {
314 		return payCalendar;
315 	}
316 
317 	public void setPayCalendar(Calendar payCalendar) {
318 		this.payCalendar = payCalendar;
319 	}
320 
321 }