001/** 002 * Copyright 2004-2014 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 */ 016package org.kuali.kpme.tklm.time.calendar; 017 018import org.apache.log4j.Logger; 019import org.joda.time.DateTime; 020import org.kuali.kpme.core.api.calendar.entry.CalendarEntry; 021import org.kuali.kpme.core.api.earncode.EarnCode; 022import org.kuali.kpme.core.calendar.CalendarParent; 023import org.kuali.kpme.core.calendar.web.CalendarDay; 024import org.kuali.kpme.core.calendar.web.CalendarWeek; 025import org.kuali.kpme.core.service.HrServiceLocator; 026import org.kuali.kpme.core.util.HrConstants; 027import org.kuali.kpme.tklm.api.leave.block.LeaveBlock; 028import org.kuali.kpme.tklm.api.time.calendar.TkCalendarContract; 029import org.kuali.kpme.tklm.api.time.timeblock.TimeBlock; 030import org.kuali.kpme.tklm.leave.block.LeaveBlockAggregate; 031import org.kuali.kpme.tklm.leave.block.LeaveBlockRenderer; 032import org.kuali.kpme.tklm.time.timeblock.TimeBlockBo; 033import org.kuali.kpme.tklm.time.timeblock.web.TimeBlockRenderer; 034import org.kuali.kpme.tklm.time.timehourdetail.TimeHourDetailRenderer; 035import org.kuali.kpme.tklm.time.util.TkTimeBlockAggregate; 036 037import java.util.ArrayList; 038import java.util.List; 039import java.util.Map; 040 041public class TkCalendar extends CalendarParent implements TkCalendarContract { 042 043 private static final long serialVersionUID = -5393478597803080619L; 044 private static final Logger LOG = Logger.getLogger(TkCalendar.class); 045 private CalendarEntry payCalEntry; 046 private DateTime beginDateTime; 047 private DateTime endDateTime; 048 049 public TkCalendar() {} 050 051 public TkCalendar(CalendarEntry calendarEntry) { 052 super(calendarEntry); 053 } 054 055 public static TkCalendar getCalendar(TkTimeBlockAggregate tbAggregate, LeaveBlockAggregate lbAggregate) { 056 TkCalendar tc = new TkCalendar(); 057 058 if (tbAggregate != null && lbAggregate != null) { 059 if(tbAggregate.getDayTimeBlockList().size() != lbAggregate.getDayLeaveBlockList().size()){ 060 LOG.error("TimeBlockAggregate and LeaveBlockAggregate should have the same size of Day Blocks List"); 061 return null; 062// throw new RuntimeException("TimeBlockAggregate and LeaveBlockAggregate should have the same size of Day Blocks List"); 063 } 064 065 List<CalendarWeek> weeks = new ArrayList<CalendarWeek>(); 066 tc.setPayCalEntry(tbAggregate.getPayCalendarEntry()); 067 068 int firstDay = 0; 069 if (tc.getBeginDateTime().getDayOfWeek() != 7) { 070 firstDay = 0 - tc.getBeginDateTime().getDayOfWeek(); // always render calendar weeks from Sundays 071 } 072 for (int i = 0; i < tbAggregate.numberOfAggregatedWeeks(); i++) { 073 TkCalendarWeek week = new TkCalendarWeek(); 074 List<List<TimeBlock>> weekBlocks = tbAggregate.getWeekTimeBlocks(i); 075 List<List<LeaveBlock>> weekLeaveBlocks = lbAggregate.getWeekLeaveBlocks(i); 076 List<CalendarDay> days = new ArrayList<CalendarDay>(7); 077 078 for (int j = 0; j < weekBlocks.size(); j++) { 079 List<TimeBlock> dayBlocks = weekBlocks.get(j); 080 List<LeaveBlock> dayLeaveBlocks = weekLeaveBlocks.get(j); 081 // Create the individual days. 082 TkCalendarDay day = new TkCalendarDay(); 083 084 //Set missed punch flag 085 int k=0; 086 for(TimeBlock tb : dayBlocks){ 087 TimeBlockBo timeBlockBo = TimeBlockBo.from(tb); 088 timeBlockBo.assignClockedByMissedPunch(); 089 tb = TimeBlockBo.to(timeBlockBo); 090 dayBlocks.set(k, tb); 091 k++; 092 } 093 094 day.setTimeblocks(dayBlocks); 095 day.setLeaveBlocks(dayLeaveBlocks); 096 day.setDayNumberString(tc.getDayNumberString(i * 7 + j + firstDay)); 097 day.setDayNumberDelta(i * 7 + j + firstDay); 098 day.setDateString(tc.getDateString(day.getDayNumberDelta())); 099 assignDayLunchLabel(day); 100 int dayIndex = i * 7 + j + firstDay; 101 DateTime beginDateTemp = tc.getBeginDateTime().plusDays(dayIndex); 102 day.setGray(false); 103 if (beginDateTemp.isBefore(tc.getBeginDateTime().getMillis()) 104 || beginDateTemp.isAfter(tc.getEndDateTime().getMillis())) { 105 day.setGray(true); 106 } 107 if (tc.getEndDateTime().getHourOfDay() == 0 && beginDateTemp.equals(tc.getEndDateTime())) { 108 day.setGray(true); 109 } 110 days.add(day); 111 } 112 week.setDays(days); 113 weeks.add(week); 114 } 115 tc.setWeeks(weeks); 116 } else { 117 return null; 118 } 119 120 return tc; 121 } 122 123 public static TkCalendar getCalendar(TkTimeBlockAggregate aggregate) { 124 TkCalendar tc = new TkCalendar(); 125 126 if (aggregate != null) { 127 List<CalendarWeek> weeks = new ArrayList<CalendarWeek>(); 128 tc.setPayCalEntry(aggregate.getPayCalendarEntry()); 129 130 int firstDay = 0; 131 if (tc.getBeginDateTime().getDayOfWeek() != 7) { 132 firstDay = 0 - tc.getBeginDateTime().getDayOfWeek(); // always render calendar weeks from Sundays 133 } 134 for (int i = 0; i < aggregate.numberOfAggregatedWeeks(); i++) { 135 TkCalendarWeek week = new TkCalendarWeek(); 136 List<List<TimeBlock>> weekBlocks = aggregate.getWeekTimeBlocks(i); 137 List<CalendarDay> days = new ArrayList<CalendarDay>(7); 138 139 for (int j = 0; j < weekBlocks.size(); j++) { 140 List<TimeBlock> dayBlocks = weekBlocks.get(j); 141 // Create the individual days. 142 TkCalendarDay day = new TkCalendarDay(); 143 144 day.setTimeblocks(dayBlocks); 145 day.setDayNumberString(tc.getDayNumberString(i * 7 + j + firstDay)); 146 day.setDayNumberDelta(i * 7 + j + firstDay); 147 day.setDateString(tc.getDateString(day.getDayNumberDelta())); 148 assignDayLunchLabel(day); 149 int dayIndex = i * 7 + j + firstDay; 150 DateTime beginDateTemp = tc.getBeginDateTime().plusDays(dayIndex); 151 day.setGray(false); 152 if (beginDateTemp.isBefore(tc.getBeginDateTime().getMillis()) 153 || beginDateTemp.isAfter(tc.getEndDateTime().getMillis())) { 154 day.setGray(true); 155 } 156 if (tc.getEndDateTime().getHourOfDay() == 0 && beginDateTemp.equals(tc.getEndDateTime())) { 157 day.setGray(true); 158 } 159 days.add(day); 160 } 161 week.setDays(days); 162 weeks.add(week); 163 } 164 tc.setWeeks(weeks); 165 } else { 166 return null; 167 } 168 169 return tc; 170 } 171 172 public static void assignDayLunchLabel(TkCalendarDay day) { 173 EarnCode ec = null; 174 String label = ""; 175 String id = ""; 176 for (TimeBlockRenderer tbr : day.getBlockRenderers()) { 177 for (TimeHourDetailRenderer thdr : tbr.getDetailRenderers()) { 178 if (thdr.getTitle().equals(HrConstants.LUNCH_EARN_CODE)) { 179 ec = HrServiceLocator.getEarnCodeService().getEarnCode(thdr.getTitle(), tbr.getTimeBlock().getBeginDateTime().toLocalDate()); 180 if (ec != null) { 181 label = ec.getDescription() + " : " + thdr.getHours() + " hours"; 182 id = thdr.getTkTimeHourDetailId(); 183 } 184 } 185 } 186 tbr.setLunchLabel(label); 187 tbr.setLunchLabelId(id); 188 189 label = ""; 190 } 191 } 192 193 194 public void assignAssignmentStyle(Map<String, String> styleMap) { 195 for (CalendarWeek aWeek : this.getWeeks()) { 196 for (CalendarDay aDay : aWeek.getDays()) { 197 for (TimeBlockRenderer tbr : ((TkCalendarDay)aDay).getBlockRenderers()) { 198 String assignmentKey = tbr.getTimeBlock().getAssignmentKey(); 199 if (assignmentKey != null && styleMap.containsKey(assignmentKey)) { 200 tbr.setAssignmentClass(styleMap.get(assignmentKey)); 201 } else { 202 tbr.setAssignmentClass(""); 203 } 204 } 205 for (LeaveBlockRenderer lbr : ((TkCalendarDay)aDay).getLeaveBlockRenderers()) { 206 String assignmentKey = lbr.getLeaveBlock().getAssignmentKey(); 207 if (assignmentKey != null && styleMap.containsKey(assignmentKey)) { 208 lbr.setAssignmentClass(styleMap.get(assignmentKey)); 209 } else { 210 lbr.setAssignmentClass(""); 211 } 212 } 213 214 } 215 } 216 } 217 218 public CalendarEntry getPayCalEntry() { 219 return payCalEntry; 220 } 221 222 public void setPayCalEntry(CalendarEntry payCalEntry) { 223 this.payCalEntry = payCalEntry; 224 // Relative time, with time zone added. 225 this.beginDateTime = payCalEntry.getBeginPeriodLocalDateTime().toDateTime(HrServiceLocator.getTimezoneService().getUserTimezoneWithFallback()); 226 this.endDateTime = payCalEntry.getEndPeriodLocalDateTime().toDateTime(HrServiceLocator.getTimezoneService().getUserTimezoneWithFallback()); 227 } 228 229 public DateTime getBeginDateTime() { 230 return beginDateTime; 231 } 232 233 public DateTime getEndDateTime() { 234 return endDateTime; 235 } 236 237 /** 238 * Provides the calendar title / heading. If the Pay Calendar entry spans 239 * multiple months, you get Abbreviated Month name + year of both the 240 * beginning month and the ending month. 241 * 242 * @return String for calendar title use. 243 */ 244 public String getCalendarTitle() { 245 StringBuilder sb = new StringBuilder(); 246 247 if (getBeginDateTime().getMonthOfYear() == getEndDateTime().getMonthOfYear() || 248 (getBeginDateTime().getMonthOfYear() != getEndDateTime().getMonthOfYear() 249 && getEndDateTime().getDayOfMonth() == 1 && getEndDateTime().getSecondOfDay() == 0)) { 250 sb.append(getBeginDateTime().toString("MMMM y")); 251 } else { 252 sb.append(getBeginDateTime().toString("MMM y")); 253 sb.append(" - "); 254 sb.append(getEndDateTime().toString("MMM y")); 255 } 256 257 return sb.toString(); 258 } 259 260 /** 261 * Assumption of 7 "days" per week, or 7 "blocks" per row. 262 * 263 * @return A list of string titles for each row block (day) 264 */ 265 public List<String> getCalendarDayHeadings() { 266 List<String> dayStrings = new ArrayList<String>(7); 267 // always render from Sunday 268 int firstDay = 0 - getBeginDateTime().getDayOfWeek(); 269 int lastDay = firstDay + 7; 270 271 if (getBeginDateTime().getMinuteOfDay() == 0) { 272 // "Standard" days. 273 for (int i = firstDay; i < lastDay; i++) { 274 DateTime currDay = getBeginDateTime().plusDays(i); 275 dayStrings.add(currDay.toString("E")); 276 } 277 } else { 278 // Day Split Strings 279 280 for (int i = firstDay; i < lastDay; i++) { 281 StringBuilder builder = new StringBuilder(""); 282 DateTime currStart = getBeginDateTime().plusDays(i); 283 DateTime currEnd = getBeginDateTime().plusDays(i); 284 285 builder.append(currStart.toString("E HH:mm")); 286 builder.append(" - "); 287 builder.append(currEnd.toString("E HH:mm")); 288 289 dayStrings.add(builder.toString()); 290 } 291 } 292 293 return dayStrings; 294 } 295 296 public String getCalenadrYear() { 297 return getBeginDateTime().toString("yyyy"); 298 } 299 300 public String getCalendarMonth() { 301 return getBeginDateTime().toString("M"); 302 } 303 304 private String getDayNumberString(int dayDelta) { 305 StringBuilder b = new StringBuilder(); 306 307 if (getBeginDateTime().getMinuteOfDay() == 0) { 308 DateTime currStart = getBeginDateTime().plusDays(dayDelta); 309 b.append(currStart.toString("d")); 310 } else { 311 DateTime currStart = getBeginDateTime().plusDays(dayDelta); 312 DateTime currEnd = getBeginDateTime().plusDays(dayDelta); 313 314 b.append(currStart.toString("d HH:mm")); 315 b.append(" - "); 316 //TODO: should this be currEnd??? 317 b.append(currStart.toString("d HH:mm")); 318 } 319 320 return b.toString(); 321 } 322 323 private String getDateString(int dayDelta) { 324 return getBeginDateTime().plusDays(dayDelta).toString("M/d/yyyy"); 325 } 326 327}