1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.hr.time.timesummary.service;
17
18 import org.apache.commons.collections.CollectionUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.joda.time.DateTime;
21 import org.joda.time.DateTimeFieldType;
22 import org.joda.time.LocalDateTime;
23 import org.kuali.hr.job.Job;
24 import org.kuali.hr.lm.LMConstants;
25 import org.kuali.hr.lm.leaveSummary.LeaveSummary;
26 import org.kuali.hr.lm.leaveSummary.LeaveSummaryRow;
27 import org.kuali.hr.lm.leaveblock.LeaveBlock;
28 import org.kuali.hr.lm.util.LeaveBlockAggregate;
29 import org.kuali.hr.time.assignment.Assignment;
30 import org.kuali.hr.time.assignment.AssignmentDescriptionKey;
31 import org.kuali.hr.time.calendar.Calendar;
32 import org.kuali.hr.time.calendar.CalendarEntries;
33 import org.kuali.hr.time.earncode.EarnCode;
34 import org.kuali.hr.time.earncodegroup.EarnCodeGroup;
35 import org.kuali.hr.time.flsa.FlsaDay;
36 import org.kuali.hr.time.flsa.FlsaWeek;
37 import org.kuali.hr.time.service.base.TkServiceLocator;
38 import org.kuali.hr.time.timeblock.TimeBlock;
39 import org.kuali.hr.time.timeblock.TimeHourDetail;
40 import org.kuali.hr.time.timesheet.TimesheetDocument;
41 import org.kuali.hr.time.timesummary.AssignmentRow;
42 import org.kuali.hr.time.timesummary.EarnCodeSection;
43 import org.kuali.hr.time.timesummary.EarnGroupSection;
44 import org.kuali.hr.time.timesummary.TimeSummary;
45 import org.kuali.hr.time.util.TKUtils;
46 import org.kuali.hr.time.util.TkConstants;
47 import org.kuali.hr.time.util.TkTimeBlockAggregate;
48 import org.kuali.hr.time.workarea.WorkArea;
49
50 import java.math.BigDecimal;
51 import java.sql.Timestamp;
52 import java.util.*;
53
54 public class TimeSummaryServiceImpl implements TimeSummaryService {
55 private static final String OTHER_EARN_GROUP = "Other";
56
57 @Override
58 public TimeSummary getTimeSummary(TimesheetDocument timesheetDocument) {
59 TimeSummary timeSummary = new TimeSummary();
60
61 if(timesheetDocument.getTimeBlocks() == null) {
62 return timeSummary;
63 }
64
65 List<Boolean> dayArrangements = new ArrayList<Boolean>();
66
67 timeSummary.setSummaryHeader(getHeaderForSummary(timesheetDocument.getCalendarEntry(), dayArrangements));
68 TkTimeBlockAggregate tkTimeBlockAggregate = new TkTimeBlockAggregate(timesheetDocument.getTimeBlocks(), timesheetDocument.getCalendarEntry(), TkServiceLocator.getCalendarService().getCalendar(timesheetDocument.getCalendarEntry().getHrCalendarId()), true);
69
70 List<Assignment> timeAssignments = timesheetDocument.getAssignments();
71 List<String> tAssignmentKeys = new ArrayList<String>();
72 for(Assignment assign : timeAssignments) {
73 tAssignmentKeys.add(assign.getAssignmentKey());
74 }
75 List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForTimeCalendar(timesheetDocument.getPrincipalId(),
76 timesheetDocument.getCalendarEntry().getBeginPeriodDate(), timesheetDocument.getCalendarEntry().getEndPeriodDate(), tAssignmentKeys);
77 LeaveBlockAggregate leaveBlockAggregate = new LeaveBlockAggregate(leaveBlocks, timesheetDocument.getCalendarEntry());
78 tkTimeBlockAggregate = combineTimeAndLeaveAggregates(tkTimeBlockAggregate, leaveBlockAggregate);
79
80 timeSummary.setWorkedHours(getWorkedHours(tkTimeBlockAggregate, leaveBlockAggregate));
81
82 List<EarnGroupSection> earnGroupSections = getEarnGroupSections(tkTimeBlockAggregate, timeSummary.getSummaryHeader().size()+1,
83 dayArrangements, timesheetDocument.getAsOfDate(), timesheetDocument.getDocEndDate());
84 timeSummary.setSections(earnGroupSections);
85
86 try {
87 List<LeaveSummaryRow> maxedLeaveRows = getMaxedLeaveRows(timesheetDocument.getCalendarEntry(),timesheetDocument.getPrincipalId());
88 timeSummary.setMaxedLeaveRows(maxedLeaveRows);
89 } catch (Exception e) {
90
91 e.printStackTrace();
92 }
93
94 return timeSummary;
95 }
96
97 private List<LeaveSummaryRow> getMaxedLeaveRows(
98 CalendarEntries calendarEntry, String principalId) throws Exception {
99 List<LeaveSummaryRow> maxedLeaveRows = new ArrayList<LeaveSummaryRow>();
100 if (TkServiceLocator.getLeaveApprovalService().isActiveAssignmentFoundOnJobFlsaStatus(principalId, TkConstants.FLSA_STATUS_NON_EXEMPT, true)) {
101 Map<String,ArrayList<String>> eligibilities = TkServiceLocator.getBalanceTransferService().getEligibleTransfers(calendarEntry,principalId);
102 Map<String,ArrayList<String>> payouts = TkServiceLocator.getLeavePayoutService().getEligiblePayouts(calendarEntry, principalId);
103 List<String> onDemandTransfers = eligibilities.get(LMConstants.MAX_BAL_ACTION_FREQ.ON_DEMAND);
104 onDemandTransfers.addAll(payouts.get(LMConstants.MAX_BAL_ACTION_FREQ.ON_DEMAND));
105 if(!onDemandTransfers.isEmpty()) {
106 LeaveSummary summary = TkServiceLocator.getLeaveSummaryService().getLeaveSummary(principalId, calendarEntry);
107 for(LeaveSummaryRow row : summary.getLeaveSummaryRows()) {
108 if(onDemandTransfers.contains(row.getAccrualCategoryRuleId()))
109 maxedLeaveRows.add(row);
110
111 }
112 }
113 }
114 return maxedLeaveRows;
115 }
116
117
118
119
120
121
122
123
124
125 public List<EarnGroupSection> getEarnGroupSections(TkTimeBlockAggregate tkTimeBlockAggregate, int numEntries, List<Boolean> dayArrangements, Date asOfDate , Date docEndDate){
126 List<EarnGroupSection> earnGroupSections = new ArrayList<EarnGroupSection>();
127 List<FlsaWeek> flsaWeeks = tkTimeBlockAggregate.getFlsaWeeks(TkServiceLocator.getTimezoneService().getUserTimezoneWithFallback());
128 Map<String, EarnCodeSection> earnCodeToEarnCodeSection = new HashMap<String, EarnCodeSection>();
129 Map<String, EarnGroupSection> earnGroupToEarnGroupSection = new HashMap<String, EarnGroupSection>();
130
131 int dayCount = 0;
132
133
134
135 List<FlsaWeek> trimmedFlsaWeeks = new ArrayList<FlsaWeek>();
136 for(FlsaWeek flsaWeek : flsaWeeks){
137 if(flsaWeek.getFlsaDays().size() > 0){
138 trimmedFlsaWeeks.add(flsaWeek);
139 }
140 }
141
142
143
144 for(FlsaWeek flsaWeek : trimmedFlsaWeeks){
145 int weekSize = 0;
146 List<FlsaDay> flsaDays = flsaWeek.getFlsaDays();
147 for(FlsaDay flsaDay : flsaDays){
148 Map<String, List<TimeBlock>> earnCodeToTimeBlocks = flsaDay.getEarnCodeToTimeBlocks();
149
150 for(String earnCode : earnCodeToTimeBlocks.keySet()){
151 for(TimeBlock timeBlock : earnCodeToTimeBlocks.get(earnCode)){
152 for(TimeHourDetail thd : timeBlock.getTimeHourDetails()){
153 if(StringUtils.equals(TkConstants.LUNCH_EARN_CODE, thd.getEarnCode())){
154 continue;
155 }
156 EarnCodeSection earnCodeSection = earnCodeToEarnCodeSection.get(thd.getEarnCode());
157 if(earnCodeSection == null){
158 earnCodeSection = new EarnCodeSection();
159 earnCodeSection.setEarnCode(thd.getEarnCode());
160 EarnCode earnCodeObj = TkServiceLocator.getEarnCodeService().getEarnCode(thd.getEarnCode(), TKUtils.getTimelessDate(asOfDate));
161 earnCodeSection.setDescription(earnCodeObj.getDescription());
162 earnCodeSection.setIsAmountEarnCode((earnCodeObj.getRecordMethod()!= null && earnCodeObj.getRecordMethod().equalsIgnoreCase(TkConstants.EARN_CODE_AMOUNT)) ? true : false);
163 for(int i = 0;i<(numEntries-1);i++){
164 earnCodeSection.getTotals().add(BigDecimal.ZERO);
165 }
166
167 earnCodeToEarnCodeSection.put(thd.getEarnCode(), earnCodeSection);
168 }
169 String assignKey = timeBlock.getAssignmentKey();
170 AssignmentRow assignRow = earnCodeSection.getAssignKeyToAssignmentRowMap().get(assignKey);
171 if(assignRow == null){
172 assignRow = new AssignmentRow();
173 assignRow.setAssignmentKey(assignKey);
174 AssignmentDescriptionKey assignmentKey = TkServiceLocator.getAssignmentService().getAssignmentDescriptionKey(assignKey);
175 Assignment assignment = TkServiceLocator.getAssignmentService().getAssignment(timeBlock.getPrincipalId(), assignmentKey, TKUtils.getTimelessDate(asOfDate));
176
177 if(assignment == null) {
178 assignment = TkServiceLocator.getAssignmentService().getAssignment(timeBlock.getPrincipalId(), assignmentKey, TKUtils.getTimelessDate(docEndDate));
179 }
180
181 if(assignment != null){
182 if(assignment.getJob() == null){
183 Job aJob = TkServiceLocator.getJobService().getJob(assignment.getPrincipalId(),assignment.getJobNumber(),TKUtils.getTimelessDate(assignment.getEffectiveDate()));
184 assignment.setJob(aJob);
185 }
186 if(assignment.getWorkAreaObj() == null){
187 WorkArea aWorkArea = TkServiceLocator.getWorkAreaService().getWorkArea(assignment.getWorkArea(), TKUtils.getTimelessDate(assignment.getEffectiveDate()));
188 assignment.setWorkAreaObj(aWorkArea);
189 }
190 assignRow.setDescr(assignment.getAssignmentDescription());
191 }
192 for(int i = 0;i<(numEntries-1);i++){
193 assignRow.getTotal().add(BigDecimal.ZERO);
194 assignRow.getAmount().add(BigDecimal.ZERO);
195 }
196 assignRow.setEarnCodeSection(earnCodeSection);
197 earnCodeSection.addAssignmentRow(assignRow);
198 }
199 assignRow.addToTotal(dayCount, thd.getHours());
200 assignRow.addToAmount(dayCount, thd.getAmount());
201 }
202 }
203 }
204 dayCount++;
205 weekSize++;
206 }
207
208 for(EarnCodeSection earnCodeSection : earnCodeToEarnCodeSection.values()){
209 earnCodeSection.addWeeklyTotal(dayCount, weekSize);
210 }
211 weekSize = 0;
212
213 dayCount++;
214 }
215
216 dayCount = 0;
217
218 for(EarnCodeSection earnCodeSection : earnCodeToEarnCodeSection.values()){
219 String earnCode = earnCodeSection.getEarnCode();
220 EarnCodeGroup earnGroupObj = TkServiceLocator.getEarnCodeGroupService().getEarnCodeGroupSummaryForEarnCode(earnCode, TKUtils.getTimelessDate(asOfDate));
221 String earnGroup = null;
222 if(earnGroupObj == null){
223 earnGroup = OTHER_EARN_GROUP;
224 } else{
225 earnGroup = earnGroupObj.getDescr();
226 }
227
228 EarnGroupSection earnGroupSection = earnGroupToEarnGroupSection.get(earnGroup);
229 if(earnGroupSection == null){
230 earnGroupSection = new EarnGroupSection();
231 earnGroupSection.setEarnGroup(earnGroup);
232 for(int i =0;i<(numEntries-1);i++){
233 earnGroupSection.getTotals().add(BigDecimal.ZERO);
234 }
235 earnGroupToEarnGroupSection.put(earnGroup, earnGroupSection);
236 }
237 earnGroupSection.addEarnCodeSection(earnCodeSection, dayArrangements);
238
239 }
240 for(EarnGroupSection earnGroupSection : earnGroupToEarnGroupSection.values()){
241 earnGroupSections.add(earnGroupSection);
242 }
243 return earnGroupSections;
244 }
245
246
247
248
249
250
251 protected List<String> getSummaryHeader(CalendarEntries payCalEntry){
252 List<String> summaryHeader = new ArrayList<String>();
253 int dayCount = 0;
254 Date beginDateTime = payCalEntry.getBeginPeriodDateTime();
255 Date endDateTime = payCalEntry.getEndPeriodDateTime();
256 boolean virtualDays = false;
257 LocalDateTime endDate = payCalEntry.getEndLocalDateTime();
258
259 if (endDate.get(DateTimeFieldType.hourOfDay()) != 0 || endDate.get(DateTimeFieldType.minuteOfHour()) != 0 ||
260 endDate.get(DateTimeFieldType.secondOfMinute()) != 0){
261 virtualDays = true;
262 }
263
264 Date currDateTime = beginDateTime;
265 java.util.Calendar cal = GregorianCalendar.getInstance();
266
267 while(currDateTime.before(endDateTime)){
268 LocalDateTime currDate = new LocalDateTime(currDateTime);
269 summaryHeader.add(makeHeaderDiplayString(currDate, virtualDays));
270
271 dayCount++;
272 if((dayCount % 7) == 0){
273 summaryHeader.add("Week "+ ((dayCount / 7)));
274 }
275 cal.setTime(currDateTime);
276 cal.add(java.util.Calendar.HOUR, 24);
277 currDateTime = cal.getTime();
278 }
279
280 summaryHeader.add("Period Total");
281 return summaryHeader;
282 }
283
284
285 private TkTimeBlockAggregate combineTimeAndLeaveAggregates(TkTimeBlockAggregate tbAggregate, LeaveBlockAggregate lbAggregate) {
286 if (tbAggregate != null
287 && lbAggregate != null
288 && tbAggregate.getDayTimeBlockList().size() == lbAggregate.getDayLeaveBlockList().size()) {
289 for (int i = 0; i < tbAggregate.getDayTimeBlockList().size(); i++) {
290 List<LeaveBlock> leaveBlocks = lbAggregate.getDayLeaveBlockList().get(i);
291 if (CollectionUtils.isNotEmpty(leaveBlocks)) {
292 for (LeaveBlock lb : leaveBlocks) {
293
294
295 TimeBlock timeBlock = new TimeBlock();
296 timeBlock.setHours(lb.getLeaveAmount().negate());
297 timeBlock.setBeginTimestamp(new Timestamp(lb.getLeaveDate().getTime()));
298 timeBlock.setEndTimestamp(new Timestamp(new DateTime(lb.getLeaveDate()).plusMinutes(timeBlock.getHours().intValue()).getMillis()));
299 timeBlock.setAssignmentKey(lb.getAssignmentKey());
300 timeBlock.setEarnCode(lb.getEarnCode());
301 timeBlock.setPrincipalId(lb.getPrincipalId());
302 timeBlock.setWorkArea(lb.getWorkArea());
303 TimeHourDetail timeHourDetail = new TimeHourDetail();
304 timeHourDetail.setEarnCode(timeBlock.getEarnCode());
305 timeHourDetail.setHours(timeBlock.getHours());
306 timeHourDetail.setAmount(BigDecimal.ZERO);
307 timeBlock.addTimeHourDetail(timeHourDetail);
308 tbAggregate.getDayTimeBlockList().get(i).add(timeBlock);
309 }
310 }
311
312 }
313 }
314 return tbAggregate;
315 }
316
317
318
319
320
321
322
323
324
325
326
327
328 private List<BigDecimal> getWorkedHours(TkTimeBlockAggregate aggregate, LeaveBlockAggregate lbAggregate) {
329 List<BigDecimal> hours = new ArrayList<BigDecimal>();
330 BigDecimal periodTotal = TkConstants.BIG_DECIMAL_SCALED_ZERO;
331 for (FlsaWeek week : aggregate.getFlsaWeeks(TkServiceLocator.getTimezoneService().getUserTimezoneWithFallback())) {
332 BigDecimal weeklyTotal = TkConstants.BIG_DECIMAL_SCALED_ZERO;
333 for (FlsaDay day : week.getFlsaDays()) {
334 BigDecimal totalForDay = TkConstants.BIG_DECIMAL_SCALED_ZERO;
335 for (TimeBlock block : day.getAppliedTimeBlocks()) {
336 totalForDay = totalForDay.add(block.getHours(), TkConstants.MATH_CONTEXT);
337 weeklyTotal = weeklyTotal.add(block.getHours(), TkConstants.MATH_CONTEXT);
338 periodTotal = periodTotal.add(block.getHours(), TkConstants.MATH_CONTEXT);
339 }
340 hours.add(totalForDay);
341 }
342 hours.add(weeklyTotal);
343 }
344 hours.add(periodTotal);
345
346 return hours;
347 }
348
349
350
351
352
353
354
355
356
357
358
359 @Override
360 public List<String> getHeaderForSummary(CalendarEntries cal, List<Boolean> dayArrangements) {
361 List<String> header = new ArrayList<String>();
362
363
364 int flsaBeginDay = this.getPayCalendarForEntry(cal).getFlsaBeginDayConstant();
365 boolean virtualDays = false;
366 LocalDateTime startDate = cal.getBeginLocalDateTime();
367 LocalDateTime endDate = cal.getEndLocalDateTime();
368
369
370
371
372 if (endDate.get(DateTimeFieldType.hourOfDay()) != 0 || endDate.get(DateTimeFieldType.minuteOfHour()) != 0 ||
373 endDate.get(DateTimeFieldType.secondOfMinute()) != 0)
374 {
375 endDate = endDate.plusDays(1);
376 virtualDays = true;
377 }
378
379 boolean afterFirstDay = false;
380 int week = 1;
381 for (LocalDateTime currentDate = startDate; currentDate.compareTo(endDate) < 0; currentDate = currentDate.plusDays(1)) {
382
383 if (currentDate.getDayOfWeek() == flsaBeginDay && afterFirstDay) {
384 header.add("Week " + week);
385 dayArrangements.add(false);
386 week++;
387 }
388
389 header.add(makeHeaderDiplayString(currentDate, virtualDays));
390 dayArrangements.add(true);
391
392
393 afterFirstDay = true;
394 }
395
396
397
398
399 if (!header.get(header.size()-1).startsWith("Week")) {
400 dayArrangements.add(false);
401 header.add("Week " + week);
402 }
403
404
405 header.add("Period Total");
406 dayArrangements.add(false);
407 return header;
408 }
409
410
411
412
413
414
415
416 private String makeHeaderDiplayString(LocalDateTime currentDate, boolean virtualDays) {
417 StringBuilder display = new StringBuilder();
418
419 display.append(currentDate.toString("E"));
420 if (virtualDays) {
421 LocalDateTime nextDate = currentDate.plusDays(1);
422 display.append(" - ");
423 display.append(nextDate.toString("E"));
424 }
425
426 display.append("<br />");
427
428 display.append(currentDate.toString(TkConstants.DT_ABBREV_DATE_FORMAT));
429 if (virtualDays) {
430 LocalDateTime nextDate = currentDate.plusDays(1);
431 display.append(" - ");
432 display.append(nextDate.toString(TkConstants.DT_ABBREV_DATE_FORMAT));
433 }
434
435 return display.toString();
436 }
437
438
439
440
441
442 private Calendar getPayCalendarForEntry(CalendarEntries calEntry) {
443 Calendar cal = null;
444
445 if (calEntry != null) {
446 cal = TkServiceLocator.getCalendarService().getCalendar(calEntry.getHrCalendarId());
447 }
448
449 return cal;
450 }
451
452 }