package controllers;
import be.objectify.deadbolt.java.actions.Group;
import be.objectify.deadbolt.java.actions.Restrict;
import com.fasterxml.jackson.databind.ObjectMapper;
import dao.DataAccessException;
import models.DaoManager;
import models.dto.*;
import models.entities.Contact;
import models.entities.Order;
import models.entities.OrderStateChange;
import play.Logger;
import play.db.jpa.Transactional;
import play.mvc.Controller;
import play.mvc.Result;
import utils.Utilities;
import java.io.IOException;
import java.util.Calendar;
import java.util.List;
import static play.libs.Json.toJson;
/**
* Created by NotePad.by on 03.09.2014.
*/
@Restrict({@Group("manager"), @Group("supervisor"), @Group("executor"), @Group("delivery-manager")})
public class OrderController extends Controller {
@Transactional
public static Result getOrderStateChanges(int id) {
try {
Order order = DaoManager.getOrderDao().findById(id);
if (order == null) {
return notFound(Utilities.getJsonErrorNode("can't find order with id " + id));
}
OrderStateChangeListDto dto = OrderStateChangeListDto.createFrom(order.getChanges());
return ok(toJson(dto));
} catch (DataAccessException e) {
Logger.error("can't find order with id " + id);
return notFound("can't find order with id " + id);
}
}
@Transactional
public static Result getAllByContactId(int pageNumber, int pageSize, int id) {
try {
Contact contact = DaoManager.getContactDao().findById(id);
if (contact == null) {
return notFound("Can't find contact with id " + id);
}
List<Order> orders = DaoManager.getOrderDao().getAllByContact(contact, pageNumber - 1, pageSize);
if (orders == null) {
return notFound("Can't find contactOrders for this client with id " + id);
}
OrderListDto dto = OrderListDto.createFrom(orders, 1);
return ok(toJson(dto));
} catch (DataAccessException e) {
Logger.error("Can't get contactOrders for client with id " + id);
return notFound("Can't find contactOrders for this client with id " + id);
}
}
@Transactional
@Restrict({@Group("manager"), @Group("supervisor")})
public static Result add() {
try {
String requestBody = request().body().asJson().toString();
Logger.debug("Add request body: " + requestBody);
OrderDto dto = new ObjectMapper().readValue(requestBody, OrderDto.class);
Order order = new Order();
dto.mapBack(order);
order.setState(DaoManager.getOrderStateDao().findByName("new"));
order.setCreatedOn(Calendar.getInstance().getTime());
DaoManager.getOrderDao().persist(order);
OrderStateChange stateChange = new OrderStateChange();
stateChange.setNewState(DaoManager.getOrderStateDao().findByName("new"));
stateChange.setPerformedOn(Calendar.getInstance().getTime());
stateChange.setChanger(SecurityController.getUser());
stateChange.setAlteredOrder(order);
DaoManager.getOrderStateChangeDao().persist(stateChange);
} catch (IOException e) {
Logger.error("failed to parse new order json", e);
return badRequest(Utilities.getJsonErrorNode("failed to parse new order json"));
} catch (DataAccessException e) {
Logger.error("failed to save new order", e);
return badRequest(Utilities.getJsonErrorNode("failed to save new order"));
}
return ok();
}
@Transactional
@Restrict({@Group("manager"), @Group("supervisor")})
public static Result update(int id) {
try {
String requestBody = request().body().asJson().toString();
Order order = DaoManager.getOrderDao().findById(id);
if (order == null) {
return notFound(Utilities.getJsonErrorNode("can't find order with id " + id));
}
Logger.debug("Edit request body: " + requestBody);
OrderDto dto = new ObjectMapper().readValue(requestBody, OrderDto.class);
dto.mapBack(order);
DaoManager.getOrderDao().persist(order);
} catch (DataAccessException e) {
Logger.error("failed to update order", e);
return badRequest(Utilities.getJsonErrorNode("failed to update order"));
} catch (IOException e) {
Logger.error("failed to parse update order json", e);
return badRequest(Utilities.getJsonErrorNode("failed to parse update order json"));
}
return ok("save update order");
}
@Transactional
public static Result getOrder(int id) {
try {
Order order = DaoManager.getOrderDao().findById(id);
if (order == null) {
return notFound(Utilities.getJsonErrorNode("can't find order with id " + id));
}
if (!SecurityController.hasAccessToOrder(order)) {
return forbidden("not allowed to view the order " + id);
}
String currentUserRole = SecurityController.getUser().getRole().getName();
String orderState = order.getState().getName();
if (OrderStateController.roleAccessibleStates.get(currentUserRole).contains(orderState)) {
OrderDto dto = OrderDto.createFrom(order);
return ok(toJson(dto));
}
return forbidden("not allowed to view the order " + id);
} catch (DataAccessException e) {
Logger.error("can't find order with id " + id);
return notFound("can't find order with id " + id);
}
}
@Transactional
public static Result searchOrders(Integer pageNumber, Integer pageSize, String query) {
try {
if (pageNumber == null || pageSize == null || pageNumber <= 0 || pageNumber <= 0) {
return badRequest(Utilities.getJsonErrorNode("Bad page number or size"));
}
OrderSearchDto searchDto = new ObjectMapper().readValue(query, OrderSearchDto.class);
String currentUserRole = SecurityController.getUser().getRole().getName();
Integer currentUserId = SecurityController.getUser().getId();
if (currentUserRole.equalsIgnoreCase("manager")) {
searchDto.setCreatorId(currentUserId);
} else if (currentUserRole.equalsIgnoreCase("executor")) {
searchDto.setExecutorId(currentUserId);
} else if (currentUserRole.equalsIgnoreCase("delivery-manager")) {
searchDto.setDeliveryManagerId(currentUserId);
}
if (searchDto.getState() != null && searchDto.getState().equalsIgnoreCase("default")) {
searchDto.setState(OrderStateController.roleAccessibleStates.get(currentUserRole).get(0));
}
OrderListExpandedDTO ordersDto = performSearch(pageNumber, pageSize, searchDto);
if (searchDto.getState() != null) {
ordersDto.setAvailableStates(OrderStateController.roleAccessibleStates.get(currentUserRole));
ordersDto.setState(searchDto.getState());
}
return ok(toJson(ordersDto));
} catch (DataAccessException e) {
Logger.error("Can't get " + query + " orders");
return notFound("Can't find " + query + " orders");
} catch (IOException e) {
Logger.error("Failed to parse search query " + query);
return notFound("Failed to parse search query " + query);
}
}
private static OrderListExpandedDTO performSearch(Integer pageNumber, Integer pageSize, OrderSearchDto searchDto) throws DataAccessException {
List<Order> orders = DaoManager.getOrderDao().search(pageNumber - 1, pageSize, searchDto);
if (orders == null) {
throw new DataAccessException();
}
Integer totalOrders = DaoManager.getOrderDao().searchResultsCount(searchDto);
Integer totalPages = Double.valueOf(Math.ceil((double) totalOrders / pageSize)).intValue();
OrderListExpandedDTO ordersDto = OrderListExpandedDTO.createFrom(orders, totalPages);
return ordersDto;
}
@Transactional
public static Result updateOrderState(int id) {
try {
String requestBody = request().body().asJson().toString();
Order order = DaoManager.getOrderDao().findById(id);
if (order == null) {
return notFound(Utilities.getJsonErrorNode("can't find order with id " + id));
}
Logger.debug("Update order state request body: " + requestBody);
OrderStateChangeDto dto = new ObjectMapper().readValue(requestBody, OrderStateChangeDto.class);
OrderStateChange stateChange = new OrderStateChange();
dto.mapBack(stateChange);
stateChange.setPerformedOn(Calendar.getInstance().getTime());
stateChange.setChanger(SecurityController.getUser());
stateChange.setAlteredOrder(order);
order.setState(stateChange.getNewState());
DaoManager.getOrderStateChangeDao().persist(stateChange);
} catch (DataAccessException e) {
Logger.error("failed to update order state", e);
return badRequest(Utilities.getJsonErrorNode("failed to update order state"));
} catch (IOException e) {
Logger.error("failed to parse update order json", e);
return badRequest(Utilities.getJsonErrorNode("failed to parse update order json"));
}
return ok("changed order " + id + " state");
}
}