@Test
  public void shouldReturnLastAddedPeriodForASchedule() throws Exception {
    DateTime date1 = new DateTime();
    DateTime date2 = date1.plusMonths(3);

    ProcessingPeriod period1 =
        make(
            a(
                defaultProcessingPeriod,
                with(ProcessingPeriodBuilder.startDate, date1.toDate()),
                with(scheduleId, schedule.getId())));
    ProcessingPeriod period2 =
        make(
            a(
                defaultProcessingPeriod,
                with(ProcessingPeriodBuilder.startDate, date2.toDate()),
                with(scheduleId, schedule.getId()),
                with(name, "Month2")));

    mapper.insert(period1);
    mapper.insert(period2);

    ProcessingPeriod fetchedPeriod = mapper.getLastAddedProcessingPeriod(schedule.getId());
    assertThat(fetchedPeriod.getId(), is(period2.getId()));
  }
  @Test
  public void shouldReturnAllPeriodsForASchedule() throws Exception {
    DateTime date1 = new DateTime();
    DateTime date2 = date1.plusMonths(3);

    ProcessingPeriod period1 =
        make(
            a(
                defaultProcessingPeriod,
                with(ProcessingPeriodBuilder.startDate, date1.toDate()),
                with(scheduleId, schedule.getId())));
    ProcessingPeriod period2 =
        make(
            a(
                defaultProcessingPeriod,
                with(ProcessingPeriodBuilder.startDate, date2.toDate()),
                with(scheduleId, schedule.getId()),
                with(name, "Month2")));

    mapper.insert(period1);
    mapper.insert(period2);

    List<ProcessingPeriod> fetchedPeriods = mapper.getAll(schedule.getId());
    assertThat(fetchedPeriods.size(), is(2));
    assertThat(fetchedPeriods.get(0).getId(), is(period2.getId()));
  }
  @Test
  public void shouldGetAllPeriodsForPeriodDateRange() throws Exception {
    DateTime currentDate = DateTime.parse("2013-01-01");
    ProcessingPeriod period1 =
        make(
            a(
                defaultProcessingPeriod,
                with(ProcessingPeriodBuilder.startDate, currentDate.toDate()),
                with(ProcessingPeriodBuilder.endDate, currentDate.plusMonths(1).toDate()),
                with(scheduleId, schedule.getId()),
                with(name, "Month1")));
    ProcessingPeriod period2 =
        make(
            a(
                defaultProcessingPeriod,
                with(ProcessingPeriodBuilder.startDate, currentDate.plusMonths(1).toDate()),
                with(ProcessingPeriodBuilder.endDate, currentDate.plusMonths(2).toDate()),
                with(scheduleId, schedule.getId()),
                with(name, "Month2")));
    ProcessingPeriod period3 =
        make(
            a(
                defaultProcessingPeriod,
                with(ProcessingPeriodBuilder.startDate, currentDate.plusMonths(2).toDate()),
                with(ProcessingPeriodBuilder.endDate, currentDate.plusMonths(3).toDate()),
                with(scheduleId, schedule.getId()),
                with(name, "Month3")));
    ProcessingPeriod period4 =
        make(
            a(
                defaultProcessingPeriod,
                with(ProcessingPeriodBuilder.startDate, currentDate.plusDays(2).toDate()),
                with(ProcessingPeriodBuilder.endDate, currentDate.plusMonths(1).toDate()),
                with(scheduleId, schedule.getId()),
                with(name, "Month4")));
    ProcessingPeriod period5 =
        make(
            a(
                defaultProcessingPeriod,
                with(ProcessingPeriodBuilder.startDate, currentDate.minusDays(2).toDate()),
                with(ProcessingPeriodBuilder.endDate, currentDate.plusMonths(3).toDate()),
                with(scheduleId, schedule.getId()),
                with(name, "Month5")));

    mapper.insert(period1);
    mapper.insert(period2);
    mapper.insert(period3);
    mapper.insert(period4);
    mapper.insert(period5);
    DateTime searchStartDate = currentDate;
    DateTime searchEndDate = searchStartDate.plusDays(45);
    List<ProcessingPeriod> searchResults =
        mapper.getAllPeriodsForDateRange(
            schedule.getId(), searchStartDate.toDate(), searchEndDate.toDate());
    for (ProcessingPeriod period : searchResults) {
      period.setModifiedDate(null);
    }
    assertThat(searchResults, is(hasItems(period1, period2, period4, period5)));
    assertThat(searchResults, is(not(hasItems(period3))));
  }
  @Test
  public void shouldGetPeriodById() {
    ProcessingPeriod processingPeriod =
        make(a(defaultProcessingPeriod, with(scheduleId, schedule.getId())));
    mapper.insert(processingPeriod);

    ProcessingPeriod period = mapper.getById(processingPeriod.getId());
    assertThat(period.getName(), is(processingPeriod.getName()));
  }
  @Test
  public void shouldDeleteAPeriod() {
    ProcessingPeriod processingPeriod =
        make(a(defaultProcessingPeriod, with(scheduleId, schedule.getId())));
    mapper.insert(processingPeriod);

    mapper.delete(processingPeriod.getId());
    assertThat(mapper.getAll(schedule.getId()).size(), is(0));
  }
  @Test
  public void shouldInsertPeriodWithAllData() throws Exception {
    Date date1 = new Date();
    Date date2 = new Date(date1.getTime() + 90 * 24 * 60 * 60 * 1000);

    ProcessingPeriod period1 =
        make(
            a(
                defaultProcessingPeriod,
                with(scheduleId, schedule.getId()),
                with(ProcessingPeriodBuilder.startDate, date1),
                with(endDate, date2),
                with(numberOfMonths, 3)));

    Integer insertCount = mapper.insert(period1);

    assertThat(insertCount, is(1));
    ProcessingPeriod insertedPeriod = mapper.getAll(schedule.getId()).get(0);
    assertThat(insertedPeriod.getName(), is("Month1"));
    assertThat(insertedPeriod.getDescription(), is("first month"));
    assertThat(insertedPeriod.getStartDate(), is(date1));
    assertThat(insertedPeriod.getEndDate(), is(date2));
    assertThat(insertedPeriod.getNumberOfMonths(), is(3));
    assertThat(insertedPeriod.getModifiedBy(), is(1L));
    assertThat(insertedPeriod.getModifiedDate(), is(notNullValue()));
  }
 public Integer findM(ProcessingPeriod currentPeriod) {
   List<ProcessingPeriod> nPreviousPeriods =
       periodRepository.getNPreviousPeriods(currentPeriod, 1);
   if (nPreviousPeriods.size() > 0) {
     return nPreviousPeriods.get(0).getNumberOfMonths();
   }
   return currentPeriod.getNumberOfMonths();
 }
  @Test
  public void shouldGetPeriodContainingADateForASchedule() throws Exception {
    Date currentDate = new Date();
    ProcessingPeriod period =
        make(
            a(
                defaultProcessingPeriod,
                with(startDate, addDays(currentDate, -1)),
                with(endDate, addDays(currentDate, 5)),
                with(scheduleId, schedule.getId()),
                with(name, "Month1")));
    mapper.insert(period);

    ProcessingPeriod periodForDate = mapper.getPeriodForDate(period.getScheduleId(), currentDate);

    assertThat(periodForDate, is(period));
  }
  @Test
  public void shouldGetAllPeriodsBeforeCurrentDate() throws Exception {
    DateTime currentDate = DateTime.parse("2013-01-01");
    ProcessingPeriod period1 =
        make(
            a(
                defaultProcessingPeriod,
                with(ProcessingPeriodBuilder.startDate, currentDate.toDate()),
                with(ProcessingPeriodBuilder.endDate, currentDate.plusMonths(1).toDate()),
                with(scheduleId, schedule.getId()),
                with(name, "Month1")));
    ProcessingPeriod period2 =
        make(
            a(
                defaultProcessingPeriod,
                with(ProcessingPeriodBuilder.startDate, currentDate.minusMonths(2).toDate()),
                with(ProcessingPeriodBuilder.endDate, currentDate.minusMonths(1).toDate()),
                with(scheduleId, schedule.getId()),
                with(name, "Month2")));
    ProcessingPeriod period3 =
        make(
            a(
                defaultProcessingPeriod,
                with(ProcessingPeriodBuilder.startDate, currentDate.minusMonths(1).toDate()),
                with(ProcessingPeriodBuilder.endDate, currentDate.plusMonths(1).toDate()),
                with(scheduleId, schedule.getId()),
                with(name, "Month3")));
    ProcessingPeriod period4 =
        make(
            a(
                defaultProcessingPeriod,
                with(ProcessingPeriodBuilder.startDate, currentDate.plusMonths(1).toDate()),
                with(ProcessingPeriodBuilder.endDate, currentDate.plusMonths(2).toDate()),
                with(scheduleId, schedule.getId()),
                with(name, "Month5")));

    mapper.insert(period1);
    mapper.insert(period2);
    mapper.insert(period3);
    mapper.insert(period4);
    List<ProcessingPeriod> searchResults = mapper.getAllPeriodsBefore(schedule.getId(), null);
    for (ProcessingPeriod period : searchResults) {
      period.setModifiedDate(null);
    }
    assertThat(searchResults, is(asList(period4, period1, period3, period2)));
  }
 @Override
 public ProcessingPeriod instantiate(PropertyLookup<ProcessingPeriod> lookup) {
   Long nullLong = null;
   ProcessingPeriod period = new ProcessingPeriod();
   period.setName(lookup.valueOf(name, PERIOD_NAME));
   period.setDescription(lookup.valueOf(description, PERIOD_DESC));
   period.setStartDate(lookup.valueOf(startDate, START_DATE));
   period.setEndDate(lookup.valueOf(endDate, END_DATE));
   period.setNumberOfMonths(lookup.valueOf(numberOfMonths, NUMBER_OF_MONTHS));
   period.setModifiedBy(lookup.valueOf(modifiedBy, MODIFIED_BY));
   period.setScheduleId(lookup.valueOf(scheduleId, SCHEDULE_ID));
   period.setId(lookup.valueOf(id, nullLong));
   return period;
 }
  @Test
  public void shouldReturnNullIfCurrentPeriodDoesNotExist() {
    Date currentDate = new Date();
    ProcessingPeriod period1 =
        make(
            a(
                defaultProcessingPeriod,
                with(startDate, addDays(currentDate, 2)),
                with(endDate, addDays(currentDate, 5)),
                with(scheduleId, schedule.getId()),
                with(name, "Month1")));

    mapper.insert(period1);

    ProcessingPeriod actualPeriod =
        mapper.getCurrentPeriod(schedule.getId(), period1.getStartDate());

    assertNull(actualPeriod);
  }
  @Test
  public void shouldNotGetCurrentPeriodIfProgramStartDateIsAfterCurrentPeriodEndDate() {
    Date currentDate = new Date();
    ProcessingPeriod period1 =
        make(
            a(
                defaultProcessingPeriod,
                with(startDate, addDays(currentDate, -1)),
                with(endDate, addDays(currentDate, 5)),
                with(scheduleId, schedule.getId()),
                with(name, "Month1")));

    mapper.insert(period1);

    Date programStartDate = addDays(period1.getStartDate(), 7);
    ProcessingPeriod actualPeriod = mapper.getCurrentPeriod(schedule.getId(), programStartDate);

    Assert.assertNull(actualPeriod);
  }
  @Test
  public void shouldGetCurrentPeriodByFacilityAndProgram() {
    Date currentDate = new Date();
    ProcessingPeriod period1 =
        make(
            a(
                defaultProcessingPeriod,
                with(startDate, addDays(currentDate, -1)),
                with(endDate, addDays(currentDate, 5)),
                with(scheduleId, schedule.getId()),
                with(name, "Month1")));

    mapper.insert(period1);

    ProcessingPeriod actualPeriod =
        mapper.getCurrentPeriod(schedule.getId(), period1.getStartDate());

    assertThat(actualPeriod, is(period1));
  }
  @RequestMapping(value = "/schedules/{scheduleId}/periods", method = POST, headers = ACCEPT_JSON)
  @PreAuthorize("@permissionEvaluator.hasPermission(principal,'MANAGE_SCHEDULE')")
  public ResponseEntity<OpenLmisResponse> save(
      @PathVariable("scheduleId") Long scheduleId,
      @RequestBody ProcessingPeriod processingPeriod,
      HttpServletRequest request) {
    processingPeriod.setScheduleId(scheduleId);

    processingPeriod.setModifiedBy(loggedInUserId(request));

    processingPeriod.setCreatedBy(loggedInUserId(request));

    try {
      processingScheduleService.savePeriod(processingPeriod);
    } catch (Exception e) {
      return error(new DataException(e.getMessage()), HttpStatus.BAD_REQUEST);
    }
    ResponseEntity<OpenLmisResponse> successResponse =
        success(messageService.message("message.period.added.success"));
    successResponse.getBody().addData("id", processingPeriod.getId());
    return successResponse;
  }
  @Test
  public void shouldGetAllPeriodsAfterAGivenDate() throws Exception {
    DateTime date1 = new DateTime();
    DateTime date2 = date1.minusMonths(1);
    DateTime date3 = date1.minusMonths(2);
    DateTime date4 = date1.minusMonths(3);
    DateTime date5 = date1.minusMonths(4);
    DateTime futureDate = date1.plusMonths(1);

    insertProcessingPeriod("Period 1", date5, date4);
    ProcessingPeriod period2 = insertProcessingPeriod("Period 2", date4.plusDays(1), date3);
    ProcessingPeriod period3 = insertProcessingPeriod("Period 3", date3.plusDays(1), date2);
    ProcessingPeriod period4 = insertProcessingPeriod("Period 4", date2.plusDays(1), date1);
    insertProcessingPeriod("Period 5", date1.plusDays(1), futureDate);

    List<ProcessingPeriod> relevantPeriods =
        mapper.getAllPeriodsAfterDate(schedule.getId(), date3.toDate(), date1.toDate());

    assertThat(relevantPeriods.size(), is(3));
    assertThat(relevantPeriods.get(0).getId(), is(period2.getId()));
    assertThat(relevantPeriods.get(1).getId(), is(period3.getId()));
    assertThat(relevantPeriods.get(2).getId(), is(period4.getId()));
  }