ProductBean.java 10.6 KB
package fi.codecrew.moya.beans;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fi.codecrew.moya.bortal.views.BillSummary;
import fi.codecrew.moya.enums.apps.ShopPermission;
import fi.codecrew.moya.facade.AccountEventFacade;
import fi.codecrew.moya.facade.BillLineFacade;
import fi.codecrew.moya.facade.DiscountFacade;
import fi.codecrew.moya.facade.EventUserFacade;
import fi.codecrew.moya.facade.InventoryEventFacade;
import fi.codecrew.moya.facade.ProductFacade;
import fi.codecrew.moya.facade.UserFacade;
import fi.codecrew.moya.model.AccountEvent;
import fi.codecrew.moya.model.Discount;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.InventoryEvent;
import fi.codecrew.moya.model.LanEvent;
import fi.codecrew.moya.model.Product;
import fi.codecrew.moya.model.ProductFlag;
import fi.codecrew.moya.model.ProductLimitation;
import fi.codecrew.moya.model.Role;

/**
 * Session Bean implementation class ProductBean
 */
@Stateless
@LocalBean
@DeclareRoles({
		ShopPermission.S_LIST_ALL_PRODUCTS,
		ShopPermission.S_LIST_USERPRODUCTS,
		ShopPermission.S_MANAGE_PRODUCTS,
		ShopPermission.S_SHOP_PRODUCTS,
		ShopPermission.S_SHOP_TO_OTHERS
})
public class ProductBean implements ProductBeanLocal {

	private static final String DEFAULT_CREDIT_PRODCT = "Automagic Credit product";

	@EJB
	private ProductFacade productFacade;

	@EJB
	private InventoryEventFacade ieFacade;

	@EJB
	private EventBeanLocal eventBean;

	@EJB
	private AccountEventFacade accounteventfacade;
	@EJB
	private DiscountFacade discountfacade;
	@EJB
	private UserFacade userFacade;

	@EJB
	private PermissionBeanLocal permbean;
	@EJB
	private EventUserFacade eventUserFacade;
	@EJB
	private UserBeanLocal userbean;

	@EJB
	private BillBeanLocal billbean;
	@EJB
	private EventBeanLocal eventbean;
	@EJB
	private BillLineFacade billLineFacade;
	@EJB
	private ProductPBean productPBean;

	@SuppressWarnings("unused")
	private static final Logger logger = LoggerFactory.getLogger(ProductBean.class);

	/**
	 * Default constructor.
	 */
	public ProductBean() {
		// TODO Auto-generated constructor stub
	}

	@Override
	@RolesAllowed(ShopPermission.S_LIST_USERPRODUCTS)
	public List<Product> listUserShoppableProducts() {
		return productFacade.findProductsByFlag(ProductFlag.USER_SHOPPABLE);
	}

	@Override
	@RolesAllowed(ShopPermission.S_MANAGE_PRODUCTS)
	public void create(Product prod) {
		LanEvent event = eventBean.getCurrentEvent();
		prod.setEvent(event);
		productFacade.create(prod);

	}

	@Override
	@RolesAllowed(ShopPermission.S_LIST_ALL_PRODUCTS)
	public List<Product> getProducts() {
		return productFacade.findAll();
	}

	@Override
	@RolesAllowed(ShopPermission.S_MANAGE_PRODUCTS)
	public Product mergeChanges(Product product) {
		return productFacade.merge(product);
	}

	@Override
	public Product findCreditProduct() {
		List<Product> ret = productFacade.findProductsByPrice(BigDecimal.ONE.negate());
		Product retProd = null;
		if (ret == null || ret.isEmpty()) {
			retProd = new Product(eventBean.getCurrentEvent());
			retProd.setName(DEFAULT_CREDIT_PRODCT);
			retProd.setPrice(BigDecimal.ONE.negate());
			productFacade.create(retProd);
		} else {
			retProd = ret.get(0);
		}
		return retProd;
	}

