org.openlmis.fulfillment.service.OrderServiceTest.java Source code

Java tutorial

Introduction

Here is the source code for org.openlmis.fulfillment.service.OrderServiceTest.java

Source

/*
 * This program is part of the OpenLMIS logistics management information system platform software.
 * Copyright  2017 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.fulfillment.service;

import static com.google.common.collect.Sets.newHashSet;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.UUID.randomUUID;
import static org.javers.common.collections.Sets.asSet;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anySet;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.openlmis.fulfillment.service.PermissionService.ORDERS_EDIT;
import static org.openlmis.fulfillment.service.PermissionService.ORDERS_VIEW;
import static org.openlmis.fulfillment.service.PermissionService.PODS_MANAGE;
import static org.openlmis.fulfillment.service.PermissionService.PODS_VIEW;
import static org.openlmis.fulfillment.service.PermissionService.SHIPMENTS_EDIT;
import static org.openlmis.fulfillment.service.PermissionService.SHIPMENTS_VIEW;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.util.Collections;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InOrder;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.openlmis.fulfillment.OrderDataBuilder;
import org.openlmis.fulfillment.OrderLineItemDataBuilder;
import org.openlmis.fulfillment.StatusChangeDataBuilder;
import org.openlmis.fulfillment.domain.Base36EncodedOrderNumberGenerator;
import org.openlmis.fulfillment.domain.ExternalStatus;
import org.openlmis.fulfillment.domain.FtpTransferProperties;
import org.openlmis.fulfillment.domain.Order;
import org.openlmis.fulfillment.domain.OrderLineItem;
import org.openlmis.fulfillment.domain.OrderNumberConfiguration;
import org.openlmis.fulfillment.domain.OrderStatus;
import org.openlmis.fulfillment.domain.StatusChange;
import org.openlmis.fulfillment.extension.ExtensionManager;
import org.openlmis.fulfillment.extension.point.OrderNumberGenerator;
import org.openlmis.fulfillment.repository.OrderNumberConfigurationRepository;
import org.openlmis.fulfillment.repository.OrderRepository;
import org.openlmis.fulfillment.repository.TransferPropertiesRepository;
import org.openlmis.fulfillment.service.referencedata.FacilityDto;
import org.openlmis.fulfillment.service.referencedata.FacilityReferenceDataService;
import org.openlmis.fulfillment.service.referencedata.OrderableDto;
import org.openlmis.fulfillment.service.referencedata.OrderableReferenceDataService;
import org.openlmis.fulfillment.service.referencedata.PeriodReferenceDataService;
import org.openlmis.fulfillment.service.referencedata.PermissionStrings;
import org.openlmis.fulfillment.service.referencedata.ProcessingPeriodDto;
import org.openlmis.fulfillment.service.referencedata.ProgramDto;
import org.openlmis.fulfillment.service.referencedata.ProgramReferenceDataService;
import org.openlmis.fulfillment.service.referencedata.UserDto;
import org.openlmis.fulfillment.service.referencedata.UserReferenceDataService;
import org.openlmis.fulfillment.testutils.FacilityDataBuilder;
import org.openlmis.fulfillment.testutils.OrderableDataBuilder;
import org.openlmis.fulfillment.testutils.ProcessingPeriodDataBuilder;
import org.openlmis.fulfillment.testutils.ProgramDataBuilder;
import org.openlmis.fulfillment.testutils.UserDataBuilder;
import org.openlmis.fulfillment.util.AuthenticationHelper;
import org.openlmis.fulfillment.util.DateHelper;
import org.openlmis.fulfillment.web.util.OrderDto;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;

@SuppressWarnings({ "PMD.TooManyMethods" })
@RunWith(MockitoJUnitRunner.class)
public class OrderServiceTest {

    @Rule
    public ExpectedException exception = ExpectedException.none();

    @Mock
    private OrderRepository orderRepository;

    @Mock
    private OrderNumberConfigurationRepository orderNumberConfigurationRepository;

    @Mock
    private FacilityReferenceDataService facilityReferenceDataService;

    @Mock
    private ProgramReferenceDataService programReferenceDataService;

    @Mock
    private PeriodReferenceDataService periodReferenceDataService;

    @Mock
    private OrderableReferenceDataService orderableReferenceDataService;

    @Mock
    private UserReferenceDataService userReferenceDataService;

    @Mock
    private TransferPropertiesRepository transferPropertiesRepository;

    @Mock
    private FulfillmentNotificationService notificationService;

    @Mock
    private OrderStorage orderStorage;

    @Mock
    private OrderSender orderSender;

    @Mock
    private DateHelper dateHelper;

    @Mock
    private ExtensionManager extensionManager;

    @Mock
    private PermissionService permissionService;

    @Mock
    private AuthenticationHelper authenticationHelper;

    @InjectMocks
    private ExporterBuilder exporter;

    @InjectMocks
    private OrderService orderService;

    @Captor
    private ArgumentCaptor<Order> orderCaptor;

    private ProgramDto program;
    private FacilityDto facility;
    private ProcessingPeriodDto period1;
    private ProcessingPeriodDto period2;
    private OrderableDto orderable;
    private OrderNumberConfiguration orderNumberConfiguration;
    private Order order;
    private UserDto userDto;
    private FtpTransferProperties properties;
    private LocalDate startDate;
    private LocalDate endDate;

    @Before
    public void setUp() {
        generateTestData();
        mockResponses();
    }

    @Test
    public void shouldCreateRegularOrder() throws Exception {
        OrderDto dto = OrderDto.newInstance(order, exporter);
        dto.setId(null);

        Order created = orderService.createOrder(dto, userDto.getId());

        // then
        validateCreatedOrder(created, order);

        verify(orderRepository).save(orderCaptor.capture());
        verify(orderStorage).store(any(Order.class));
        verify(orderSender).send(any(Order.class));
        verify(orderStorage).delete(any(Order.class));

        assertEquals(OrderStatus.IN_ROUTE, orderCaptor.getValue().getStatus());

        verify(notificationService).sendOrderCreatedNotification(eq(created));
    }

    @Test
    public void shouldCreateRegularOrderIfFacilityNotSupportProgram() throws Exception {
        facility.setSupportedPrograms(emptyList());

        OrderDto dto = OrderDto.newInstance(order, exporter);
        dto.setId(null);

        order.setStatus(OrderStatus.ORDERED);

        Order created = orderService.createOrder(dto, userDto.getId());

        // then
        validateCreatedOrder(created, order);

        verify(orderRepository).save(orderCaptor.capture());
        verify(orderStorage).store(any(Order.class));
        verify(orderSender).send(any(Order.class));
        verify(orderStorage).delete(any(Order.class));

        assertEquals(OrderStatus.IN_ROUTE, orderCaptor.getValue().getStatus());

        verify(notificationService).sendOrderCreatedNotification(eq(created));
    }

    @Test
    public void shouldCreateOrderForFulfill() throws Exception {
        program.setSupportLocallyFulfilled(true);

        OrderDto dto = OrderDto.newInstance(order, exporter);
        dto.setId(null);

        order.setStatus(OrderStatus.ORDERED);

        Order created = orderService.createOrder(dto, userDto.getId());

        // then
        validateCreatedOrder(created, order);

        verify(orderRepository).save(orderCaptor.capture());
        verify(orderStorage).store(any(Order.class));
        verify(orderSender).send(any(Order.class));
        verify(orderStorage).delete(any(Order.class));

        assertEquals(OrderStatus.ORDERED, orderCaptor.getValue().getStatus());

        verify(notificationService).sendOrderCreatedNotification(eq(created));
    }

    @Test
    public void shouldSaveOrder() throws Exception {
        Order created = orderService.save(order);

        // then
        validateCreatedOrder(created, order);
        assertEquals(OrderStatus.IN_ROUTE, created.getStatus());

        InOrder inOrder = inOrder(orderRepository, orderStorage, orderSender);
        inOrder.verify(orderRepository).save(order);
        inOrder.verify(orderStorage).store(order);
        inOrder.verify(orderSender).send(order);
        inOrder.verify(orderStorage).delete(order);

        verify(notificationService).sendOrderCreatedNotification(eq(created));
    }

    @Test
    public void shouldSaveOrderAndNotDeleteFileIfFtpSendFailure() throws Exception {
        StatusChange statusChange = new StatusChange();
        statusChange.setStatus(ExternalStatus.APPROVED);
        statusChange.setCreatedDate(ZonedDateTime.now());
        statusChange.setAuthorId(randomUUID());
        order.setStatusChanges(Lists.newArrayList(statusChange));

        when(orderSender.send(order)).thenReturn(false);
        Order created = orderService.save(order);

        // then
        validateCreatedOrder(created, order);
        assertEquals(OrderStatus.TRANSFER_FAILED, created.getStatus());

        InOrder inOrder = inOrder(orderRepository, orderStorage, orderSender);
        inOrder.verify(orderRepository).save(order);
        inOrder.verify(orderStorage).store(order);
        inOrder.verify(orderSender).send(order);
        inOrder.verify(orderStorage, never()).delete(order);
    }

    @Test
    public void shouldFindOrderIfMatchedSupplyingAndRequestingFacilitiesAndProgram() {
        Order order = generateOrder();
        Pageable pageable = new PageRequest(0, 10);
        UserDto user = new UserDataBuilder().build();
        PermissionStrings.Handler handler = mock(PermissionStrings.Handler.class);
        when(handler.getFacilityIds(ORDERS_EDIT, ORDERS_VIEW, SHIPMENTS_EDIT, SHIPMENTS_VIEW))
                .thenReturn(newHashSet(order.getSupplyingFacilityId()));
        when(handler.getFacilityIds(PODS_MANAGE, PODS_VIEW))
                .thenReturn(newHashSet(order.getRequestingFacilityId()));

        when(permissionService.getPermissionStrings(user.getId())).thenReturn(handler);

        OrderSearchParams params = new OrderSearchParams(order.getSupplyingFacilityId(),
                order.getRequestingFacilityId(), order.getProgramId(), order.getProcessingPeriodId(),
                Sets.newHashSet(order.getStatus().toString()), null, null);
        when(orderRepository.searchOrders(params, asSet(order.getProcessingPeriodId()), pageable,
                newHashSet(order.getSupplyingFacilityId()), newHashSet(order.getRequestingFacilityId())))
                        .thenReturn(new PageImpl<>(Collections.singletonList(order), pageable, 1));

        when(authenticationHelper.getCurrentUser()).thenReturn(user);

        Page<Order> receivedOrders = orderService.searchOrders(params, pageable);

        assertEquals(1, receivedOrders.getContent().size());
        assertEquals(receivedOrders.getContent().get(0).getSupplyingFacilityId(), order.getSupplyingFacilityId());
        assertEquals(receivedOrders.getContent().get(0).getRequestingFacilityId(), order.getRequestingFacilityId());
        assertEquals(receivedOrders.getContent().get(0).getProgramId(), order.getProgramId());

        verify(orderRepository, atLeastOnce()).searchOrders(anyObject(), anyObject(), anyObject(), anySet(),
                anySet());
    }

    @Test
    public void shouldNotCheckPermissionWhenCrossServiceRequest() {
        Order order = generateOrder();
        Pageable pageable = new PageRequest(0, 10);

        OrderSearchParams params = new OrderSearchParams(order.getSupplyingFacilityId(),
                order.getRequestingFacilityId(), order.getProgramId(), order.getProcessingPeriodId(),
                Sets.newHashSet(order.getStatus().toString()), null, null);
        when(orderRepository.searchOrders(params, asSet(order.getProcessingPeriodId()), pageable))
                .thenReturn(new PageImpl<>(Collections.singletonList(order), pageable, 1));

        when(authenticationHelper.getCurrentUser()).thenReturn(null);

        Page<Order> receivedOrders = orderService.searchOrders(params, pageable);

        assertEquals(receivedOrders.getContent().get(0).getSupplyingFacilityId(), order.getSupplyingFacilityId());
        assertEquals(receivedOrders.getContent().get(0).getRequestingFacilityId(), order.getRequestingFacilityId());
        assertEquals(receivedOrders.getContent().get(0).getProgramId(), order.getProgramId());

        verify(orderRepository, atLeastOnce()).searchOrders(anyObject(), anyObject(), anyObject());

        verify(permissionService, never()).getPermissionStrings(anyObject());
    }

    @Test
    public void shouldSearchByStartDateAndEndDate() {
        Order order = generateOrder();
        Pageable pageable = new PageRequest(0, 10);

        OrderSearchParams params = new OrderSearchParams(order.getSupplyingFacilityId(),
                order.getRequestingFacilityId(), order.getProgramId(), null,
                Sets.newHashSet(order.getStatus().toString()), startDate, endDate);
        when(orderRepository.searchOrders(params, asSet(period1.getId(), period2.getId()), pageable))
                .thenReturn(new PageImpl<>(Collections.singletonList(order), pageable, 1));

        when(authenticationHelper.getCurrentUser()).thenReturn(null);

        Page<Order> receivedOrders = orderService.searchOrders(params, pageable);

        assertEquals(1, receivedOrders.getContent().size());
        assertEquals(order, receivedOrders.getContent().get(0));

        verify(orderRepository, atLeastOnce()).searchOrders(anyObject(), anyObject(), anyObject());
    }

    @Test
    public void shouldReturnEmptyPageIfFilteredPeriodsAndGivenPeriodIdDoesNotMatch() {
        Order order = generateOrder();
        Pageable pageable = new PageRequest(0, 10);

        when(authenticationHelper.getCurrentUser()).thenReturn(null);

        OrderSearchParams params = new OrderSearchParams(order.getSupplyingFacilityId(),
                order.getRequestingFacilityId(), order.getProgramId(), order.getProcessingPeriodId(),
                Sets.newHashSet(order.getStatus().toString()), startDate, endDate);
        Page<Order> receivedOrders = orderService.searchOrders(params, pageable);

        assertEquals(0, receivedOrders.getContent().size());
        verify(orderRepository, never()).searchOrders(anyObject(), anyObject(), anyObject(), anyObject(),
                anyObject());
    }

    @Test
    public void shouldReturnEmptyPageIfPeriodsSearchReturnsEmptyList() {
        Order order = generateOrder();
        Pageable pageable = new PageRequest(0, 10);

        when(authenticationHelper.getCurrentUser()).thenReturn(null);

        when(periodReferenceDataService.search(startDate, endDate)).thenReturn(emptyList());

        OrderSearchParams params = new OrderSearchParams(order.getSupplyingFacilityId(),
                order.getRequestingFacilityId(), order.getProgramId(), null,
                Sets.newHashSet(order.getStatus().toString()), startDate, endDate);
        Page<Order> receivedOrders = orderService.searchOrders(params, pageable);

        assertEquals(0, receivedOrders.getContent().size());
        verify(orderRepository, never()).searchOrders(anyObject(), anyObject(), anyObject(), anyObject(),
                anyObject());
    }

    @Test
    public void shouldSearchByStartDateAndEndDateAndPeriodId() {
        Order order = generateOrder();
        Pageable pageable = new PageRequest(0, 10);

        OrderSearchParams params = new OrderSearchParams(order.getSupplyingFacilityId(),
                order.getRequestingFacilityId(), order.getProgramId(), period1.getId(),
                Sets.newHashSet(order.getStatus().toString()), startDate, endDate);
        when(orderRepository.searchOrders(params, asSet(period1.getId()), pageable))
                .thenReturn(new PageImpl<>(Collections.singletonList(order), pageable, 1));

        when(authenticationHelper.getCurrentUser()).thenReturn(null);

        Page<Order> receivedOrders = orderService.searchOrders(params, pageable);

        assertEquals(1, receivedOrders.getContent().size());
        assertEquals(order, receivedOrders.getContent().get(0));

        verify(orderRepository, atLeastOnce()).searchOrders(anyObject(), anyObject(), anyObject());
    }

    private Order generateOrder() {
        return new OrderDataBuilder().withOrderedStatus().build();
    }

    private void validateCreatedOrder(Order actual, Order expected) {
        assertEquals(actual.getExternalId(), expected.getExternalId());
        assertEquals(actual.getReceivingFacilityId(), expected.getReceivingFacilityId());
        assertEquals(actual.getRequestingFacilityId(), expected.getRequestingFacilityId());
        assertEquals(actual.getProgramId(), expected.getProgramId());
        assertEquals(actual.getSupplyingFacilityId(), expected.getSupplyingFacilityId());
        assertEquals(1, actual.getOrderLineItems().size());
        assertEquals(1, expected.getOrderLineItems().size());

        OrderLineItem actualLineItem = actual.getOrderLineItems().iterator().next();
        OrderLineItem expectedLineItem = expected.getOrderLineItems().iterator().next();

        assertEquals(expectedLineItem.getOrderedQuantity(), actualLineItem.getOrderedQuantity());
        assertEquals(expectedLineItem.getOrderableId(), actualLineItem.getOrderableId());

        StatusChange actualStatusChange = actual.getStatusChanges().iterator().next();
        StatusChange expectedStatusChange = expected.getStatusChanges().iterator().next();

        assertEquals(expectedStatusChange.getStatus(), actualStatusChange.getStatus());
        assertEquals(expectedStatusChange.getCreatedDate(), actualStatusChange.getCreatedDate());
        assertEquals(expectedStatusChange.getAuthorId(), actualStatusChange.getAuthorId());
    }

    private void generateTestData() {
        program = new ProgramDataBuilder().build();
        facility = new FacilityDataBuilder().withSupportedPrograms(Collections.singletonList(program)).build();
        period1 = new ProcessingPeriodDataBuilder().build();
        period2 = new ProcessingPeriodDataBuilder().build();

        orderNumberConfiguration = new OrderNumberConfiguration("prefix", true, true, true);

        userDto = new UserDataBuilder().build();

        orderable = new OrderableDataBuilder().build();
        OrderLineItem orderLineItem = new OrderLineItemDataBuilder().withOrderedQuantity(100L)
                .withOrderableId(orderable.getId()).build();
        StatusChange statusChange = new StatusChangeDataBuilder().build();
        order = new OrderDataBuilder().withQuotedCost(BigDecimal.ZERO).withProgramId(program.getId())
                .withCreatedById(userDto.getId()).withEmergencyFlag().withStatus(OrderStatus.IN_ROUTE)
                .withStatusChanges(statusChange).withSupplyingFacilityId(facility.getId())
                .withProcessingPeriodId(period1.getId()).withLineItems(orderLineItem).build();

        userDto = new UserDataBuilder().build();

        properties = new FtpTransferProperties();

        startDate = LocalDate.now();
        endDate = startDate.plusMonths(1);
    }

    private void mockResponses() {
        when(programReferenceDataService.findOne(program.getId())).thenReturn(program);
        when(facilityReferenceDataService.findOne(facility.getId())).thenReturn(facility);
        when(periodReferenceDataService.findOne(period1.getId())).thenReturn(period1);
        when(orderableReferenceDataService.findByIds(any())).thenReturn(Collections.singletonList(orderable));

        when(userReferenceDataService.findOne(any())).thenReturn(userDto);

        when(orderNumberConfigurationRepository.findAll())
                .thenReturn(Collections.singletonList(orderNumberConfiguration));

        when(extensionManager.getExtension(OrderNumberGenerator.POINT_ID, OrderNumberGenerator.class))
                .thenReturn(new Base36EncodedOrderNumberGenerator());

        when(transferPropertiesRepository.findFirstByFacilityId(any())).thenReturn(properties);

        when(orderRepository.save(any(Order.class))).thenReturn(order);
        when(orderSender.send(order)).thenReturn(true);

        when(dateHelper.getCurrentDateTimeWithSystemZone()).thenReturn(ZonedDateTime.now());

        when(periodReferenceDataService.search(startDate, endDate)).thenReturn(asList(period1, period2));
    }
}