package cz.coffei.foodo.data.dao; import com.sun.corba.se.spi.protocol.InitialServerRequestDispatcher; import cz.coffei.foodo.data.entities.*; import cz.coffei.foodo.data.enums.OrderItemType; import cz.coffei.foodo.data.enums.OrderStatus; import cz.coffei.foodo.data.exceptions.EntityInvalidException; import cz.coffei.foodo.data.mail.MailSender; import javax.ejb.Stateless; import javax.inject.Inject; import javax.mail.MessagingException; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import java.sql.Timestamp; import java.util.*; import java.util.logging.Logger; import java.util.stream.Collectors; import java.util.stream.Stream; /** * Created by jtrantin on 26.7.15. */ @Stateless public class OrderDao { @Inject private Logger log; @Inject private EntityManager em; @Inject private MenuDao menuDao; @Inject private IngredientGroupDao groupDao; @Inject private IngredientDao ingredientDao; @Inject private PriceConstantDao priceConstantDao; public Order createOrder(Order order) throws EntityInvalidException { PriceConstant takeawayPrice = priceConstantDao.getPriceConstant("takeaway", 0); Integer price = 0; for(OrderItem orderItem : order.getOrderItems()) { orderItem.setOrder(order); if(orderItem.getType()== OrderItemType.MENU) { if(orderItem.getMenu()==null || orderItem.getMenu().getId()==null) throw new EntityInvalidException("type MENU specified but no valid menu present"); MenuItem menu = menuDao.getMenuItem(orderItem.getMenu().getId()); price += menu.getPrice() * (orderItem.getTimes() != null ? orderItem.getTimes() : 1); } else { // custom salad if(orderItem.getIngredients()==null) throw new EntityInvalidException("type SALAD specified but no ingredients present"); List<Ingredient> ingredients = fetchAllIngredients(orderItem.getIngredients()); // get all required groups & check ingredients are selected properly List<IngredientGroup> requiredGroups = groupDao.getAllRequiredGroups(); for (IngredientGroup group : requiredGroups) { if(ingredients.stream().noneMatch((ingredient -> ingredient.getGroup().equals(group)))) throw new EntityInvalidException("No ingredients from group " + group.getName() + " are selected."); } // check whether groups that do not allow more ingredients are not misused List<IngredientGroup> mappedGroups = ingredients.stream().map(Ingredient::getGroup).filter(group -> !group.isAllowMore()).collect(Collectors.toList()); List<IngredientGroup> usedGroups = mappedGroups.stream().distinct().collect(Collectors.toList()); for(IngredientGroup group : usedGroups) { if(mappedGroups.stream().filter(filterGroup -> filterGroup.equals(group)).count() > 1) throw new EntityInvalidException("More ingredients from group " + group.getName() + " selected even though it's forbidden"); } for (Ingredient ingredient : ingredients) { if (ingredient.getPrice() != null) { price += ingredient.getPrice() * (orderItem.getTimes() != null ? orderItem.getTimes() : 1); } else { price += ingredient.getGroup().getPrice() * (orderItem.getTimes() != null ? orderItem.getTimes() : 1); } } } } if (order.isTakeaway()) { int portionCount = order.getOrderItems().stream().mapToInt(orderItem -> orderItem.getTimes() != null ? orderItem.getTimes() : 1).sum(); price += portionCount * takeawayPrice.getValue(); } order.setStatus(OrderStatus.NEW); int offset = TimeZone.getDefault().getOffset(System.currentTimeMillis()); order.setCreated(new Timestamp(System.currentTimeMillis() - offset)); order.setTotalPrice(price); em.persist(order); return order; } public void updateOrder(Order order) throws EntityInvalidException { if(order.getId()==null) throw new EntityInvalidException("entity has no id"); em.merge(order); } public List<Order> getAllOrders() { CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Order> query = cb.createQuery(Order.class); Root<Order> root = query.from(Order.class); query.select(root); TypedQuery<Order> typedQuery = em.createQuery(query); return typedQuery.getResultList(); } public Order getOrderById(Long id) { if(id==null) throw new IllegalArgumentException("entity has no id"); CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Order> query = cb.createQuery(Order.class); Root<Order> root = query.from(Order.class); query.select(root); query.where(cb.equal(root.get(Order_.id), id)); TypedQuery<Order> typedQuery = em.createQuery(query); Order order = typedQuery.getSingleResult(); return order; } public List<Order> getOrdersByStatuses(List<OrderStatus> statuses) { if(statuses == null) throw new NullPointerException("statuses"); if(statuses.isEmpty()) return Collections.emptyList(); CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Order> query = cb.createQuery(Order.class); Root<Order> root = query.from(Order.class); query.select(root); List<Predicate> statusPredicates = statuses.stream().map((status) -> cb.equal(root.get(Order_.status), status)).collect(Collectors.toList()); query.where(cb.or(statusPredicates.toArray(new Predicate[0]))); TypedQuery<Order> typedQuery = em.createQuery(query); return typedQuery.getResultList(); } public void deleteOrder(Order order) throws EntityInvalidException { if(order.getId()==null) throw new EntityInvalidException("entity has no id"); if (!em.contains(order)) { order = em.merge(order); } em.remove(order); } private List<Ingredient> fetchAllIngredients(List<Ingredient> ingredients) { List<Ingredient> result = ingredients.stream().mapToLong((Ingredient::getId)) .mapToObj(ingredientDao::getIngredientById) .collect(Collectors.toList()); return result; } }