Commit 82dfb3fd by Tuomas Riihimäki

Place selection with neomap

1 parent 380c6c51
...@@ -23,6 +23,7 @@ import java.math.BigDecimal; ...@@ -23,6 +23,7 @@ import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collection; import java.util.Collection;
import java.util.Date;
import java.util.List; import java.util.List;
import javax.annotation.security.DeclareRoles; import javax.annotation.security.DeclareRoles;
...@@ -49,6 +50,7 @@ import fi.codecrew.moya.exceptions.BillExceptionNotEnoughtCredits; ...@@ -49,6 +50,7 @@ import fi.codecrew.moya.exceptions.BillExceptionNotEnoughtCredits;
import fi.codecrew.moya.facade.BillFacade; import fi.codecrew.moya.facade.BillFacade;
import fi.codecrew.moya.facade.BillLineFacade; import fi.codecrew.moya.facade.BillLineFacade;
import fi.codecrew.moya.facade.EventUserFacade; import fi.codecrew.moya.facade.EventUserFacade;
import fi.codecrew.moya.facade.PlaceSlotFacade;
import fi.codecrew.moya.model.AccountEvent; import fi.codecrew.moya.model.AccountEvent;
import fi.codecrew.moya.model.Bill; import fi.codecrew.moya.model.Bill;
import fi.codecrew.moya.model.BillLine; import fi.codecrew.moya.model.BillLine;
...@@ -56,8 +58,10 @@ import fi.codecrew.moya.model.Discount; ...@@ -56,8 +58,10 @@ import fi.codecrew.moya.model.Discount;
import fi.codecrew.moya.model.EventUser; import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.FoodWave; import fi.codecrew.moya.model.FoodWave;
import fi.codecrew.moya.model.LanEvent; import fi.codecrew.moya.model.LanEvent;
import fi.codecrew.moya.model.PlaceSlot;
import fi.codecrew.moya.model.Product; import fi.codecrew.moya.model.Product;
import fi.codecrew.moya.model.ProductFlag; import fi.codecrew.moya.model.ProductFlag;
import fi.codecrew.moya.utilities.jpa.GenericFacade;
import fi.codecrew.moya.utilities.moyamessage.MoyaEventType; import fi.codecrew.moya.utilities.moyamessage.MoyaEventType;
/** /**
...@@ -102,6 +106,8 @@ public class BillBean implements BillBeanLocal { ...@@ -102,6 +106,8 @@ public class BillBean implements BillBeanLocal {
private LoggingBeanLocal logbean; private LoggingBeanLocal logbean;
@EJB @EJB
private BillPBean billpbean; private BillPBean billpbean;
@EJB
private PlaceSlotFacade psFacade;
/** /**
* Default constructor. * Default constructor.
...@@ -259,9 +265,37 @@ public class BillBean implements BillBeanLocal { ...@@ -259,9 +265,37 @@ public class BillBean implements BillBeanLocal {
} }
billFacade.create(bill); billFacade.create(bill);
generateBillNumber(bill); generateBillNumber(bill);
createPlaceslots(bill);
return bill; return bill;
} }
/**
* Create place slots for the bill
*
* @param bill
*/
private void createPlaceslots(Bill bill) {
for (BillLine bl : bill.getBillLines()) {
if (bl == null)
return;
Product prod = bl.getLineProduct();
if (prod == null || prod.getPlaces() == null || prod.getPlaces().isEmpty()) {
// Not a place product.
return;
}
int count = bl.getQuantity().intValue();
Date now = new Date();
for (int i = 0; i < count; ++i)
{
PlaceSlot ps = new PlaceSlot();
ps.setBill(bill);
ps.setCreated(now);
ps.setProduct(prod);
psFacade.create(ps);
}
}
}
@RolesAllowed({ BillPermission.S_WRITE_ALL }) @RolesAllowed({ BillPermission.S_WRITE_ALL })
public Bill save(Bill bill) { public Bill save(Bill bill) {
return billFacade.merge(bill); return billFacade.merge(bill);
......
...@@ -25,6 +25,7 @@ package fi.codecrew.moya.beans; ...@@ -25,6 +25,7 @@ package fi.codecrew.moya.beans;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
...@@ -230,8 +231,8 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -230,8 +231,8 @@ public class PlaceBean implements PlaceBeanLocal {
@Override @Override
@RolesAllowed(MapPermission.S_BUY_PLACES) @RolesAllowed(MapPermission.S_BUY_PLACES)
public boolean reservePlace(Place place, EventUser user) { public boolean reservePlace(Place place, EventUser user) {
place = placeFacade.find(place.getId()); place = placeFacade.reload(place);
user = eventUserFacade.find(user.getId()); user = eventUserFacade.reload(user);
boolean ret = false; boolean ret = false;
// when admin click's place, he reserves it -> just ignore it // when admin click's place, he reserves it -> just ignore it
...@@ -239,13 +240,30 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -239,13 +240,30 @@ public class PlaceBean implements PlaceBeanLocal {
if (place.isBuyable() || permbean.hasPermission(MapPermission.MANAGE_OTHERS)) { if (place.isBuyable() || permbean.hasPermission(MapPermission.MANAGE_OTHERS)) {
if (place.getProduct().getProductFlags().contains(ProductFlag.PREPAID_CREDIT)) { if (place.getProduct().getProductFlags().contains(ProductFlag.PREPAID_CREDIT)) {
// TODO: We should check there is enough credits... logger.warn("Reserving place {} with Prepaid credit!", place);
BigDecimal balance = user.getAccountBalance();
BigDecimal price = getTotalReservationPrice(user, place);
boolean canReserve = (price.compareTo(balance) <= 0);
logger.debug("Balance {}, price {}", balance, price);
if (!canReserve)
{
logger.debug("Did not have enought credits to reserve place! required {} , got {}", price, balance);
return false;
}
} else { } else {
List<PlaceSlot> slots = placeSlotFacade.findFreePlaceSlots(user, place.getProduct()); List<PlaceSlot> slots = placeSlotFacade.findFreePlaceSlots(user, place.getProduct());
logger.info("Found free slots {} for user {}", Arrays.asList(slots.toArray()), user);
if (slots != null && !slots.isEmpty()) { if (slots != null && !slots.isEmpty()) {
PlaceSlot slot = slots.get(0); PlaceSlot slot = slots.get(0);
logger.warn("Reserving place {} with placeslot {}", place, slot);
slot.setPlace(place); slot.setPlace(place);
slot.setUsed(new Date()); slot.setUsed(new Date());
} else {
logger.warn("Not enough slots to reserve place {}", place);
// Not enough slots to reserve place
return false;
} }
} }
......
...@@ -12,7 +12,8 @@ ...@@ -12,7 +12,8 @@
<ui:composition template="#{sessionHandler.template}"> <ui:composition template="#{sessionHandler.template}">
<f:metadata> <f:metadata>
<f:event type="preRenderView" listener="#{ajaxMapView.initReserveMap()}" /> <f:event type="preRenderView"
listener="#{ajaxMapView.initReserveMap()}" />
</f:metadata> </f:metadata>
<ui:define name="content"> <ui:define name="content">
<h:form> <h:form>
...@@ -32,20 +33,29 @@ ...@@ -32,20 +33,29 @@
<h:outputScript target="head" library="seatjs" name="d3-tip.js" /> <h:outputScript target="head" library="seatjs" name="d3-tip.js" />
<h:outputScript target="head" library="seatjs" name="seatmap.js" /> <h:outputScript target="head" library="seatjs" name="seatmap.js" />
<h:outputStylesheet library="seatjs" name="placemap.css" /> <h:outputStylesheet library="seatjs" name="placemap.css" />
<h:form>
<svg id="seatmap" style="margin: auto; border: 1px solid black; background-image: url()" <h:commandButton rendered="#{mapView.canUserBuy()}"
width="#{ajaxMapView.map.width}px" height="#{ajaxMapView.map.height}px" /> value="#{i18n['mapView.buyPlaces']}"
<script type="text/javascript"> action="#{placeView.buySelectedPlaces()}" />
</h:form>
<div>
<svg id="seatmap"
style="margin: auto; border: 1px solid black; background-image: url()"
width="#{ajaxMapView.map.width}px"
height="#{ajaxMapView.map.height}px" />
<script type="text/javascript">
px = placemap({ px = placemap({
element : document.getElementById("seatmap"), element : document.getElementById("seatmap"),
moyaurl : "#{request.contextPath}", moyaurl : "#{request.contextPath}",
map_id : #{ajaxMapView.map.id}, map_id : #{ajaxMapView.map.id},
onclick : function(d) { onclick : function(d) {
placeClicker([{name: 'placeId', value: d}]) // placeClicker([{name: 'placeId', value: d}])
return false; return false;
} }
}); });
</script> </script>
</div>
</ui:define> </ui:define>
</ui:composition> </ui:composition>
</h:body> </h:body>
......
...@@ -17,11 +17,11 @@ ...@@ -17,11 +17,11 @@
</f:metadata> </f:metadata>
<ui:param name="thispage" value="page.place.placemap" /> <ui:param name="thispage" value="page.place.placemap" />
<ui:define name="content"> <ui:define name="content">
<h:form> <!-- <h:form>
<p:remoteCommand name="placeClicker" update=":fbdiag" <p:remoteCommand name="placeClicker" update=":fbdiag"
action="#{ajaxMapView.placeClicked()}" /> action="#{ajaxMapView.placeClicked()}" />
</h:form> </h:form>
-->
<p:dialog rendered="#{ajaxMapView.isMgmtPermission()}" <p:dialog rendered="#{ajaxMapView.isMgmtPermission()}"
visible="#{!empty ajaxMapView.place}" id="fbdiag"> visible="#{!empty ajaxMapView.place}" id="fbdiag">
Clicked place name : #{ajaxMapView.place.name}; Clicked place name : #{ajaxMapView.place.name};
...@@ -35,7 +35,13 @@ ...@@ -35,7 +35,13 @@
<h:outputScript target="head" library="seatjs" name="d3-tip.js" /> <h:outputScript target="head" library="seatjs" name="d3-tip.js" />
<h:outputScript target="head" library="seatjs" name="seatmap.js" /> <h:outputScript target="head" library="seatjs" name="seatmap.js" />
<h:outputStylesheet library="seatjs" name="placemap.css" /> <h:outputStylesheet library="seatjs" name="placemap.css" />
<button onclick="px.update()" >Update</button><br/> <div style="margin: 5px;">
<h:form id="placeselectform">
<h:commandButton rendered="#{ajaxMapView.canUserBuy()}"
value="#{i18n['mapView.buyPlaces']}"
action="#{ajaxMapView.buySelectedPlaces()}" />
</h:form>
</div>
<svg id="seatmap" style="margin: auto; border: 1px solid black;" <svg id="seatmap" style="margin: auto; border: 1px solid black;"
width="#{ajaxMapView.map.width}px" width="#{ajaxMapView.map.width}px"
height="#{ajaxMapView.map.height}px" /> height="#{ajaxMapView.map.height}px" />
...@@ -57,6 +63,37 @@ ...@@ -57,6 +63,37 @@
// }); // });
//px.enable_edit(); //px.enable_edit();
</script> </script>
<h:panelGrid columns="3" cellpadding="10">
<h:panelGrid columns="2">
<div
style="border-color: black; border-style: solid; border-width: 1px; background-color: grey; width: 10px; height: 10px;">&nbsp;</div>
<h:outputText value="#{i18n['placeSelect.legend.grey']}" />
<div
style="border-color: black; border-style: solid; border-width: 1px; background-color: white; width: 10px; height: 10px;">&nbsp;</div>
<h:outputText value="#{i18n['placeSelect.legend.white']}" />
<div
style="border-color: black; border-style: solid; border-width: 1px; background-color: red; width: 10px; height: 10px;">&nbsp;</div>
<h:outputText value="#{i18n['placeSelect.legend.red']}" />
<div
style="border-color: black; border-style: solid; border-width: 1px; background-color: green; width: 10px; height: 10px;">&nbsp;</div>
<h:outputText value="#{i18n['placeSelect.legend.green']}" />
<div
style="border-color: black; border-style: solid; border-width: 1px; background-color: blue; width: 10px; height: 10px;">&nbsp;</div>
<h:outputText value="#{i18n['placeSelect.legend.blue']}" />
</h:panelGrid>
<h:panelGrid columnClasses=",rightalign" columns="2">
<h:outputLabel value="#{i18n['placeSelect.totalPlaces']}:" />
<h:outputText value="#{ajaxMapView.availablePlaces}" />
<h:outputLabel value="#{i18n['placeSelect.placesleft']}:" />
<h:outputText value="#{ajaxMapView.placesLeftToSelect}" />
</h:panelGrid>
</h:panelGrid>
</ui:define> </ui:define>
</ui:composition> </ui:composition>
</h:body> </h:body>
......
...@@ -108,7 +108,7 @@ public class PlacemapRestViewV1 { ...@@ -108,7 +108,7 @@ public class PlacemapRestViewV1 {
@POST @POST
@Path("/place/{place}") @Path("/place/{place}")
public SimplePlacelistRoot togglePlaceReservation(@PathParam("place") Integer placeId) public Response togglePlaceReservation(@PathParam("place") Integer placeId)
{ {
EventUser user = null; EventUser user = null;
if (userView != null) { if (userView != null) {
...@@ -116,16 +116,23 @@ public class PlacemapRestViewV1 { ...@@ -116,16 +116,23 @@ public class PlacemapRestViewV1 {
} }
Place p = placebean.find(placeId); Place p = placebean.find(placeId);
boolean success = false;
if (p.isReservedFor(user)) { if (p.isReservedFor(user)) {
placebean.releasePlace(p); success = placebean.releasePlace(p);
} else if (p.isBuyable() && !p.isTaken()) { } else if (p.isBuyable() && !p.isTaken()) {
placebean.reservePlace(p, user); logger.info("Rest Reserving place for place {}", p);
success = placebean.reservePlace(p, user);
} }
logger.info("Returning rest success {}", success);
p = placebean.find(placeId); ResponseBuilder resp = null;
List<Place> thisplace = new ArrayList<Place>(); if (success) {
thisplace.add(p); p = placebean.find(placeId);
List<Place> thisplace = new ArrayList<Place>();
return SimplePlacelistRoot.wrap(thisplace, user); thisplace.add(p);
resp = Response.ok(SimplePlacelistRoot.wrap(thisplace, user));
} else {
resp = Response.status(Response.Status.FORBIDDEN);
}
return resp.build();
} }
} }
...@@ -16,10 +16,13 @@ import fi.codecrew.moya.beans.EventBeanLocal; ...@@ -16,10 +16,13 @@ import fi.codecrew.moya.beans.EventBeanLocal;
import fi.codecrew.moya.beans.PermissionBeanLocal; import fi.codecrew.moya.beans.PermissionBeanLocal;
import fi.codecrew.moya.beans.PlaceBeanLocal; import fi.codecrew.moya.beans.PlaceBeanLocal;
import fi.codecrew.moya.enums.apps.MapPermission; import fi.codecrew.moya.enums.apps.MapPermission;
import fi.codecrew.moya.exceptions.BortalCatchableException;
import fi.codecrew.moya.model.EventMap; import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.LanEvent; import fi.codecrew.moya.model.LanEvent;
import fi.codecrew.moya.model.Place; import fi.codecrew.moya.model.Place;
import fi.codecrew.moya.web.cdiview.GenericCDIView; import fi.codecrew.moya.web.cdiview.GenericCDIView;
import fi.codecrew.moya.web.cdiview.user.UserView;
@Named @Named
@ConversationScoped @ConversationScoped
...@@ -47,6 +50,8 @@ public class AjaxMapView extends GenericCDIView { ...@@ -47,6 +50,8 @@ public class AjaxMapView extends GenericCDIView {
private EventMap map; private EventMap map;
private Place place; private Place place;
private Integer mapId; private Integer mapId;
@Inject
private UserView userview;
public void initReserveMap() { public void initReserveMap() {
initMap(); initMap();
...@@ -57,8 +62,8 @@ public class AjaxMapView extends GenericCDIView { ...@@ -57,8 +62,8 @@ public class AjaxMapView extends GenericCDIView {
initMap(); initMap();
} }
private void initMap() { private EventMap initMap() {
if (mapId != null) { if (map == null && mapId != null) {
map = placebean.findMap(mapId); map = placebean.findMap(mapId);
} }
if (map == null) { if (map == null) {
...@@ -73,30 +78,60 @@ public class AjaxMapView extends GenericCDIView { ...@@ -73,30 +78,60 @@ public class AjaxMapView extends GenericCDIView {
} }
} }
} }
return map;
} }
public boolean isMgmtPermission() public Long getPlacesLeftToSelect() {
{ Long ret = placebean.selectablePlaceCount(initMap());
return permbean.hasPermission(MapPermission.MANAGE_OTHERS); logger.debug("Got {} places left for map {}", ret, initMap());
return ret;
} }
public Long getAvailablePlaces() {
Long ret = placebean.availablePlaceCount(initMap());
public void placeClicked() // logger.debug("Got {} availbale places for map {}", ret, initMap());
{ return ret;
Map<String, String> vmap = context.getExternalContext().getRequestParameterMap(); }
int placeId = Integer.parseInt(vmap.get("placeId"));
place = placebean.find(placeId); public boolean canUserBuy() {
logger.info("Found place {} with placeid {}", place, placeId); return permbean.hasPermission(MapPermission.BUY_PLACES);
if (place.isReservedFor(permbean.getCurrentUser())) }
{
placebean.releasePlace(place); public String buySelectedPlaces() {
} try {
else if (place.isBuyable() && !place.isTaken()) EventUser user = userview.getSelectedUser();
{ placebean.buySelectedPlaces(user);
placebean.reservePlace(place, permbean.getCurrentUser()); return "/place/myGroups";
} catch (BortalCatchableException e) {
addFaceMessage("mapView.errorWhileBuyingPlaces");
} }
return null;
} }
public boolean isMgmtPermission()
{
return permbean.hasPermission(MapPermission.MANAGE_OTHERS);
}
// public void placeClicked()
// {
//
// Map<String, String> vmap = context.getExternalContext().getRequestParameterMap();
// int placeId = Integer.parseInt(vmap.get("placeId"));
// place = placebean.find(placeId);
// logger.info("Found place {} with placeid {}", place, placeId);
// if (place.isReservedFor(permbean.getCurrentUser()))
// {
// placebean.releasePlace(place);
// }
// else if (place.isBuyable() && !place.isTaken())
// {
// placebean.reservePlace(place, permbean.getCurrentUser());
// }
// }
public String getTestVal() { public String getTestVal() {
return testVal; return testVal;
} }
...@@ -123,7 +158,7 @@ public class AjaxMapView extends GenericCDIView { ...@@ -123,7 +158,7 @@ public class AjaxMapView extends GenericCDIView {
public FacesContext getContext() { public FacesContext getContext() {
return context; return context;
} }
public void setContext(FacesContext context) { public void setContext(FacesContext context) {
this.context = context; this.context = context;
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!