/*
* 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.pod.service;
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.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.openlmis.core.exception.DataException;
import org.openlmis.core.service.ProductService;
import org.openlmis.db.categories.UnitTests;
import org.openlmis.fulfillment.shared.FulfillmentPermissionService;
import org.openlmis.order.domain.Order;
import org.openlmis.order.domain.OrderStatus;
import org.openlmis.order.service.OrderService;
import org.openlmis.pod.domain.OrderPOD;
import org.openlmis.pod.repository.PODRepository;
import org.openlmis.rnr.builder.RequisitionBuilder;
import org.openlmis.rnr.domain.Rnr;
import org.openlmis.rnr.service.RequisitionService;
import org.openlmis.shipment.domain.ShipmentLineItem;
import org.openlmis.shipment.service.ShipmentService;
import java.text.ParseException;
import java.util.List;
import static com.natpryce.makeiteasy.MakeItEasy.a;
import static com.natpryce.makeiteasy.MakeItEasy.make;
import static java.util.Arrays.asList;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;
import static org.openlmis.core.domain.RightName.MANAGE_POD;
import static org.openlmis.order.domain.OrderStatus.*;
@Category(UnitTests.class)
@RunWith(MockitoJUnitRunner.class)
public class PODServiceTest {
@Mock
private PODRepository repository;
@Mock
private OrderService orderService;
@Mock
private ProductService productService;
@Mock
private RequisitionService requisitionService;
@Mock
private ShipmentService shipmentService;
@Mock
private FulfillmentPermissionService fulfillmentPermissionService;
@InjectMocks
private PODService podService;
@Rule
public ExpectedException expectedException = ExpectedException.none();
private Long podId;
private Long orderId;
private Long userId;
private String orderNumber;
private OrderPOD orderPod;
@Before
public void setUp() throws Exception {
podService = spy(podService);
podId = 1L;
orderId = 2L;
userId = 3L;
orderPod = new OrderPOD(podId);
orderPod.setOrderId(orderId);
orderPod.setCreatedBy(userId);
orderNumber = "OYELL_FVR00000123R";
}
@Test
public void shouldCreatePODFromPackedOrder() throws Exception {
long orderId = 4L;
OrderPOD orderPOD = new OrderPOD(orderId, orderNumber, 8L);
OrderPOD spyOrderPOD = spy(orderPOD);
doNothing().when(podService).checkPermissions(spyOrderPOD);
when(orderService.hasStatus(orderNumber, PACKED)).thenReturn(true);
List<ShipmentLineItem> shipmentLineItems = asList(mock(ShipmentLineItem.class));
when(shipmentService.getLineItems(orderId)).thenReturn(shipmentLineItems);
Rnr requisition = make(a(RequisitionBuilder.defaultRequisition));
when(requisitionService.getFullRequisitionById(orderId)).thenReturn(requisition);
doNothing().when(spyOrderPOD).fillPOD(requisition);
doNothing().when(spyOrderPOD).fillPODLineItems(shipmentLineItems);
when(repository.insert(spyOrderPOD)).thenReturn(spyOrderPOD);
OrderPOD pod = podService.createPOD(spyOrderPOD);
verify(podService).checkPermissions(spyOrderPOD);
verify(spyOrderPOD).fillPOD(requisition);
verify(spyOrderPOD).fillPODLineItems(shipmentLineItems);
assertThat(pod, is(spyOrderPOD));
}
@Test
public void shouldCreatePODFromReleasedOrder() throws Exception {
long orderId = 6L;
OrderPOD orderPOD = new OrderPOD(orderId, orderNumber, 8L);
OrderPOD spyOrderPOD = spy(orderPOD);
doNothing().when(podService).checkPermissions(spyOrderPOD);
when(orderService.hasStatus(orderNumber, RELEASED, READY_TO_PACK, TRANSFER_FAILED)).thenReturn(true);
Rnr requisition = make(a(RequisitionBuilder.defaultRequisition));
when(requisitionService.getFullRequisitionById(orderId)).thenReturn(requisition);
doNothing().when(spyOrderPOD).fillPOD(requisition);
when(repository.insert(spyOrderPOD)).thenReturn(spyOrderPOD);
OrderPOD pod = podService.createPOD(spyOrderPOD);
verify(spyOrderPOD).fillPOD(requisition);
verify(spyOrderPOD).fillPODLineItems(requisition.getAllLineItems());
verify(podService).checkPermissions(spyOrderPOD);
verify(repository).insert(spyOrderPOD);
assertThat(pod, is(spyOrderPOD));
}
@Test
public void shouldGetPODByOrderId() {
Long orderId = 2l;
OrderPOD expectedOrderPOD = new OrderPOD();
when(repository.getPODByOrderId(orderId)).thenReturn(expectedOrderPOD);
OrderPOD savedOrderPOD = podService.getPODByOrderId(orderId);
verify(repository).getPODByOrderId(orderId);
assertThat(savedOrderPOD, is(expectedOrderPOD));
}
@Test
public void shouldGetPODWithLineItemsById() throws Exception {
podService.getPodById(podId);
verify(repository).getPOD(podId);
}
@Test
public void shouldThrowErrorIfUserDoesNotHavePermissionOnGivenWareHouse() {
orderPod.setModifiedBy(7L);
when(fulfillmentPermissionService.hasPermission(7L, orderId, MANAGE_POD)).thenReturn(false);
expectedException.expect(DataException.class);
expectedException.expectMessage("error.permission.denied");
podService.checkPermissions(orderPod);
}
@Test
public void shouldNotThrowErrorIfUserHasPermissionOnGivenWareHouse() {
orderPod.setModifiedBy(7L);
when(fulfillmentPermissionService.hasPermission(7L, orderId, MANAGE_POD)).thenReturn(true);
podService.checkPermissions(orderPod);
}
@Test
public void shouldSavePODWithModifiedLineItems() throws ParseException {
OrderPOD existingPOD = mock(OrderPOD.class);
when(repository.getPOD(podId)).thenReturn(existingPOD);
when(existingPOD.getModifiedBy()).thenReturn(userId);
when(existingPOD.getOrderId()).thenReturn(orderId);
doNothing().when(podService).checkPermissions(existingPOD);
when(repository.update(existingPOD)).thenReturn(existingPOD);
OrderPOD savedPod = podService.save(orderPod);
verify(repository).update(savedPod);
verify(existingPOD).copy(orderPod);
}
@Test
public void shouldNotSaveOrderPodIfUserDoesNotHavePermissions() throws ParseException {
OrderPOD existingPOD = mock(OrderPOD.class);
when(repository.getPOD(podId)).thenReturn(existingPOD);
when(existingPOD.getModifiedBy()).thenReturn(userId);
when(existingPOD.getOrderId()).thenReturn(orderId);
doThrow(new DataException("error.permission.denied")).when(podService).checkPermissions(existingPOD);
expectedException.expect(DataException.class);
expectedException.expectMessage("error.permission.denied");
podService.save(orderPod);
}
@Test
public void shouldNotSaveAnAlreadySubmittedPOD() throws Exception {
OrderPOD existingPOD = mock(OrderPOD.class);
when(repository.getPOD(podId)).thenReturn(existingPOD);
when(existingPOD.getModifiedBy()).thenReturn(userId);
when(existingPOD.getOrderId()).thenReturn(orderId);
when(existingPOD.getOrderNumber()).thenReturn(orderNumber);
doNothing().when(podService).checkPermissions(existingPOD);
when(orderService.hasStatus(orderNumber, RECEIVED)).thenReturn(true);
expectedException.expect(DataException.class);
expectedException.expectMessage("error.pod.already.submitted");
podService.save(orderPod);
}
@Test
public void shouldNotSubmitPODIfUserDoesNotHaveTheRight() throws Exception {
OrderPOD orderPOD = new OrderPOD();
orderPOD.setId(1234L);
when(repository.getPOD(1234L)).thenReturn(orderPOD);
doThrow(new DataException("error.permission.denied")).when(podService).checkPermissions(orderPOD);
expectedException.expect(DataException.class);
expectedException.expectMessage("error.permission.denied");
podService.submit(1234L, userId);
verify(podService).checkPermissions(orderPOD);
}
@Test
public void shouldValidatePODLineItems() throws Exception {
long podId = 1234L;
OrderPOD orderPOD = mock(OrderPOD.class);
when(orderPOD.getOrderNumber()).thenReturn(orderNumber);
when(orderService.hasStatus(orderNumber, OrderStatus.RECEIVED)).thenReturn(false);
when(repository.getPOD(podId)).thenReturn(orderPOD);
doNothing().when(podService).checkPermissions(orderPOD);
doThrow(new DataException("error.invalid.received.quantity")).when(orderPOD).validate();
expectedException.expect(DataException.class);
expectedException.expectMessage("error.invalid.received.quantity");
podService.submit(podId, userId);
}
@Test
public void shouldChangeOrderStatusWhenPODIsSubmittedSuccessfully() throws Exception {
long podId = 1234L;
OrderPOD orderPOD = mock(OrderPOD.class);
when(orderPOD.getOrderNumber()).thenReturn(orderNumber);
when(orderService.hasStatus(orderNumber, OrderStatus.RECEIVED)).thenReturn(false);
when(repository.getPOD(podId)).thenReturn(orderPOD);
doNothing().when(podService).checkPermissions(orderPOD);
doNothing().when(orderPOD).validate();
podService.submit(podId, userId);
Order order = new Order(3L, RECEIVED);
order.setOrderNumber(orderNumber);
verify(orderService).updateOrderStatus(order);
}
@Test
public void shouldReturnSubmittedPOD() throws Exception {
long podId = 1234L;
OrderPOD orderPOD = mock(OrderPOD.class);
when(orderPOD.getOrderNumber()).thenReturn(orderNumber);
when(orderService.hasStatus(orderNumber, OrderStatus.RECEIVED)).thenReturn(false);
when(repository.getPOD(podId)).thenReturn(orderPOD);
doNothing().when(podService).checkPermissions(orderPOD);
doNothing().when(orderPOD).validate();
when(repository.update(orderPOD)).thenReturn(orderPOD);
OrderPOD submittedPOD = podService.submit(podId, userId);
assertThat(submittedPOD, is(orderPOD));
}
@Test
public void shouldNotSubmitAlreadySubmittedPOD() throws Exception {
long podId = 1234L;
long orderId = 2345L;
String orderNumber = "OYELL_FVR00000123R";
OrderPOD orderPOD = new OrderPOD();
orderPOD.setOrderId(orderId);
orderPOD.setOrderNumber(orderNumber);
when(repository.getPOD(podId)).thenReturn(orderPOD);
doNothing().when(podService).checkPermissions(orderPOD);
when(orderService.hasStatus(orderNumber, OrderStatus.RECEIVED)).thenReturn(true);
expectedException.expect(DataException.class);
expectedException.expectMessage("error.pod.already.submitted");
podService.submit(podId, 5432L);
}
}