TimesheetPersistence implements IPersistTimesheet, IDeleteTimesheetEntry { @Transactional(rollbackFor = OverBudgetException.class, propagation = Propagation.REQUIRES_NEW) @NonAuditable public void validateAndPersist(ProjectAssignment assignment, List<TimesheetEntry> entries, DateRange weekRange, List<Date> lockedDates) throws OverBudgetException { ProjectAssignmentStatus beforeStatus = projectAssignmentStatusService.getAssignmentStatus(assignment); boolean checkAfterStatus = beforeStatus.isValid(); try { persistEntries(assignment, entries, weekRange, !beforeStatus.isValid(), lockedDates); } catch (OverBudgetException obe) { checkAfterStatus = true; } ProjectAssignmentStatus afterStatus = projectAssignmentStatusService.getAssignmentStatus(assignment); if (checkAfterStatus && !afterStatus.isValid()) { throw new OverBudgetException(afterStatus); } else if (!beforeStatus.equals(afterStatus) && canNotifyPm(assignment)) { notifyPm(assignment, afterStatus); } } @Autowired  TimesheetPersistence(TimesheetDao timesheetDAO,
                                TimesheetCommentDao timesheetCommentDAO,
                                ProjectAssignmentStatusService projectAssignmentStatusService,
                                ProjectManagerNotifierService projectManagerNotifierService,
                                TimesheetLockService timesheetLockService,
                                ApplicationContext context); @Transactional void deleteAllTimesheetDataForUser(User user); @Transactional @Override List<ProjectAssignmentStatus> persistTimesheetWeek(Collection<TimesheetEntry> timesheetEntries,
                                                              TimesheetComment comment,
                                                              DateRange weekRange,
                                                              User forUser); @Transactional(rollbackFor = OverBudgetException.class, propagation = Propagation.REQUIRES_NEW) @NonAuditable void validateAndPersist(ProjectAssignment assignment,
                                   List<TimesheetEntry> entries,
                                   DateRange weekRange,
                                   List<Date> lockedDates);  }
