@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()));
  }
  @Before
  public void setUp() throws Exception {
    Product product = make(a(ProductBuilder.defaultProduct));
    productMapper.insert(product);

    Program program = make(a(ProgramBuilder.defaultProgram));
    programMapper.insert(program);

    ProductCategory category = new ProductCategory("C1", "Category 1", 1);
    productCategoryMapper.insert(category);

    ProgramProduct programProduct =
        new ProgramProduct(program, product, 30, true, new Money("12.5"));
    programProduct.setProductCategory(category);
    programProductMapper.insert(programProduct);

    Facility facility = make(a(FacilityBuilder.defaultFacility));
    facilityMapper.insert(facility);

    ProcessingSchedule processingSchedule =
        make(a(ProcessingScheduleBuilder.defaultProcessingSchedule));
    processingScheduleMapper.insert(processingSchedule);

    ProcessingPeriod processingPeriod =
        make(a(defaultProcessingPeriod, with(scheduleId, processingSchedule.getId())));
    processingPeriodMapper.insert(processingPeriod);

    requisition = new Rnr(facility, new Program(HIV), processingPeriod, false, MODIFIED_BY, 1L);
    requisition.setStatus(INITIATED);
    requisitionMapper.insert(requisition);

    user = new User();
    user.setId(MODIFIED_BY);
  }
  @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()));
  }
  @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()));
  }
 public ProcessingSchedule save(ProcessingSchedule processingSchedule) {
   if (processingSchedule.getId() == null || processingSchedule.getId() == 0) {
     repository.create(processingSchedule);
   } else {
     repository.update(processingSchedule);
   }
   return repository.get(processingSchedule.getId());
 }
  @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 shouldGetAllPeriodsBeforeDate() 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);
    DateTime searchStartDate = currentDate;
    List<ProcessingPeriod> searchResults =
        mapper.getAllPeriodsBefore(schedule.getId(), searchStartDate.toDate());
    for (ProcessingPeriod period : searchResults) {
      period.setModifiedDate(null);
    }
    assertThat(searchResults, is(asList(period1, period3, period2)));
  }
  @Test
  public void shouldReturnEmptyListIfNoPeriodFoundForGivenSchedule() throws Exception {
    ProcessingPeriod period1 = make(a(defaultProcessingPeriod, with(scheduleId, schedule.getId())));
    mapper.insert(period1);

    List<ProcessingPeriod> fetchedPeriods = mapper.getAll(1233L);
    assertTrue(fetchedPeriods.isEmpty());
  }
  @Test
  public void shouldNotInsertDuplicatePeriodName() throws Exception {
    ProcessingSchedule schedule2 = make(a(defaultProcessingSchedule, with(code, "XXX")));
    scheduleMapper.insert(schedule2);

    ProcessingPeriod period1 =
        make(a(defaultProcessingPeriod, with(scheduleId, schedule.getId()), with(name, "Month1")));
    ProcessingPeriod period2 =
        make(a(defaultProcessingPeriod, with(scheduleId, schedule2.getId()), with(name, "Month1")));
    ProcessingPeriod period3 =
        make(a(defaultProcessingPeriod, with(scheduleId, schedule2.getId()), with(name, "Month1")));
    expectedException.expect(DuplicateKeyException.class);
    expectedException.expectMessage("duplicate key value violates unique constraint");
    mapper.insert(period1);
    mapper.insert(period2);
    mapper.insert(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 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 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 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));
  }
  private ProcessingPeriod insertProcessingPeriod(
      String name, DateTime startDate, DateTime endDate) {
    ProcessingPeriod period =
        make(
            a(
                defaultProcessingPeriod,
                with(ProcessingPeriodBuilder.name, name),
                with(scheduleId, schedule.getId()),
                with(ProcessingPeriodBuilder.startDate, startDate.toDate()),
                with(ProcessingPeriodBuilder.endDate, endDate.toDate())));

    mapper.insert(period);
    return period;
  }
  @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 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()));
  }
 public List<ProcessingPeriod> getPeriodsForDeliveryZoneAndProgram(Long zoneId, Long programId) {
   ProcessingSchedule schedule =
       repository.getProcessingScheduleByZoneAndProgram(zoneId, programId);
   return scheduleService.getAllPeriodsBefore(schedule.getId(), null);
 }