BillBean.java 11 KB
/*
 * Copyright Codecrew Ry
 * 
 * All rights reserved.
 * 
 * This license applies to any software containing a notice placed by the 
 * copyright holder. Such software is herein referred to as the Software. 
 * This license covers modification, distribution and use of the Software. 
 * 
 * Any distribution and use in source and binary forms, with or without 
 * modification is not permitted without explicit written permission from the 
 * copyright owner. 
 * 
 * A non-exclusive royalty-free right is granted to the copyright owner of the 
 * Software to use, modify and distribute all modifications to the Software in 
 * future versions of the Software. 
 * 
 */
package fi.codecrew.moya.beans;

import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.ArrayList;
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.EJBAccessException;
import javax.ejb.EJBException;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;

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

import fi.codecrew.moya.beanutil.PdfPrinter;
import fi.codecrew.moya.bortal.views.BillSummary;
import fi.codecrew.moya.enums.apps.BillPermission;
import fi.codecrew.moya.enums.apps.SpecialPermission;
import fi.codecrew.moya.facade.BillFacade;
import fi.codecrew.moya.facade.BillLineFacade;
import fi.codecrew.moya.facade.EventUserFacade;
import fi.codecrew.moya.model.AccountEvent;
import fi.codecrew.moya.model.Bill;
import fi.codecrew.moya.model.BillLine;
import fi.codecrew.moya.model.Discount;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.FoodWave;
import fi.codecrew.moya.model.LanEvent;
import fi.codecrew.moya.model.LanEventPropertyKey;
import fi.codecrew.moya.model.Product;
import fi.codecrew.moya.model.ProductFlag;
import fi.codecrew.moya.util.MailMessage;

/**
 * Session Bean implementation class BillBean
 */
