BillBean.java 6.13 KB
package fi.insomnia.bortal.beans;

import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Calendar;
import java.util.Collection;
import java.util.List;

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

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

import fi.insomnia.bortal.beanutil.PdfPrinter;
import fi.insomnia.bortal.bortal.views.BillSummary;
import fi.insomnia.bortal.enums.Permission;
import fi.insomnia.bortal.enums.RolePermission;
import fi.insomnia.bortal.facade.BillFacade;
import fi.insomnia.bortal.facade.BillLineFacade;
import fi.insomnia.bortal.model.AccountEvent;
import fi.insomnia.bortal.model.Bill;
import fi.insomnia.bortal.model.BillLine;
import fi.insomnia.bortal.model.Discount;
import fi.insomnia.bortal.model.LanEvent;
import fi.insomnia.bortal.model.Product;
import fi.insomnia.bortal.model.User;

/**
 * Session Bean implementation class BillBean
 */
@Stateless
@LocalBean
@DeclareRoles({ "BILL/READ", "USER_MANAGEMENT/EXECUTE", "USER_MANAGEMENT/READ" })
public class BillBean implements BillBeanLocal {

	private static final Logger logger = LoggerFactory.getLogger(BillBean.class);
	@EJB
	private BillFacade billFacade;

	@EJB
	private EventBeanLocal eventbean;
	@EJB
	private BillLineFacade billLineFacade;
	@PersistenceContext
	private EntityManager em;

	@EJB
	private PermissionBeanLocal permbean;
	@EJB
	private ProductBeanLocal productBean;

	@EJB
	private PlaceBean placebean;

	@EJB
	private PermissionBeanLocal permissionbean;

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

	@Override
	public Bill findById(int id) throws PermissionDeniedException {
		LanEvent event = eventbean.getCurrentEvent();
		if (id <= 0) {
			return null;
		}
		Bill bill = billFacade.find(event.getId(), id);
		User currentuser = permbean.getCurrentUser();
		logger.debug("bill {} user {}", bill, currentuser);

		if (bill == null || !currentuser.equals(bill.getUser())) {
			bill = null;
			permbean.fatalPermission(Permission.USER_MANAGEMENT, RolePermission.READ, "No right to read bill: ", bill);
		}
		return bill;

	}

	@Override
	public void getPdfBillStream(Bill bill, OutputStream ostream) {
		if (bill == null) {
			return;
		}
		if (bill.getBillNumber() == null || bill.getBillNumber() <= 0) {
			generateBillNumber(bill);
		}
		new PdfPrinter(bill).output(ostream);
	}

	private void generateBillNumber(Bill bill) {
		if (bill.getBillNumber() == null || bill.getBillNumber() == 0) {
			LanEvent currEvent = eventbean.getCurrentEvent();
			Integer billnr = billFacade.getBiggestBillNumber(currEvent);
			if (billnr == null || billnr < currEvent.getNextBillNumber()) {
				billnr = currEvent.getNextBillNumber();
			} else {
				++billnr;
			}
			bill.setBillNumber(billnr);
			billFacade.merge(bill);
		}

	}

	@Override
	public Bill createEmptyBill(User shoppingUser) throws PermissionDeniedException {
		if (permbean.isCurrentUser(shoppingUser)) {
			permbean.fatalPermission(Permission.SHOP, RolePermission.EXECUTE, "No permission to create empty bill for self");
		} else if (!permbean.hasPermission(Permission.ACCOUNT_MANAGEMENT, RolePermission.EXECUTE)) {
		}
		LanEvent event = eventbean.getCurrentEvent();
		Bill ret = new Bill(event, shoppingUser);
		billFacade.create(ret);
		ret.setUser(shoppingUser);
		em.flush();
		logger.debug("Created bill with id {} and user {}", ret.getId(), ret.getUser());
		return ret;
	}

	@Override
	@RolesAllowed("SHOP/EXECUTE")
	public BillLine addProductToBill(Bill bill, Product product, BigDecimal count) throws PermissionDeniedException {

		// If bill number > 0 bill has been sent and extra privileges are needed
		// to modify.
		boolean iscurrent = permissionbean.isCurrentUser(bill.getUser());
		Integer billnr = bill.getBillNumber();
		if (!iscurrent || billnr != null) {
			permbean.fatalPermission(Permission.USER_MANAGEMENT, RolePermission.EXECUTE, "User tried to modify bill ", bill, "without sufficient permissions");
		}
		BillLine line = new BillLine(bill, product.getName(), product.getUnitName(), count, product.getPrice(), product.getVat());
		line.setLineProduct(product);
		billLineFacade.create(line);

		List<Discount> discounts = productBean.getActiveDiscounts(product, count);

		for (Discount disc : discounts) {
			BigDecimal unitPrice = product.getPrice().subtract(product.getPrice().multiply(disc.getPercentage())).negate().setScale(2, RoundingMode.HALF_UP);
			BigDecimal vatPrice = product.getVat().subtract(product.getVat().multiply(disc.getPercentage())).negate().setScale(2, RoundingMode.HALF_UP);

			BillLine discountLine = new BillLine(bill, disc.getShortdesc(), product.getUnitName(), count, unitPrice, vatPrice);
			billLineFacade.create(discountLine);

		}

		em.flush();
		return line;
	}

	@Override
	@RolesAllowed("BILL/WRITE")
	public List<Bill> findAll() {

		return billFacade.findAll(eventbean.getCurrentEvent());
	}

	@Override
	@RolesAllowed("BILL/READ")
	public Collection<BillSummary> getBillLineSummary() {
		Collection<BillSummary> ret = billLineFacade.getLineSummary(eventbean.getCurrentEvent());

		return ret;
	}

	@Override
	@RolesAllowed("BILL/WRITE")
	public void markPaid(Bill bill, Calendar when) {

		Product creditproduct = productBean.findCreditProduct();

		AccountEvent ac = productBean.createAccountEvent(creditproduct, bill.totalPrice(), bill.getUser());
		ac.setDelivered(when);
		ac.setEventTime(when);
		ac.setBill(bill);
		ac.setSeller(permbean.getCurrentUser());

		bill.setAccountEvent(ac);
		bill.setPaidDate(when);

		billFacade.merge(bill);

		for (BillLine bl : bill.getBillLines()) {
			Product prod = bl.getLineProduct();
			if (prod != null) {
				if (prod.isPrepaidInstant()) {
					logger.debug("Creating Bill prepaidInstant product {}, {}", prod.getName(), bl.getQuantity());
					if (prod.getPlaces().size() > 0) {
						placebean.lockPlaceProduct(bill.getUser(), prod, bl.getQuantity());
					}

					productBean.createAccountEvent(prod, bl.getQuantity(), bill.getUser());

				}
			}
		}

	}
}