	/**
	 * TODO: This is not enforced!!!
	 * 
	 * @param product
	 *            Product to find limits for
	 * @return How many products can still be bought. NULL if no limit.
	 */
	@Override
	public HashMap<Integer, BigDecimal> getProductLimit(Map<Integer, BigDecimal> prodCounts, EventUser user)
	{
		Set<Role> userroles = new HashSet<Role>(userbean.findUsersRoles(user));
		HashMap<Integer, BigDecimal> ret = new HashMap<Integer, BigDecimal>();
		for (Entry<Integer, BigDecimal> pc : prodCounts.entrySet())
		{
			Product prod = productFacade.find(pc.getKey());
			BigDecimal lim = getPrivateProductLimit(prod, user, prodCounts, userroles);
			ret.put(prod.getId(), lim);
			// logger.info("Added product limit {} to {}", lim, prod);
		}
		System.out.println(ret);
		return ret;
	}

	@Override
	public BigDecimal getProductLimit(Product product, EventUser user, Map<Integer, BigDecimal> prodCounts)
	{
		product = productFacade.reload(product);
		HashSet<Role> userroles = new HashSet<Role>(userbean.findUsersRoles(user));
		return getPrivateProductLimit(product, user, prodCounts, userroles);
	}

	private BigDecimal getPrivateProductLimit(Product product, EventUser user, Map<Integer, BigDecimal> prodCounts, Set<Role> userroles)
	{
		BigDecimal ret = null;
		if (product != null && product.getProductLimits() != null)
		{

			for (ProductLimitation limit : product.getProductLimits())
			{
				BigDecimal currentCount = BigDecimal.ZERO;
				for (Product p : limit.getProducts())
				{
					currentCount = currentCount.add(prodCounts.get(p.getId()));
				}

				// logger.info("Got limit {} for product {}", limit, product);
				if (limit.getMatchingRoles() != null && !limit.getMatchingRoles().isEmpty())
				{
					boolean roleMatched = false;

					for (Role mr : limit.getMatchingRoles()) {
						if (userroles.contains(mr)) {
							roleMatched = true;
							break;
						}
					}
					if (!roleMatched) {
						continue;
					}
				}

				BigDecimal count = currentCount;

				switch (limit.getType())
				{
				case GLOBAL_BILLED:
					BigDecimal globBillTot = BigDecimal.ZERO;
					for (Product p : limit.getProducts())
					{
						BillSummary globBilledSummary = billLineFacade.getLineSummary(p, eventbean.getCurrentEvent());
						globBillTot = globBillTot.add(globBilledSummary.getTotal());
					}
					count = count.add(globBillTot);
					ret = limit.getUpperLimit().subtract(count);
					break;
				case GLOBAL_BILL_PAID:
					BigDecimal globBillPaid = BigDecimal.ZERO;
					for (Product p : limit.getProducts())
					{
						BillSummary billPaidSummary = billLineFacade.getLineSummary(p, eventbean.getCurrentEvent());
						globBillPaid = globBillPaid.add(billPaidSummary.getPaid());
					}
					count = count.add(globBillPaid);
					ret = limit.getUpperLimit().subtract(count);
					break;
				case GLOBAL_ACCOUNTEVENTS:
					BigDecimal globalProductCount = accounteventfacade.getProductCount(limit.getProducts());
					if (globalProductCount != null) {
						count = count.add(globalProductCount);
					}
					ret = limit.getUpperLimit().subtract(count);
					break;
				case USER_ACCOUNTEVENTS:
					BigDecimal userProductCount = accounteventfacade.getProductCount(limit.getProducts(), user);
					if (userProductCount != null)
					{
						count = count.add(userProductCount);
					}
					ret = limit.getUpperLimit().subtract(count);
					break;
				case USER_BILLED:
					BigDecimal userBillTot = BigDecimal.ZERO;
					for (Product p : limit.getProducts())
					{
						BillSummary userBilledSummary = billLineFacade.getLineSummary(p, eventbean.getCurrentEvent(), user);
						userBillTot = userBillTot.add(userBilledSummary.getTotal());
					}
					count = count.add(userBillTot);
					ret = limit.getUpperLimit().subtract(count);
					break;
				case USER_BILL_PAID:
					BigDecimal userBillPaid = BigDecimal.ZERO;
					for (Product p : limit.getProducts())
					{
						BillSummary userPaidSummary = billLineFacade.getLineSummary(p, eventbean.getCurrentEvent(), user);
						userBillPaid = userBillPaid.add(userPaidSummary.getPaid());
					}
					count = count.add(userBillPaid);
					ret = limit.getUpperLimit().subtract(count);
					break;

				default:
					break;

				}
				if (ret != null)
				{
					// logger.warn("breaking for value {}, product {}", ret,
					// product);
					break;
				}

			}

		}
		return ret;
	}

