Commit 4df4dc08 by Tuomas Riihimäki

Add product limitation for places.

When product is billed there should be created new groupMembership (not implemented yet)
When limitation 'PLACES' is added for product, it should check how many places have been reserved
ie how mony groupmemberships with that product have been created and limit bought places.
1 parent f1f0b6b2
......@@ -28,8 +28,11 @@ import fi.codecrew.moya.enums.apps.UserPermission;
import fi.codecrew.moya.facade.AccountEventFacade;
import fi.codecrew.moya.facade.BillLineFacade;
import fi.codecrew.moya.facade.DiscountFacade;
import fi.codecrew.moya.facade.EventMapFacade;
import fi.codecrew.moya.facade.EventUserFacade;
import fi.codecrew.moya.facade.GroupMembershipFacade;
import fi.codecrew.moya.facade.InventoryEventFacade;
import fi.codecrew.moya.facade.PlaceFacade;
import fi.codecrew.moya.facade.ProductFacade;
import fi.codecrew.moya.facade.UserFacade;
import fi.codecrew.moya.model.AccountEvent;
......@@ -107,6 +110,14 @@ public class ProductBean implements ProductBeanLocal {
@EJB
private CardTemplateBean cardTemplateBean;
@EJB
private PlaceFacade placeFacade;
@EJB
private EventMapFacade mapfacade;
@EJB
private GroupMembershipFacade gmfacade;
private static final Logger logger = LoggerFactory.getLogger(ProductBean.class);
/**
......@@ -188,6 +199,15 @@ public class ProductBean implements ProductBeanLocal {
return getPrivateProductLimit(product, user, prodCounts, userroles);
}
/**
* Returns available products to be bought for the user.
*
* @param product
* @param user
* @param prodCounts
* @param userroles
* @return Number of buyable products
*/
private BigDecimal getPrivateProductLimit(Product product, EventUser user, Map<Integer, BigDecimal> prodCounts, Set<Role> userroles)
{
BigDecimal ret = null;
......@@ -222,15 +242,26 @@ public class ProductBean implements ProductBeanLocal {
switch (limit.getType())
{
case GLOBAL_BILLED:
case PLACE: {
Long reserved = 0L;
Long available = 0L;
for (Product p : limit.getProducts()) {
reserved += gmfacade.findPlaceProductCount(p);
available += placeFacade.findCountForProduct(p);
}
ret = BigDecimal.valueOf(available - reserved).subtract(count);
break;
}
case GLOBAL_BILLED: {
BigDecimal globBillTot = BigDecimal.ZERO;
for (Product p : limit.getProducts()) {
BillSummary globBilledSummary = billLineFacade.getLineSummary(p, eventbean.getCurrentEvent());
globBillTot = globBillTot.add(globBilledSummary.getTotal());
globBillTot = globBillTot.add(globBilledSummary.getActive());
}
count = count.add(globBillTot);
ret = limit.getUpperLimit().subtract(count);
break;
}
case GLOBAL_BILL_PAID:
BigDecimal globBillPaid = BigDecimal.ZERO;
for (Product p : limit.getProducts()) {
......@@ -258,7 +289,7 @@ public class ProductBean implements ProductBeanLocal {
BigDecimal userBillTot = BigDecimal.ZERO;
for (Product p : limit.getProducts()) {
BillSummary userBilledSummary = billLineFacade.getLineSummary(p, eventbean.getCurrentEvent(), user);
userBillTot = userBillTot.add(userBilledSummary.getTotal());
userBillTot = userBillTot.add(userBilledSummary.getActive());
}
count = count.add(userBillTot);
ret = limit.getUpperLimit().subtract(count);
......
......@@ -2,13 +2,8 @@ package fi.codecrew.moya.facade;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import fi.codecrew.moya.model.Place_;
import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.Place;
@Stateless
@LocalBean
......@@ -18,43 +13,4 @@ public class EventMapFacade extends IntegerPkGenericFacade<EventMap> {
super(EventMap.class);
}
public Long countAvailable(EventMap map) {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<Place> root = cq.from(Place.class);
cq.select(cb.count(root));
cq.where(
cb.equal(root.get(Place_.map), map),
cb.isFalse(root.get(Place_.disabled))
);
return getSingleNullableResult(getEm().createQuery(cq));
}
public Long countSelectable(EventMap map) {
if (map == null) {
return null;
}
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<Place> root = cq.from(Place.class);
cq.select(cb.count(root));
cq.where(
cb.equal(root.get(Place_.map), map),
cb.isNull(root.get(Place_.releaseTime)),
cb.isNull(root.get(Place_.group)),
cb.isFalse(root.get(Place_.disabled))
);
return getSingleNullableResult(getEm().createQuery(cq));
}
}
......@@ -20,6 +20,7 @@ import fi.codecrew.moya.model.GroupMembership_;
import fi.codecrew.moya.model.PlaceGroup;
import fi.codecrew.moya.model.PlaceGroup_;
import fi.codecrew.moya.model.Place_;
import fi.codecrew.moya.model.Product;
import fi.codecrew.moya.utilities.PasswordFunctions;
@Stateless
......@@ -65,13 +66,13 @@ public class GroupMembershipFacade extends IntegerPkGenericFacade<GroupMembershi
// q.setParameter("token", token);
return getSingleNullableResult(getEm().createQuery(cq));
}
public List<GroupMembership> matchByToken(String token) {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<GroupMembership> cq = cb.createQuery(GroupMembership.class);
Root<GroupMembership> root = cq.from(GroupMembership.class);
cq.where(cb.like(root.get(GroupMembership_.inviteToken), "%"+token+"%"),
cq.where(cb.like(root.get(GroupMembership_.inviteToken), "%" + token + "%"),
cb.equal(root.get(GroupMembership_.placeGroup).get(PlaceGroup_.event), eventbean.getCurrentEvent())
);
......@@ -123,7 +124,7 @@ public class GroupMembershipFacade extends IntegerPkGenericFacade<GroupMembershi
// p.setParameter("user", user);
// return p.getResultList();
}
public List<GroupMembership> findAllWithoutUser() {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<GroupMembership> cq = cb.createQuery(GroupMembership.class);
......@@ -137,4 +138,16 @@ public class GroupMembershipFacade extends IntegerPkGenericFacade<GroupMembershi
return getEm().createQuery(cq).getResultList();
}
public Long findPlaceProductCount(Product product) {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<GroupMembership> root = cq.from(GroupMembership.class);
cq.select(cb.count(root));
cq.where(cb.equal(root.get(GroupMembership_.placeProduct), product));
return super.getSingleNullableResult(getEm().createQuery(cq));
}
}
......@@ -22,13 +22,14 @@ import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.LanEvent;
import fi.codecrew.moya.model.Place;
import fi.codecrew.moya.model.Place_;
import fi.codecrew.moya.model.Product;
@Stateless
@LocalBean
public class PlaceFacade extends IntegerPkGenericFacade<Place> {
private static final Logger logger = LoggerFactory.getLogger(PlaceFacade.class);
@EJB
EventBeanLocal eventBean;
......@@ -127,18 +128,66 @@ public class PlaceFacade extends IntegerPkGenericFacade<Place> {
);
return getSingleNullableResult(getEm().createQuery(cq));
}
public List<Place> findAll() {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<Place> cq = cb.createQuery(Place.class);
Root<Place> root = cq.from(Place.class);
cq.where( cb.equal(root.get(Place_.map).get(EventMap_.event), eventBean.getCurrentEvent()));
cq.where(cb.equal(root.get(Place_.map).get(EventMap_.event), eventBean.getCurrentEvent()));
cq.orderBy(cb.asc(root.get(Place_.name)));
return getEm().createQuery(cq).getResultList();
}
}
public Long findCountForProduct(Product product) {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<Place> root = cq.from(Place.class);
cq.select(cb.count(root));
cq.where(
cb.equal(root.get(Place_.product), product),
cb.isFalse(root.get(Place_.disabled))
);
return super.getSingleNullableResult(getEm().createQuery(cq));
}
public Long countAvailable(EventMap map) {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<Place> root = cq.from(Place.class);
cq.select(cb.count(root));
cq.where(
cb.equal(root.get(Place_.map), map),
cb.isFalse(root.get(Place_.disabled))
);
return getSingleNullableResult(getEm().createQuery(cq));
}
public Long countSelectable(EventMap map) {
if (map == null) {
return null;
}
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<Place> root = cq.from(Place.class);
cq.select(cb.count(root));
cq.where(
cb.equal(root.get(Place_.map), map),
cb.isNull(root.get(Place_.releaseTime)),
cb.isNull(root.get(Place_.group)),
cb.isFalse(root.get(Place_.disabled))
);
return getSingleNullableResult(getEm().createQuery(cq));
}
}
......@@ -6,31 +6,40 @@ import fi.codecrew.moya.model.BillLine;
public class BillSummary {
public BillSummary(String name) {
this.name = name;
}
private String name;
private BigDecimal total = BigDecimal.ZERO;
private BigDecimal paid = BigDecimal.ZERO;
public String getName() {
return name;
}
public BigDecimal getTotal() {
return total;
}
public void addLine(BillLine bl) {
total = getTotal().add(bl.getQuantity());
if (bl.getBill().getPaidDate() != null) {
paid = getPaid().add(bl.getQuantity());
}
}
public BigDecimal getPaid() {
return paid;
}
public BillSummary(String name) {
this.name = name;
}
private String name;
private BigDecimal active = BigDecimal.ZERO;
private BigDecimal paid = BigDecimal.ZERO;
private BigDecimal expired = BigDecimal.ZERO;
public String getName() {
return name;
}
public BigDecimal getActive() {
return active;
}
public void addLine(BillLine bl) {
if (bl.getBill().isExpired()) {
expired = getExpired().add(bl.getQuantity());
} else {
active = getActive().add(bl.getQuantity());
if (bl.getBill().getPaidDate() != null) {
paid = getPaid().add(bl.getQuantity());
}
}
}
public BigDecimal getPaid() {
return paid;
}
public BigDecimal getExpired() {
return expired;
}
}
......@@ -2,5 +2,5 @@ package fi.codecrew.moya.model;
public enum ProductLimitationType {
GLOBAL_BILLED, GLOBAL_BILL_PAID, GLOBAL_ACCOUNTEVENTS, USER_BILLED, USER_BILL_PAID, USER_ACCOUNTEVENTS,
GLOBAL_BILLED, GLOBAL_BILL_PAID, GLOBAL_ACCOUNTEVENTS, USER_BILLED, USER_BILL_PAID, USER_ACCOUNTEVENTS, PLACE
}
......@@ -20,7 +20,7 @@
<f:facet name="header">
<h:outputText value="${i18n['product.boughtTotal']}" />
</f:facet>
<h:outputText value="#{sumline.total}">
<h:outputText value="#{sumline.active}">
<f:convertNumber />
</h:outputText>
</h:column>
......@@ -32,6 +32,14 @@
<f:convertNumber />
</h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="${i18n['product.expired']}" />
</f:facet>
<h:outputText value="#{sumline.expired}">
<f:convertNumber />
</h:outputText>
</h:column>
</h:dataTable>
</ui:define>
</ui:composition>
......
......@@ -15,7 +15,6 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import fi.codecrew.moya.beans.PlaceGroupBeanLocal;
import fi.codecrew.moya.beans.PlaceMapBeanLocal;
import fi.codecrew.moya.beans.ProductBeanLocal;
import fi.codecrew.moya.model.AccountEvent;
import fi.codecrew.moya.model.Product;
......@@ -29,8 +28,6 @@ import fi.codecrew.moya.rest.highcharts.HcSeriesRoot;
public class AccountEventRestView {
@EJB
private PlaceMapBeanLocal placemapbean;
@EJB
private PlaceGroupBeanLocal pgbean;
@EJB
private ProductBeanLocal productBean;
......
......@@ -24,7 +24,6 @@ import fi.codecrew.moya.beans.EventBeanLocal;
import fi.codecrew.moya.beans.EventMapBeanLocal;
import fi.codecrew.moya.beans.PlaceBeanLocal;
import fi.codecrew.moya.beans.PlaceGroupBeanLocal;
import fi.codecrew.moya.beans.PlaceMapBeanLocal;
import fi.codecrew.moya.beans.ProductBeanLocal;
import fi.codecrew.moya.beans.UserBeanLocal;
import fi.codecrew.moya.exceptions.BortalCatchableException;
......@@ -46,8 +45,6 @@ public class MapAdminView {
@EJB
private EventMapBeanLocal eventmapbean;
@EJB
private PlaceMapBeanLocal placemapbean;
@EJB
private PlaceGroupBeanLocal pgbean;
@EJB
private EventBeanLocal eventbean;
......@@ -64,7 +61,7 @@ public class MapAdminView {
@Path("/background/{mapId}")
public Response getMapBg(@PathParam("mapId") Integer mapid)
{
EventMap map = placemapbean.findMap(mapid);
EventMap map = placebean.findMap(mapid);
ByteArrayInputStream istream = new ByteArrayInputStream(map.getMapData());
return Response.ok().entity(istream).type("image/jpeg").build();
}
......@@ -80,7 +77,7 @@ public class MapAdminView {
@GET
@Path("/places/{mapId}")
public PlaceRoot getPlaces(@PathParam("mapId") Integer mapid) {
EventMap map = placemapbean.findMap(mapid);
EventMap map = placebean.findMap(mapid);
PlaceRoot ret = new PlaceRoot(map);
logger.info("returning map {} entity {}", mapid, ret);
return ret;
......
......@@ -13,8 +13,8 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import fi.codecrew.moya.beans.PlaceBeanLocal;
import fi.codecrew.moya.beans.PlaceGroupBeanLocal;
import fi.codecrew.moya.beans.PlaceMapBeanLocal;
import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.Place;
import fi.codecrew.moya.model.PlaceGroup;
......@@ -26,14 +26,14 @@ import fi.codecrew.moya.model.PlaceGroup;
public class MapRestView {
@EJB
private PlaceMapBeanLocal placemapbean;
private PlaceBeanLocal placebean;
@EJB
private PlaceGroupBeanLocal pgbean;
@GET
@Path("/dateJson")
public String getAllCards() {
EventMap map = placemapbean.getActiveMap();
EventMap map = placebean.getActiveMap();
Map<Integer, Map<Integer, Map<Integer, Integer>>> counts = new HashMap<>();
......
......@@ -30,7 +30,7 @@ import org.slf4j.LoggerFactory;
import fi.codecrew.moya.beans.LoggingBeanLocal;
import fi.codecrew.moya.beans.PermissionBeanLocal;
import fi.codecrew.moya.beans.PlaceMapBeanLocal;
import fi.codecrew.moya.beans.PlaceBeanLocal;
import fi.codecrew.moya.beans.SecurityLogType;
import fi.codecrew.moya.enums.apps.MapPermission;
import fi.codecrew.moya.model.EventMap;
......@@ -49,7 +49,7 @@ public class PlaceMap extends HttpServlet {
private static final long serialVersionUID = 8769688627918936258L;
@EJB
private transient PlaceMapBeanLocal placemapBean;
private transient PlaceBeanLocal placeBean;
@EJB
private transient PermissionBeanLocal permbean;
......@@ -87,7 +87,7 @@ public class PlaceMap extends HttpServlet {
// Integer userId = getIntegerParameter(request,
// PARAMETER_CURRENT_USER_ID); Tämä saadaan beaneilta.
EventMap map = placemapBean.findMap(mapId);
EventMap map = placeBean.findMap(mapId);
logger.debug("Mapid: {}", mapId);
ostream = response.getOutputStream();
......
......@@ -13,7 +13,6 @@ import org.slf4j.LoggerFactory;
import fi.codecrew.moya.beans.EventBeanLocal;
import fi.codecrew.moya.beans.PlaceBeanLocal;
import fi.codecrew.moya.beans.PlaceMapBeanLocal;
import fi.codecrew.moya.enums.apps.MapPermission;
import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.EventUser;
......@@ -25,8 +24,6 @@ import fi.codecrew.moya.web.cdiview.GenericCDIView;
public class MapView extends GenericCDIView {
private static final long serialVersionUID = 2374905512998240551L;
@EJB
private transient PlaceMapBeanLocal placeMapBean;
@Inject
@SelectedUser
......@@ -79,7 +76,7 @@ public class MapView extends GenericCDIView {
}
public Long getPlacesLeftToSelect() {
Long ret = placeMapBean.selectablePlaceCount(getActiveMap());
Long ret = placeBean.selectablePlaceCount(getActiveMap());
logger.debug("Got {} places left for map {}", ret, getActiveMap());
return ret;
......@@ -88,7 +85,7 @@ public class MapView extends GenericCDIView {
public Long getAvailablePlaces()
{
Long ret = placeMapBean.availablePlaceCount(getActiveMap());
Long ret = placeBean.availablePlaceCount(getActiveMap());
logger.debug("Got {} availbale places for map {}", ret, getActiveMap());
return ret;
......@@ -98,7 +95,7 @@ public class MapView extends GenericCDIView {
@Produces
public EventMap getActiveMap() {
if (activeMap == null) {
activeMap = placeMapBean.getActiveMap();
activeMap = placeBean.getActiveMap();
}
return activeMap;
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!