@Stateless
@LocalBean
@DeclareRoles({ BillPermission.S_CREATE_BILL, BillPermission.S_READ_ALL, BillPermission.S_VIEW_OWN, BillPermission.S_WRITE_ALL, SpecialPermission.S_USER, SpecialPermission.S_VERKKOMAKSU_CHECK, })
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;

	@EJB
	private PermissionBeanLocal permbean;
	@EJB
	private ProductBean productBean;

	@EJB
	private PlaceBean placebean;

	@EJB
	private UtilBean utilbean;

	@EJB
	private LoggingBeanLocal loggingBean;
	@EJB
	private EventUserFacade eventUserFacade;
	@EJB
	private ProductPBean productPBean;

	@EJB
	private DiscountBean discountBean;

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

	@Override
	@RolesAllowed(BillPermission.S_VIEW_OWN)
	public Bill findById(int id) {
		if (id <= 0) {
			return null;
		}
		Bill bill = billFacade.find(id);
		EventUser currentuser = permbean.getCurrentUser();
		logger.debug("bill {} user {}", bill, currentuser);

		if (bill != null && !currentuser.equals(bill.getUser())
				&& !permbean.hasPermission(BillPermission.READ_ALL)) {
			bill = null;
		}
		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();

			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(BillPermission.CREATE_BILL,
	// "No permission to create empty bill for self");
	// } else {
	// permbean.fatalPermission(BillPermission.WRITE_ALL,
	// "Trying to create bill to someone else without sufficient permission");
	// }
	//
	// 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(BillPermission.WRITE_ALL,
	// "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(BillPermission.S_READ_ALL)
	public List<Bill> findAll() {

		return billFacade.findAll();
	}

	@Override
	@RolesAllowed(BillPermission.S_READ_ALL)
	public Collection<BillSummary> getBillLineSummary() {
		Collection<BillSummary> ret = billLineFacade.getLineSummary(eventbean
				.getCurrentEvent());

		return ret;
	}

	@Override
	@RolesAllowed({ BillPermission.S_WRITE_ALL,
			SpecialPermission.S_VERKKOMAKSU_CHECK })
	public Bill markPaid(Bill bill, Calendar when) {

		if (bill.getAccountEvent() != null || bill.getPaidDate() != null) {
			throw new EJBException("Bill already marked paid!");
		}
		if (bill.isFoowavePaymentOver())
		{
			throw new EJBException("Trying to mark paid a closed or left foodwave");

		}

		bill = billFacade.reload(bill);
		Product creditproduct = productBean.findCreditProduct();

		EventUser user = bill.getUser();
		AccountEvent ac = productBean.createAccountEvent(creditproduct, bill.totalPrice(), user);

		logger.info("Created creditentry. {}, userproducts {}", ac, user.getAccountEvents().size());

		// Used in foodwave. Should be null!
		// ac.setDelivered(when);
		ac.setEventTime(when);
		ac.setBill(bill);
		ac.setSeller(permbean.getCurrentUser());

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

		// bill = billFacade.merge(bill);

		for (BillLine bl : bill.getBillLines()) {

			Product prod = bl.getLineProduct();
			if (prod != null && !prod.getProductFlags().contains(ProductFlag.PREPAID_CREDIT)) {

				logger.debug("Creating Bill prepaidInstant product {}, {}", prod.getName(), bl.getQuantity());

				AccountEvent ac2 = productPBean.createAccountEvent(prod, bl.getQuantity(), user, bill.getSentDate(), bl.getFoodwave());
				logger.info("Created ac from product. {}, userproducts {}", ac2, user.getAccountEvents().size());

				ac2.setSeller(permbean.getCurrentUser());

			}

		}
		MailMessage msg = new MailMessage();

		String subject = MessageFormat.format(eventbean.getPropertyString(LanEventPropertyKey.BILL_PAID_MAIL_SUBJECT), user.getEvent().getName());
		String content = MessageFormat.format(eventbean.getPropertyString(LanEventPropertyKey.BILL_PAID_MAIL_CONTENT), (bill.getBillNumber() == null) ? "----" : bill.getBillNumber().toString());
		logger.info("Bill mail subject: {}, content {}", subject, content);
		msg.setSubject(subject);
		msg.setMessage(content);
		msg.setTo(bill.getUser().getUser());
		utilbean.sendMail(msg);
		eventUserFacade.flush();
		eventUserFacade.evict(bill.getUser());

		return bill;
	}

	@Override
	@RolesAllowed({ BillPermission.S_CREATE_BILL, BillPermission.S_WRITE_ALL })
	public Bill createBill(Bill bill) {
		if (!permbean.isCurrentUser(bill.getUser()) && !permbean.hasPermission(BillPermission.WRITE_ALL)) {
			loggingBean.logMessage(SecurityLogType.permissionDenied, permbean.getCurrentUser(), "Not enought rights to create bill for user ");
			throw new EJBAccessException("Could not create bill for another user");
		}
		billFacade.create(bill);
		generateBillNumber(bill);
		return bill;
	}

	@RolesAllowed({ BillPermission.S_WRITE_ALL })
	public Bill save(Bill bill) {
		return billFacade.merge(bill);
	}

	@Override
	@RolesAllowed({ BillPermission.S_VIEW_OWN, BillPermission.S_READ_ALL })
	public List<Bill> find(EventUser user) {
		if (!permbean.isCurrentUser(user) && !permbean.hasPermission(BillPermission.READ_ALL)) {
			loggingBean.logMessage(SecurityLogType.permissionDenied, permbean.getCurrentUser(), "Not enought rights to get bill list for user ");
			throw new EJBAccessException("Could not list bills for another user");
		}
		return billFacade.find(user);
	}

	@Override
	@RolesAllowed({ BillPermission.S_VIEW_OWN, BillPermission.S_WRITE_ALL })
	public Bill expireBill(Bill bill) {
		if (!permbean.isCurrentUser(bill.getUser()) && !permbean.hasPermission(BillPermission.WRITE_ALL)) {
			loggingBean.logMessage(SecurityLogType.permissionDenied, permbean.getCurrentUser(), "Not enought rights to expire a bill for user ");
			throw new EJBAccessException("Could not list bills for another user");
		}

		bill = billFacade.reload(bill);
		bill.markExpired();
		return bill;
	}

	@Override
	public Bill addProductToBill(Bill bill, Product product, BigDecimal count) {
		return this.addProductToBill(bill, product, count, null);
	}

	@Override
	public Bill addProductToBill(Bill bill, Product product, BigDecimal count, FoodWave foodwave) {

		// If bill number > 0 bill has been sent and extra privileges are needed
		// to modify.
		// if (!iscurrent || billnr != null) {
		// permbean.fatalPermission(BillPermission.WRITE_ALL,
		// "User tried to modify bill ", bill,
		// "without sufficient permissions");
		// }
		if (bill.getBillLines() == null) {
			bill.setBillLines(new ArrayList<BillLine>());
		}

		bill.getBillLines().add(new BillLine(bill, product, count, foodwave));

		for (Discount disc : discountBean.getActiveDiscountsByProduct(product, count, bill.getSentDate(), bill.getUser())) {
			bill.getBillLines().add(new BillLine(bill, product, disc, count));
		}

		return bill;
	}

}