	@Override
	public BigDecimal calculateTotal(Product product, BigDecimal quantity, Calendar date) {
		if (product == null || quantity == null) {
			throw new RuntimeException("Some parameter is null!");
		}
		BigDecimal total = product.getPrice();
		for (Discount d : product.getActiveDiscounts(quantity, date)) {
			total = total.multiply(d.getPercentage());
		}
		return total.setScale(2, RoundingMode.HALF_UP).multiply(quantity);

	}

	// // TODO: alennukset lasketaan täällä. HUOMHUOM!!
	// @Override
	// public List<Discount> getActiveDiscounts(Product product, BigDecimal
	// quantity) {
	// ArrayList<Discount> ret = new ArrayList<Discount>();
	// for (Discount d : product.getDiscounts()) {
	// if (d.isActive() && quantity.compareTo(d.getAmountMax()) <= 0 &&
	// quantity.compareTo(d.getAmountMin()) >= 0) {
	// ret.add(d);
	// }
	// }
	// return ret;
	// }

	@Override
	public Product findById(int id) {
		Product ret = productFacade.find(id);
		if (ret != null && !ret.getEvent().equals(eventBean.getCurrentEvent())) {
			ret = null;
		}
		return ret;
	}

	@Override
	@RolesAllowed(ShopPermission.S_MANAGE_PRODUCTS)
	public List<Product> findForStaffshop() {
		return productFacade.findAll();
	}

	@RolesAllowed(ShopPermission.S_MANAGE_PRODUCTS)
	public List<Product> findProductsByFlag(ProductFlag... productFlags) {
		return productFacade.findProductsByFlag(productFlags);
	}

	@RolesAllowed(ShopPermission.S_MANAGE_PRODUCTS)
	@Override
	public Discount findDiscount(Integer discountid) {
		return discountfacade.find(discountid);
	}

	@Override
	@RolesAllowed(ShopPermission.S_MANAGE_PRODUCTS)
	public Discount save(Discount discount) {
		return discountfacade.merge(discount);
	}

	@Override
	public AccountEvent createAccountEvent(Product product, BigDecimal quantity, EventUser user) {
		user = eventUserFacade.reload(user);
		AccountEvent ret = productPBean.createAccountEvent(product, quantity, user, Calendar.getInstance());
		return ret;
	}

	@Override
	// @RolesAllowed(ShopPermission.S_LIST_ALL_PRODUCTS)
	public Product findByBarcode(String barcode) {
		return productFacade.findProductByBarcode(barcode);
	}

	@Override
	@RolesAllowed(ShopPermission.S_MANAGE_PRODUCTS)
	public void saveInventoryEvent(InventoryEvent ie) {
		logger.debug("Creating new Inventoryevent {}", ie);
		ieFacade.create(ie);
	}

	@Override
	@RolesAllowed(ShopPermission.S_MANAGE_PRODUCTS)
	public List<Product> findProductsForEvent() {
		return productFacade.findAll();
	}

	@Override
	public List<Product> findPlaceProducts() {
		
		ArrayList<Product> returnProducts = new ArrayList<Product>();
		
		for(Product product : findProductsForEvent()) {
			if(product.getPlaces() != null && product.getPlaces().size() > 0) {
				returnProducts.add(product);
			}
		}
		
		return returnProducts;
	}
}