@Test public void should_persist_new_timesheet() throws OverBudgetException { DateRange dateRange = new DateRange(); okStatus(); persister.validateAndPersist(assignment, newEntries, dateRange, Lists.<Date>newArrayList()); verify(statusService, times(2)).getAssignmentStatus(assignment); verify(timesheetDAO).persist(any(TimesheetEntry.class)); verify(timesheetDAO).getTimesheetEntriesInRange(assignment, dateRange); }
@Test public void should_update_existing_timesheet() throws OverBudgetException { DateRange dateRange = new DateRange(); withExistingEntries(dateRange); okStatus(); persister.validateAndPersist(assignment, newEntries, dateRange, Lists.<Date>newArrayList()); verify(statusService, times(2)).getAssignmentStatus(assignment); verify(timesheetDAO).delete(any(TimesheetEntry.class)); verify(timesheetDAO).merge(any(TimesheetEntry.class)); }
@Test public void should_not_persist_an_timesheet_that_went_overbudget() { DateRange dateRange = new DateRange(); withExistingEntries(dateRange); ProjectAssignmentStatus validStatus = new ProjectAssignmentStatus(); when(statusService.getAssignmentStatus(assignment)).thenReturn(validStatus); ProjectAssignmentStatus invalidStatus = new ProjectAssignmentStatus(); invalidStatus.addStatus(Status.OVER_OVERRUN); invalidStatus.setValid(false); when(statusService.getAssignmentStatus(assignment)).thenReturn(validStatus, invalidStatus); try { persister.validateAndPersist(assignment, newEntries, dateRange, Lists.<Date>newArrayList()); fail(); } catch (OverBudgetException e) { verify(timesheetDAO).merge(any(TimesheetEntry.class)); verify(timesheetDAO).delete(any(TimesheetEntry.class)); } }
@SuppressWarnings("deprecation") @Test public void should_allow_to_decrease_existing_hours_even_when_project_is_over_budget() throws OverBudgetException { Date dateC = new Date(2008 - 1900, Calendar.APRIL, 3); newEntries.clear(); existingEntries.clear(); { TimesheetEntry entryDel = new TimesheetEntry(); TimesheetEntryId idDel = new TimesheetEntryId(); idDel.setProjectAssignment(assignment); idDel.setEntryDate(dateC); entryDel.setEntryId(idDel); entryDel.setHours(7f); newEntries.add(entryDel); } { TimesheetEntry entryDel = new TimesheetEntry(); TimesheetEntryId idDel = new TimesheetEntryId(); idDel.setProjectAssignment(assignment); idDel.setEntryDate(dateC); entryDel.setEntryId(idDel); entryDel.setHours(8f); existingEntries.add(entryDel); } when(timesheetDAO.getTimesheetEntriesInRange(any(ProjectAssignment.class), any(DateRange.class))).thenReturn(existingEntries); ProjectAssignmentStatus beforeStatus = new ProjectAssignmentStatus(); beforeStatus.addStatus(Status.OVER_OVERRUN); beforeStatus.setValid(false); ProjectAssignmentStatus afterStatus = new ProjectAssignmentStatus(); afterStatus.addStatus(Status.OVER_OVERRUN); afterStatus.setValid(false); when(statusService.getAssignmentStatus(assignment)).thenReturn(beforeStatus, afterStatus); persister.validateAndPersist(assignment, newEntries, new DateRange(), Lists.<Date>newArrayList()); verify(timesheetDAO).merge(any(TimesheetEntry.class)); }
@Test public void should_not_allow_to_book_more_hours_when_the_project_is_overbudget() { when(timesheetDAO.getTimesheetEntriesInRange(any(ProjectAssignment.class), any(DateRange.class))).thenReturn(existingEntries); ProjectAssignmentStatus beforeStatus = new ProjectAssignmentStatus(); beforeStatus.setValid(false); ProjectAssignmentStatus afterStatus = new ProjectAssignmentStatus(); afterStatus.addStatus(Status.OVER_OVERRUN); afterStatus.setValid(false); when(statusService.getAssignmentStatus(assignment)).thenReturn(beforeStatus, afterStatus); try { persister.validateAndPersist(assignment, newEntries, new DateRange(), Lists.<Date>newArrayList()); fail(); } catch (OverBudgetException ignored) { } }
@Test public void should_mail_pm_when_status_of_project_changes() throws OverBudgetException { when(timesheetDAO.getLatestTimesheetEntryForAssignment(assignment.getAssignmentId())).thenReturn(newEntries.get(0)); when(timesheetDAO.getTimesheetEntriesInRange(any(ProjectAssignment.class), any(DateRange.class))).thenReturn(existingEntries); ProjectAssignmentStatus beforeStatus = new ProjectAssignmentStatus(); beforeStatus.addStatus(Status.IN_ALLOTTED); beforeStatus.setValid(true); ProjectAssignmentStatus afterStatus = new ProjectAssignmentStatus(); afterStatus.addStatus(Status.IN_OVERRUN); afterStatus.setValid(true); afterStatus.setAggregate(new AssignmentAggregateReportElement()); when(statusService.getAssignmentStatus(assignment)).thenReturn(beforeStatus); when(statusService.getAssignmentStatus(assignment)).thenReturn(beforeStatus, afterStatus); persister.validateAndPersist(assignment, newEntries, new DateRange(), Lists.<Date>newArrayList()); verify(timesheetDAO).delete(any(TimesheetEntry.class)); verify(timesheetDAO).merge(any(TimesheetEntry.class)); verify(projectManagerNotifierService).mailPMFlexAllottedReached(any(AssignmentAggregateReportElement.class), any(Date.class), eq(assignment.getProject().getProjectManager())); }
@Test public void should_delete_entries_that_are_not_resubmitted() throws OverBudgetException { DateRange dateRange = new DateRange(); withExistingEntries(dateRange); okStatus(); persister.validateAndPersist(assignment, Lists.newArrayList(newEntries.get(0)), dateRange, Lists.<Date>newArrayList()); verify(statusService, times(2)).getAssignmentStatus(assignment); verify(timesheetDAO).delete(existingEntries.get(1)); verify(timesheetDAO).merge(existingEntries.get(0)); }