/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package net.rrm.ehour.timesheet.service; import com.google.common.collect.Lists; import net.rrm.ehour.config.EhourConfig; import net.rrm.ehour.data.DateRange; import net.rrm.ehour.domain.*; import net.rrm.ehour.exception.ObjectNotFoundException; import net.rrm.ehour.persistence.timesheet.dao.TimesheetCommentDao; import net.rrm.ehour.persistence.timesheet.dao.TimesheetDao; import net.rrm.ehour.project.service.ProjectAssignmentService; import net.rrm.ehour.report.reports.element.AssignmentAggregateReportElement; import net.rrm.ehour.report.service.AggregateReportService; import net.rrm.ehour.timesheet.dto.BookedDay; import net.rrm.ehour.timesheet.dto.TimesheetOverview; import net.rrm.ehour.timesheet.dto.UserProjectStatus; import net.rrm.ehour.timesheet.dto.WeekOverview; import net.rrm.ehour.util.DateUtil; import org.joda.time.Interval; import org.joda.time.LocalDate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import scala.collection.Seq; import java.util.*; /** * Provides services for displaying and manipulating timesheets. * Methods are organized by their functionality rather than technical impact. * * @author Thies */ @Service("timesheetService") public class TimesheetServiceImpl implements IOverviewTimesheet { private TimesheetDao timesheetDAO; private TimesheetCommentDao timesheetCommentDAO; private TimesheetLockService timesheetLockService; private AggregateReportService aggregateReportService; private ProjectAssignmentService projectAssignmentService; private EhourConfig configuration; @Autowired public TimesheetServiceImpl(TimesheetDao timesheetDAO, TimesheetCommentDao timesheetCommentDAO, TimesheetLockService timesheetLockService, AggregateReportService aggregateReportService, ProjectAssignmentService projectAssignmentService, EhourConfig configuration) { this.timesheetDAO = timesheetDAO; this.timesheetCommentDAO = timesheetCommentDAO; this.timesheetLockService = timesheetLockService; this.aggregateReportService = aggregateReportService; this.projectAssignmentService = projectAssignmentService; this.configuration = configuration; } /** * Fetch the timesheet overview for a user. This returns an object containing the project assignments for the * requested month and a list with all timesheet entries for that month. * * @param requestedMonth only the month and year of the calendar is used * @return TimesheetOverviewAction * @throws ObjectNotFoundException */ public TimesheetOverview getTimesheetOverview(User user, Calendar requestedMonth) { TimesheetOverview overview = new TimesheetOverview(); DateRange monthRange = DateUtil.calendarToMonthRange(requestedMonth); overview.setProjectStatus(getProjectStatus(user.getUserId(), monthRange)); List<TimesheetEntry> timesheetEntries = timesheetDAO.getTimesheetEntriesInRange(user.getUserId(), monthRange); Map<Integer, List<TimesheetEntry>> calendarMap = entriesToCalendarMap(timesheetEntries); overview.setTimesheetEntries(calendarMap); return overview; } /** * Get project status for user * * @param userId * @param monthRange * @return */ private SortedSet<UserProjectStatus> getProjectStatus(Integer userId, DateRange monthRange) { List<Integer> assignmentIds = Lists.newArrayList(); SortedSet<UserProjectStatus> userProjectStatus = new TreeSet<>(); Map<Integer, AssignmentAggregateReportElement> originalAggregates = new HashMap<>(); List<AssignmentAggregateReportElement> aggregates = aggregateReportService.getHoursPerAssignmentInRange(userId, monthRange); // only flex & fixed needed, others can already be added to the returned list for (AssignmentAggregateReportElement aggregate : aggregates) { if (aggregate.getProjectAssignment().getAssignmentType().isFixedAllottedType() || aggregate.getProjectAssignment().getAssignmentType().isFlexAllottedType()) { Integer assignmentId = aggregate.getProjectAssignment().getAssignmentId(); assignmentIds.add(assignmentId); originalAggregates.put(assignmentId, aggregate); } else { userProjectStatus.add(new UserProjectStatus(aggregate)); } } // fetch total hours for flex/fixed assignments if (!assignmentIds.isEmpty()) { List<AssignmentAggregateReportElement> timeAllottedAggregates = aggregateReportService.getHoursPerAssignment(assignmentIds); for (AssignmentAggregateReportElement aggregate : timeAllottedAggregates) { userProjectStatus.add(new UserProjectStatus(originalAggregates.get(aggregate.getProjectAssignment().getAssignmentId()), aggregate.getHours())); } } return userProjectStatus; } /** * Get a list with all day numbers in this month that has complete booked days (config defines the completion * level). *2 * @param userId * @param requestedMonth * @return List with Integers of complete booked days */ public List<LocalDate> getBookedDaysMonthOverview(Integer userId, Calendar requestedMonth) { DateRange monthRange = DateUtil.calendarToMonthRange(requestedMonth); List<BookedDay> bookedDays = timesheetDAO.getBookedHoursperDayInRange(userId, monthRange); List<LocalDate> fullyBookedDays = new ArrayList<>(); for (BookedDay bookedDay : bookedDays) { if (bookedDay.getHours() != null && bookedDay.getHours().floatValue() >= configuration.getCompleteDayHours()) { fullyBookedDays.add(new LocalDate(bookedDay.getDate())); } } Collections.sort(fullyBookedDays); return fullyBookedDays; } /** * Put the timesheet entries in a map where the day is the key and * the value is a list of timesheet entries filled out for that date * * @param timesheetEntries * @return */ private Map<Integer, List<TimesheetEntry>> entriesToCalendarMap(List<TimesheetEntry> timesheetEntries) { Map<Integer, List<TimesheetEntry>> calendarMap; Calendar cal; Integer dayKey; List<TimesheetEntry> dayEntries; calendarMap = new HashMap<>(); for (TimesheetEntry entry : timesheetEntries) { if (entry == null) { continue; } cal = new GregorianCalendar(); cal.setTime(entry.getEntryId().getEntryDate()); dayKey = cal.get(Calendar.DAY_OF_MONTH); if (calendarMap.containsKey(dayKey)) { dayEntries = calendarMap.get(dayKey); } else { dayEntries = new ArrayList<>(); } dayEntries.add(entry); calendarMap.put(dayKey, dayEntries); } return calendarMap; } /** * Get week overview for a date. Week number of supplied requested week is used */ public WeekOverview getWeekOverview(User user, Calendar requestedWeek) { Calendar reqWeek = (Calendar) requestedWeek.clone(); reqWeek.setFirstDayOfWeek(configuration.getFirstDayOfWeek()); DateRange range = DateUtil.getDateRangeForWeek(reqWeek); List<TimesheetEntry> timesheetEntries = timesheetDAO.getTimesheetEntriesInRange(user.getUserId(), range); TimesheetComment comment = timesheetCommentDAO.findById(new TimesheetCommentId(user.getUserId(), range.getDateStart())); List<ProjectAssignment> assignments = projectAssignmentService.getProjectAssignmentsForUser(user.getUserId(), range); Seq<Interval> lockedDatesAsIntervals = timesheetLockService.findLockedDatesInRange(range.getDateStart(), range.getDateEnd(), user); List<Date> lockedDates = TimesheetLockService$.MODULE$.intervalToJavaDates(lockedDatesAsIntervals); return new WeekOverview(timesheetEntries, comment, assignments, range, user, lockedDates); } }