/* * This program is part of the OpenLMIS logistics management information system platform software. * Copyright © 2013 VillageReach * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  */ package org.openlmis.core.repository.mapper; import org.joda.time.DateTime; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.openlmis.core.builder.ProcessingPeriodBuilder; import org.openlmis.core.domain.ProcessingPeriod; import org.openlmis.core.domain.ProcessingSchedule; import org.openlmis.db.categories.IntegrationTests; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DuplicateKeyException; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.transaction.annotation.Transactional; import java.util.Date; import java.util.List; import static com.natpryce.makeiteasy.MakeItEasy.*; import static java.util.Arrays.asList; import static junit.framework.Assert.assertNull; import static org.apache.commons.lang.time.DateUtils.addDays; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.matchers.JUnitMatchers.hasItems; import static org.openlmis.core.builder.ProcessingPeriodBuilder.*; import static org.openlmis.core.builder.ProcessingScheduleBuilder.code; import static org.openlmis.core.builder.ProcessingScheduleBuilder.defaultProcessingSchedule; @Category(IntegrationTests.class) @ContextConfiguration(locations = "classpath:test-applicationContext-core.xml") @RunWith(SpringJUnit4ClassRunner.class) @TransactionConfiguration(defaultRollback = true, transactionManager = "openLmisTransactionManager") @Transactional public class ProcessingPeriodMapperIT { @Rule public ExpectedException expectedException = ExpectedException.none(); @Autowired private ProcessingPeriodMapper mapper; @Autowired private ProcessingScheduleMapper scheduleMapper; private ProcessingSchedule schedule; @Before public void setUp() throws Exception { schedule = make(a(defaultProcessingSchedule)); scheduleMapper.insert(schedule); } @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 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 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 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 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 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 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 shouldGetAllPeriodsAfterAGivenPeriodAndADate() 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.getAllPeriodsAfterDateAndPeriod(schedule.getId(), period2.getId(), date3.toDate(), date1.toDate()); assertThat(relevantPeriods.size(), is(2)); assertThat(relevantPeriods.get(0).getId(), is(period3.getId())); assertThat(relevantPeriods.get(1).getId(), is(period4.getId())); } @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())); } @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 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 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))); } @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)); } @Test public void shouldGetCurrentPeriodIfProgramStartDateIsWithinCurrentPeriod() { 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(), 2); ProcessingPeriod actualPeriod = mapper.getCurrentPeriod(schedule.getId(), programStartDate); assertThat(actualPeriod, is(period1)); } @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 shouldGetNPreviousPeriodsGivenSpecificPeriod() throws Exception { DateTime now = DateTime.now(); insertProcessingPeriod("Period1", now.minusDays(14), now.minusDays(13)); ProcessingPeriod period2 = insertProcessingPeriod("Period2", now.minusDays(12), now.minusDays(11)); ProcessingPeriod period3 = insertProcessingPeriod("Period3", now.minusDays(10), now.minusDays(9)); ProcessingPeriod period4 = insertProcessingPeriod("Period4", now.minusDays(8), now.minusDays(7)); ProcessingPeriod period5 = insertProcessingPeriod("Period5", now.minusDays(6), now.minusDays(5)); ProcessingPeriod period6 = insertProcessingPeriod("Period6", now.minusDays(4), now.minusDays(3)); ProcessingPeriod currentPeriod = insertProcessingPeriod("Period", now.minusDays(2), now); List<ProcessingPeriod> nPreviousPeriods = mapper.getNPreviousPeriods(currentPeriod, 5); assertThat(nPreviousPeriods, is(asList(period6, period5, period4, period3, period2))); assertThat(nPreviousPeriods.size(), is(5)); } @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)); } 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; } }