package org.openlmis.core.model.repository;
import org.joda.time.DateTime;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
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.Lot;
import org.openlmis.core.model.LotMovementItem;
import org.openlmis.core.model.Product;
import org.openlmis.core.model.ProductProgram;
import org.openlmis.core.model.Program;
import org.openlmis.core.model.StockCard;
import org.openlmis.core.model.StockMovementItem;
import org.openlmis.core.model.builder.LotMovementItemBuilder;
import org.openlmis.core.model.builder.ProductBuilder;
import org.openlmis.core.model.builder.ProgramBuilder;
import org.openlmis.core.utils.DateUtil;
import org.roboguice.shaded.goole.common.collect.Lists;
import org.robolectric.RuntimeEnvironment;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import roboguice.RoboGuice;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.openlmis.core.manager.MovementReasonManager.MovementType.ISSUE;
import static org.openlmis.core.manager.MovementReasonManager.MovementType.RECEIVE;
import static org.openlmis.core.model.builder.StockCardBuilder.saveStockCardWithOneMovement;
@RunWith(LMISTestRunner.class)
public class StockMovementRepositoryTest {
StockRepository stockRepository;
StockMovementRepository stockMovementRepository;
StockMovementItem stockMovementItem;
private ProgramRepository programRepository;
private ProductRepository productRepository;
private ProductProgramRepository productProgramRepository;
Product product = ProductBuilder.buildAdultProduct();
@Before
public void setup() throws LMISException {
stockRepository = RoboGuice.getInjector(RuntimeEnvironment.application).getInstance(StockRepository.class);
stockMovementRepository = RoboGuice.getInjector(RuntimeEnvironment.application).getInstance(StockMovementRepository.class);
programRepository = RoboGuice.getInjector(RuntimeEnvironment.application).getInstance(ProgramRepository.class);
productRepository = RoboGuice.getInjector(RuntimeEnvironment.application).getInstance(ProductRepository.class);
productProgramRepository = RoboGuice.getInjector(RuntimeEnvironment.application).getInstance(ProductProgramRepository.class);
stockMovementItem = new StockMovementItem();
}
@Test
public void shouldListUnSyncedStockMovementItems() throws LMISException, ParseException {
//given one movement was saved but NOT SYNCED
StockCard stockCard = saveStockCardWithOneMovement(stockRepository);
assertThat(stockCard.getForeignStockMovementItems().size(), is(1));
assertThat(stockMovementRepository.listUnSynced().size(), is(1));
//when save another SYNCED movement
createMovementItem(RECEIVE, 100, stockCard, new Date(), DateUtil.today(), true);
//then
assertThat(stockCard.getForeignStockMovementItems().size(), is(2));
assertThat(stockMovementRepository.listUnSynced(), notNullValue());
assertThat(stockMovementRepository.listUnSynced().size(), is(1));
}
@Test
public void shouldListLastFiveStockMovementsOrderByDateInDescOrder() throws Exception {
StockCard stockCard = saveStockCardWithOneMovement(stockRepository);
createMovementItem(MovementReasonManager.MovementType.PHYSICAL_INVENTORY, 1000, stockCard, DateUtil.parseString("2015-12-12", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-11", DateUtil.DB_DATE_FORMAT), false);
createMovementItem(MovementReasonManager.MovementType.PHYSICAL_INVENTORY, 1001, stockCard, DateUtil.parseString("2015-12-13", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-12", DateUtil.DB_DATE_FORMAT), false);
createMovementItem(MovementReasonManager.MovementType.PHYSICAL_INVENTORY, 1002, stockCard, DateUtil.parseString("2015-12-14", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-13", DateUtil.DB_DATE_FORMAT), false);
List<StockMovementItem> stockMovementItems = stockMovementRepository.listLastFiveStockMovements(stockCard.getId());
assertEquals(4, stockMovementItems.size());
assertEquals(stockCard.getStockMovementItemsWrapper().get(0), stockMovementItems.get(0));
assertEquals(stockCard.getStockMovementItemsWrapper().get(1), stockMovementItems.get(1));
assertEquals(stockCard.getStockMovementItemsWrapper().get(2), stockMovementItems.get(2));
assertEquals(stockCard.getStockMovementItemsWrapper().get(3), stockMovementItems.get(3));
}
@Test
public void shouldQueryStockMovementsByMovementDate() throws Exception {
StockCard stockCard = saveStockCardWithOneMovement(stockRepository);
createMovementItem(MovementReasonManager.MovementType.PHYSICAL_INVENTORY, 1000, stockCard, DateUtil.parseString("2015-12-12", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-11", DateUtil.DB_DATE_FORMAT), false);
createMovementItem(MovementReasonManager.MovementType.PHYSICAL_INVENTORY, 1001, stockCard, DateUtil.parseString("2015-12-13", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-12", DateUtil.DB_DATE_FORMAT), false);
createMovementItem(MovementReasonManager.MovementType.PHYSICAL_INVENTORY, 1002, stockCard, DateUtil.parseString("2015-12-14", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-13", DateUtil.DB_DATE_FORMAT), false);
List<StockMovementItem> stockMovementItems = stockMovementRepository.queryStockMovementsByMovementDate(stockCard.getId(), DateUtil.parseString("2015-12-11", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-12", DateUtil.DB_DATE_FORMAT));
assertEquals(2, stockMovementItems.size());
assertEquals(stockCard.getStockMovementItemsWrapper().get(1), stockMovementItems.get(0));
assertEquals(stockCard.getStockMovementItemsWrapper().get(2), stockMovementItems.get(1));
}
@Test
public void shouldQueryStockMovementsByCreatedDate() throws Exception {
StockCard stockCard = saveStockCardWithOneMovement(stockRepository);
createMovementItem(MovementReasonManager.MovementType.PHYSICAL_INVENTORY, 1000, stockCard, DateUtil.parseString("2015-12-12", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-11", DateUtil.DB_DATE_FORMAT), false);
createMovementItem(MovementReasonManager.MovementType.PHYSICAL_INVENTORY, 1001, stockCard, DateUtil.parseString("2015-12-13", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-12", DateUtil.DB_DATE_FORMAT), false);
createMovementItem(MovementReasonManager.MovementType.PHYSICAL_INVENTORY, 1002, stockCard, DateUtil.parseString("2015-12-14", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-13", DateUtil.DB_DATE_FORMAT), false);
List<StockMovementItem> stockMovementItems = stockMovementRepository.queryStockItemsByCreatedDate(stockCard.getId(), DateUtil.parseString("2015-12-11", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-12", DateUtil.DB_DATE_FORMAT));
assertEquals(1, stockMovementItems.size());
assertEquals(stockCard.getStockMovementItemsWrapper().get(1), stockMovementItems.get(0));
}
@Test
public void shouldQueryStockMovementHistory() throws Exception {
StockCard stockCard = saveStockCardWithOneMovement(stockRepository);
createMovementItem(MovementReasonManager.MovementType.PHYSICAL_INVENTORY, 1000, stockCard, DateUtil.parseString("2015-12-12", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-11", DateUtil.DB_DATE_FORMAT), false);
createMovementItem(MovementReasonManager.MovementType.PHYSICAL_INVENTORY, 1001, stockCard, DateUtil.parseString("2015-12-13", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-12", DateUtil.DB_DATE_FORMAT), false);
createMovementItem(MovementReasonManager.MovementType.PHYSICAL_INVENTORY, 1002, stockCard, DateUtil.parseString("2015-12-14", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-13", DateUtil.DB_DATE_FORMAT), false);
List<StockMovementItem> stockMovementItems = stockMovementRepository.queryStockMovementHistory(stockCard.getId(), 1, 1);
assertEquals(1, stockMovementItems.size());
assertEquals(stockCard.getStockMovementItemsWrapper().get(1), stockMovementItems.get(0));
List<StockMovementItem> stockMovementItems1 = stockMovementRepository.queryStockMovementHistory(stockCard.getId(), 1, 3);
assertEquals(3, stockMovementItems1.size());
assertEquals(stockCard.getStockMovementItemsWrapper().get(3), stockMovementItems1.get(2));
}
@Test
public void shouldGetFirstStockMovement() throws Exception {
StockCard stockCard = saveStockCardWithOneMovement(stockRepository);
createMovementItem(MovementReasonManager.MovementType.PHYSICAL_INVENTORY, 1000, stockCard, DateUtil.parseString("2015-12-12", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-11", DateUtil.DB_DATE_FORMAT), false);
createMovementItem(MovementReasonManager.MovementType.PHYSICAL_INVENTORY, 1001, stockCard, DateUtil.parseString("2015-12-13", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-12", DateUtil.DB_DATE_FORMAT), false);
createMovementItem(MovementReasonManager.MovementType.PHYSICAL_INVENTORY, 1002, stockCard, DateUtil.parseString("2015-12-14", DateUtil.DB_DATE_FORMAT), DateUtil.parseString("2015-12-13", DateUtil.DB_DATE_FORMAT), false);
StockMovementItem stockMovementItem = stockMovementRepository.queryFirstStockMovementByStockCardId(stockCard.getId());
assertEquals(stockCard.getStockMovementItemsWrapper().get(0), stockMovementItem);
}
private StockMovementItem createMovementItem(MovementReasonManager.MovementType type, long quantity, StockCard stockCard, Date createdTime, Date movementDate, boolean synced) throws LMISException {
StockMovementItem stockMovementItem = new StockMovementItem();
stockMovementItem.setMovementQuantity(quantity);
stockMovementItem.setMovementType(type);
stockMovementItem.setMovementDate(movementDate);
stockMovementItem.setStockCard(stockCard);
stockMovementItem.setSynced(synced);
LMISTestApp.getInstance().setCurrentTimeMillis(createdTime.getTime());
if (stockMovementItem.isPositiveMovement()) {
stockMovementItem.setStockOnHand(stockCard.getStockOnHand() + quantity);
} else {
stockMovementItem.setStockOnHand(stockCard.getStockOnHand() - quantity);
}
stockCard.setStockOnHand(stockMovementItem.getStockOnHand());
stockRepository.addStockMovementAndUpdateStockCard(stockMovementItem);
stockRepository.refresh(stockCard);
return stockMovementItem;
}
@Test
public void shouldQueryEarliestStockMovementItemCreatedTimeByProgram() throws Exception {
Program mmia = new ProgramBuilder().setProgramCode("MMIA").build();
Program via = new ProgramBuilder().setProgramCode("VIA").build();
programRepository.createOrUpdate(mmia);
programRepository.createOrUpdate(via);
Product mmiaProduct = new ProductBuilder().setCode("B1").build();
productRepository.createOrUpdate(mmiaProduct);
Product viaProduct = new ProductBuilder().setCode("A1").build();
productRepository.createOrUpdate(viaProduct);
ArrayList<ProductProgram> productPrograms = new ArrayList<>();
ProductProgram viaProductProgram = new ProductProgram();
viaProductProgram.setProductCode(viaProduct.getCode());
viaProductProgram.setProgramCode(via.getProgramCode());
viaProductProgram.setActive(true);
productPrograms.add(viaProductProgram);
ProductProgram mmiaProductProgram = new ProductProgram();
mmiaProductProgram.setProductCode(viaProduct.getCode());
mmiaProductProgram.setProgramCode(via.getProgramCode());
mmiaProductProgram.setActive(true);
productPrograms.add(mmiaProductProgram);
productProgramRepository.batchSave(productPrograms);
StockCard stockCard = new StockCard();
stockCard.setProduct(mmiaProduct);
stockRepository.createOrUpdate(stockCard);
StockCard stockCard2 = new StockCard();
stockCard2.setProduct(viaProduct);
stockRepository.createOrUpdate(stockCard2);
createMovementItem(ISSUE, 100, stockCard, new DateTime("2017-01-01").toDate(), new DateTime("2017-01-01").toDate(), false);
createMovementItem(ISSUE, 100, stockCard2, new DateTime("2018-01-01").toDate(), new DateTime("2018-01-01").toDate(), false);
DateTime dateTime = new DateTime("2018-01-01");
Date expectedDate = new DateTime().withDate(dateTime.getYear(), dateTime.getMonthOfYear(), dateTime.getDayOfMonth()).toDate();
createMovementItem(ISSUE, 100, stockCard2, new DateTime("2018-03-02").toDate(), new DateTime("2018-03-02").toDate(), false);
Date earliestDate = stockMovementRepository.queryEarliestStockMovementDateByProgram(via.getProgramCode());
Assert.assertThat(DateUtil.cutTimeStamp(new DateTime(earliestDate)), is(DateUtil.cutTimeStamp(new DateTime(expectedDate))));
}
@Test
public void shouldGetFirstMovement() throws Exception {
StockCard stockCard = new StockCard();
stockRepository.createOrUpdate(stockCard);
StockCard stockCard2 = new StockCard();
stockRepository.createOrUpdate(stockCard2);
createMovementItem(ISSUE, 100, stockCard, new DateTime("2017-01-01").toDate(), new DateTime("2017-01-01").toDate(), false);
createMovementItem(ISSUE, 100, stockCard2, new DateTime("2016-01-01").toDate(), new DateTime("2016-01-01").toDate(), false);
createMovementItem(ISSUE, 100, stockCard2, new DateTime("2018-03-02").toDate(), new DateTime("2018-03-02").toDate(), false);
StockMovementItem stockMovementItem = stockMovementRepository.getFirstStockMovement();
assertEquals(stockCard2.getStockMovementItemsWrapper().get(0), stockMovementItem);
}
@Test
public void shouldBatchUpdateStockMovements() throws LMISException, ParseException {
StockCard stockCard = saveStockCardWithOneMovement(stockRepository);
StockMovementItem stockMovementItem = new StockMovementItem();
stockMovementItem.setMovementQuantity(100);
stockMovementItem.setMovementType(MovementReasonManager.MovementType.POSITIVE_ADJUST);
stockMovementItem.setMovementDate(DateUtil.parseString("2016-03-11", DateUtil.DB_DATE_FORMAT));
stockMovementItem.setStockCard(stockCard);
stockMovementItem.setSynced(false);
Lot lot1 = new Lot();
lot1.setProduct(product);
lot1.setExpirationDate(DateUtil.parseString("2017-12-31", DateUtil.DB_DATE_FORMAT));
lot1.setLotNumber("AAA");
Lot lot2 = new Lot();
lot2.setProduct(product);
lot2.setExpirationDate(DateUtil.parseString("2017-12-31", DateUtil.DB_DATE_FORMAT));
lot2.setLotNumber("BBB");
Lot lot3 = new Lot();
lot3.setProduct(product);
lot3.setExpirationDate(DateUtil.parseString("2017-12-31", DateUtil.DB_DATE_FORMAT));
lot3.setLotNumber("CCC");
LotMovementItem lotMovementItem = new LotMovementItemBuilder()
.setStockMovementItem(stockMovementItem)
.setLot(lot1)
.setMovementQuantity(2L).build();
LotMovementItem lotMovementItem2 = new LotMovementItemBuilder()
.setStockMovementItem(stockMovementItem)
.setLot(lot2)
.setMovementQuantity(3L).build();
LotMovementItem lotMovementItem3 = new LotMovementItemBuilder()
.setStockMovementItem(stockMovementItem)
.setLot(lot3)
.setMovementQuantity(5L).build();
stockMovementItem.setLotMovementItemListWrapper(Lists.newArrayList(lotMovementItem, lotMovementItem2, lotMovementItem3));
stockMovementItem.setStockOnHand(stockCard.getStockOnHand() + 100);
stockCard.setStockOnHand(stockMovementItem.getStockOnHand());
stockMovementRepository.batchCreateOrUpdateStockMovementsAndLotInfo(Lists.newArrayList(stockMovementItem));
stockRepository.refresh(stockCard);
StockMovementItem stockMovementItem1 = stockCard.getStockMovementItemsWrapper().get(1);
stockMovementItem1.getLotMovementItemListWrapper();
stockMovementItem1.setForeignLotMovementItems(null);
assertEquals(3, stockMovementItem.getLotMovementItemListWrapper().size());
assertEquals(stockMovementItem.getStockOnHand(), stockMovementItem1.getStockOnHand());
assertEquals(stockMovementItem.getMovementDate(), stockMovementItem1.getMovementDate());
stockMovementItem.setSynced(true);
stockMovementRepository.batchCreateOrUpdateStockMovementsAndLotInfo(Lists.newArrayList(stockMovementItem));
stockRepository.refresh(stockCard);
stockCard.setStockMovementItemsWrapper(null);
assertTrue(stockCard.getStockMovementItemsWrapper().get(1).isSynced());
}
}