/* * This program is part of the OpenLMIS logistics management information * system platform software. * * Copyright © 2015 ThoughtWorks, Inc. * * 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.model.repository; import android.support.annotation.NonNull; import com.google.inject.AbstractModule; import org.joda.time.DateTime; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.openlmis.core.LMISRepositoryUnitTest; import org.openlmis.core.LMISTestApp; import org.openlmis.core.LMISTestRunner; import org.openlmis.core.exceptions.LMISException; import org.openlmis.core.manager.MovementReasonManager; import org.openlmis.core.model.BaseInfoItem; import org.openlmis.core.model.Lot; import org.openlmis.core.model.LotOnHand; import org.openlmis.core.model.Period; import org.openlmis.core.model.Product; import org.openlmis.core.model.ProductProgram; import org.openlmis.core.model.Program; import org.openlmis.core.model.RegimenItem; import org.openlmis.core.model.RnRForm; import org.openlmis.core.model.RnrFormItem; import org.openlmis.core.model.StockCard; import org.openlmis.core.model.StockMovementItem; import org.openlmis.core.model.builder.ProductBuilder; import org.openlmis.core.model.service.RequisitionPeriodService; import org.openlmis.core.utils.DateUtil; import org.roboguice.shaded.goole.common.collect.Lists; import org.robolectric.RuntimeEnvironment; import java.util.ArrayList; import java.util.Date; import java.util.List; import roboguice.RoboGuice; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertNull; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyList; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import static org.roboguice.shaded.goole.common.collect.Lists.newArrayList; @RunWith(LMISTestRunner.class) public class MMIARepositoryTest extends LMISRepositoryUnitTest { ProductRepository mockProductRepository; MMIARepository mmiaRepository; StockRepository mockStockRepository; ProgramRepository mockProgramRepository; ProductProgramRepository productProgramRepository; RequisitionPeriodService mockRequisitionPeriodService; private Program program; RegimenItemRepository regimenItemRepository; private StockMovementRepository mockStockMovementRepository; @Before public void setup() throws LMISException { mockStockRepository = mock(StockRepository.class); mockProgramRepository = mock(ProgramRepository.class); mockProductRepository = mock(ProductRepository.class); mockRequisitionPeriodService = mock(RequisitionPeriodService.class); productProgramRepository = mock(ProductProgramRepository.class); regimenItemRepository = mock(RegimenItemRepository.class); mockStockMovementRepository = mock(StockMovementRepository.class); RoboGuice.overrideApplicationInjector(RuntimeEnvironment.application, new MyTestModule()); mmiaRepository = RoboGuice.getInjector(RuntimeEnvironment.application).getInstance(MMIARepository.class); program = new Program("ART", "ART", null, false, null); when(mockProgramRepository.queryByCode(anyString())).thenReturn(program); } @Test public void shouldCalculateInfoFromStockCardByPeriod() throws Exception { Date mockDay1 = DateUtil.parseString("2017-01-10", DateUtil.DB_DATE_FORMAT); Date mockDay2 = DateUtil.parseString("2017-01-15", DateUtil.DB_DATE_FORMAT); Date mockDay3 = DateUtil.parseString("2017-01-20", DateUtil.DB_DATE_FORMAT); Date mockToday = DateUtil.parseString("2017-01-22", DateUtil.DB_DATE_FORMAT); LMISTestApp.getInstance().setCurrentTimeMillis(mockToday.getTime()); Product product = generateProduct(); StockCard stockCard = generateStockCard(product); List<StockCard> stockCards = new ArrayList<>(); stockCards.add(stockCard); StockMovementItem stockMovementItem1 = createMovementItem(MovementReasonManager.MovementType.ISSUE, 10, stockCard, mockDay1, mockDay1); StockMovementItem stockMovementItem2 = createMovementItem(MovementReasonManager.MovementType.RECEIVE, 20, stockCard, mockDay2, mockDay2); StockMovementItem stockMovementItem3 = createMovementItem(MovementReasonManager.MovementType.POSITIVE_ADJUST, 30, stockCard, mockDay3, mockDay3); when(mockRequisitionPeriodService.generateNextPeriod(anyString(), any(Date.class))).thenReturn(new Period(new DateTime("2016-12-27"), new DateTime("2017-01-20"))); when(mockStockMovementRepository.queryStockItemsByCreatedDate(anyLong(), any(Date.class), any(Date.class))) .thenReturn(newArrayList(stockMovementItem1, stockMovementItem2, stockMovementItem3)); when(mockStockRepository.getStockCardsBeforePeriodEnd(any(RnRForm.class))).thenReturn(stockCards); ProductProgram productProgram = new ProductProgram(); productProgram.setCategory("Adult"); when(productProgramRepository.queryByCode(anyString(), anyList())).thenReturn(productProgram); List<String> mmiaCodes = newArrayList("MMIA"); when(mockProgramRepository.queryProgramCodesByProgramCodeOrParentCode(anyString())).thenReturn(mmiaCodes); List<Long> mmiaProductIds = new ArrayList<>(); when(productProgramRepository.queryActiveProductIdsByProgramsWithKits(mmiaCodes, false)).thenReturn(mmiaProductIds); Product someProduct = ProductBuilder.buildAdultProduct(); when(mockProductRepository.queryProductsByProductIds(mmiaProductIds)).thenReturn(newArrayList(product, someProduct)); RnRForm form = mmiaRepository.initNormalRnrForm(null); assertThat(form.getRnrFormItemList().size(), is(2)); RnrFormItem item = form.getRnrFormItemListWrapper().get(0); assertThat(item.getReceived(), is(20L)); assertThat(item.getIssued(), is(10L)); assertThat(item.getAdjustment(), is(30L)); assertThat(item.getInitialAmount(), is(10L)); assertThat(item.getInventory(), is(50L)); } @NonNull private Product generateProduct() { Product product = new Product(); product.setId(1L); product.setCode("ABC"); product.setPrimaryName("Test Product"); product.setStrength("200"); return product; } @NonNull private StockCard generateStockCard(Product product) { StockCard stockCard = new StockCard(); stockCard.setProduct(product); stockCard.setStockOnHand(10); stockCard.setCreatedAt(RnRForm.init(program, DateUtil.today()).getPeriodEnd()); return stockCard; } @Test public void shouldSaveSuccess() throws Exception { when(mockRequisitionPeriodService.generateNextPeriod(anyString(), any(Date.class))).thenReturn(new Period(new DateTime("2016-12-27"), new DateTime("2017-01-20"))); RnRForm initForm = mmiaRepository.initNormalRnrForm(null); List<RegimenItem> regimenItemListWrapper = initForm.getRegimenItemListWrapper(); for (int i = 0; i < regimenItemListWrapper.size(); i++) { RegimenItem item = regimenItemListWrapper.get(i); item.setAmount((long) i); } List<BaseInfoItem> baseInfoItemListWrapper = initForm.getBaseInfoItemListWrapper(); for (int i = 0; i < baseInfoItemListWrapper.size(); i++) { BaseInfoItem item = baseInfoItemListWrapper.get(i); item.setValue(String.valueOf(i)); } mmiaRepository.createOrUpdateWithItems(initForm); List<RnRForm> list = mmiaRepository.list(); RnRForm DBForm = list.get(list.size() - 1); long expectRegimeTotal = RnRForm.calculateTotalRegimenAmount(initForm.getRegimenItemListWrapper()); long regimenTotal = RnRForm.calculateTotalRegimenAmount(DBForm.getRegimenItemListWrapper()); assertThat(expectRegimeTotal, is(regimenTotal)); assertThat(mmiaRepository.getTotalPatients(initForm), is(mmiaRepository.getTotalPatients(DBForm))); } @Test public void shouldGenerateBaseInfoItems() throws Exception { RnRForm rnRForm = new RnRForm(); List<BaseInfoItem> baseInfoItems = mmiaRepository.generateBaseInfoItems(rnRForm); assertThat(baseInfoItems.size(), is(7)); assertThat(baseInfoItems.get(0).getName(), is(mmiaRepository.ATTR_NEW_PATIENTS)); assertThat(baseInfoItems.get(3).getName(), is(mmiaRepository.ATTR_PTV)); assertThat(baseInfoItems.get(baseInfoItems.size() - 1).getName(), is(mmiaRepository.ATTR_TOTAL_PATIENTS)); } @Test public void shouldInitRnrFormItemWithoutMovement() throws Exception { mmiaRepository = spy(mmiaRepository); Product product = new Product(); RnRForm form = new RnRForm(); RnrFormItem rnrFormItem = new RnrFormItem(); rnrFormItem.setInventory(100L); rnrFormItem.setProduct(product); form.setRnrFormItemListWrapper(newArrayList(rnrFormItem)); doReturn(newArrayList(form)).when(mmiaRepository).listInclude(any(RnRForm.Emergency.class), anyString()); StockCard stockCard = new StockCard(); product.setId(20); stockCard.setProduct(product); Lot lot = new Lot(); lot.setExpirationDate(DateUtil.parseString("Feb 2015", DateUtil.DATE_FORMAT_ONLY_MONTH_AND_YEAR)); stockCard.setLotOnHandListWrapper(newArrayList(new LotOnHand(lot, stockCard, 10L))); when(mockStockMovementRepository.queryStockMovementsByMovementDate(anyLong(), any(Date.class), any(Date.class))).thenReturn(new ArrayList<StockMovementItem>()); RnrFormItem rnrFormItemByPeriod = mmiaRepository.createRnrFormItemByPeriod(stockCard, new Date(), new Date()); assertThat(rnrFormItemByPeriod.getValidate(), is("01/02/2015")); assertThat(rnrFormItemByPeriod.getReceived(), is(0L)); assertThat(rnrFormItemByPeriod.getCalculatedOrderQuantity(), is(0L)); assertThat(rnrFormItemByPeriod.getInventory(), is(100L)); assertThat(rnrFormItemByPeriod.getInitialAmount(), is(100L)); stockCard.setLotOnHandListWrapper(Lists.<LotOnHand>newArrayList()); rnrFormItemByPeriod = mmiaRepository.createRnrFormItemByPeriod(stockCard, new Date(), new Date()); assertNull(rnrFormItemByPeriod.getValidate()); } private StockMovementItem createMovementItem(MovementReasonManager.MovementType type, long quantity, StockCard stockCard, Date createdTime, Date movementDate) throws LMISException { StockMovementItem stockMovementItem = new StockMovementItem(); stockMovementItem.setMovementQuantity(quantity); stockMovementItem.setMovementType(type); stockMovementItem.setMovementDate(movementDate); stockMovementItem.setStockCard(stockCard); stockMovementItem.setCreatedTime(createdTime); if (stockMovementItem.isPositiveMovement()) { stockMovementItem.setStockOnHand(stockCard.getStockOnHand() + quantity); } else { stockMovementItem.setStockOnHand(stockCard.getStockOnHand() - quantity); } stockCard.setStockOnHand(stockMovementItem.getStockOnHand()); return stockMovementItem; } public class MyTestModule extends AbstractModule { @Override protected void configure() { bind(ProductRepository.class).toInstance(mockProductRepository); bind(StockRepository.class).toInstance(mockStockRepository); bind(ProgramRepository.class).toInstance(mockProgramRepository); bind(RequisitionPeriodService.class).toInstance(mockRequisitionPeriodService); bind(ProductProgramRepository.class).toInstance(productProgramRepository); bind(RegimenItemRepository.class).toInstance(regimenItemRepository); bind(StockMovementRepository.class).toInstance(mockStockMovementRepository); } } }