Commit 53215047 by Tuukka Kivilahti

Merge branch 'productOption' into 'master'

Place moving and shop bug

Initial stuff for selfservice place moving. Menu, localisation, etc missing.

Bug where user can bypass product limits when creating bill


See merge request !351
2 parents 20f273a7 25472c7f
package fi.codecrew.moya.rest.v2.pojo;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
import com.wordnik.swagger.annotations.ApiModel;
import fi.codecrew.moya.model.Product;
@XmlRootElement()
@ApiModel(description = "Product")
public class ProductPojo {
public Integer id;
public String description;
public BigDecimal price;
public String name;
public static ProductPojo convert(Product prod) {
ProductPojo ret = new ProductPojo();
ret.id = prod.getId();
ret.name = prod.getName();
ret.price = prod.getPrice();
ret.description = prod.getDescription();
return ret;
}
public static List<ProductPojo> convert(List<Product> prods) {
ArrayList<ProductPojo> ret = new ArrayList<>();
for (Product p : prods) {
ret.add(convert(p));
}
return ret;
}
}
package fi.codecrew.moya.rest.v2;
import java.util.List;
import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.wordnik.swagger.annotations.Api;
import fi.codecrew.moya.beans.ProductBeanLocal;
import fi.codecrew.moya.rest.v2.pojo.ProductPojo;
@RequestScoped
@Path("/v2/product")
@Api(value = "/v2/product", description = "Product operations")
public class ProductRestView {
@EJB
private ProductBeanLocal prodbean;
@GET
@Path("/all")
@Produces(MediaType.APPLICATION_JSON)
public Response getAllProducts() {
List<ProductPojo> ret = ProductPojo.convert(prodbean.findProductsForEvent());
return Response.ok(ret).build();
}
}
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
package fi.codecrew.moya.beans; package fi.codecrew.moya.beans;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List; import java.util.List;
import javax.ejb.Local; import javax.ejb.Local;
...@@ -153,4 +154,6 @@ public interface PlaceBeanLocal { ...@@ -153,4 +154,6 @@ public interface PlaceBeanLocal {
*/ */
boolean isUnlockedPlaces(EventUser user); boolean isUnlockedPlaces(EventUser user);
void movePlaces(HashMap<Place, Place> change);
} }
\ No newline at end of file
...@@ -143,8 +143,7 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -143,8 +143,7 @@ public class PlaceBean implements PlaceBeanLocal {
@Override @Override
/** Use place slots */ /** Use place slots */
@Deprecated @Deprecated
public BigDecimal getTotalReservationPrice(Place newPlace) public BigDecimal getTotalReservationPrice(Place newPlace) {
{
return addAndCalcPrice(permbean.getCurrentUser(), newPlace); return addAndCalcPrice(permbean.getCurrentUser(), newPlace);
} }
...@@ -152,8 +151,7 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -152,8 +151,7 @@ public class PlaceBean implements PlaceBeanLocal {
@Override @Override
/** Use place slots */ /** Use place slots */
@Deprecated @Deprecated
public BigDecimal getTotalReservationPrice(EventUser user, Place newPlace) public BigDecimal getTotalReservationPrice(EventUser user, Place newPlace) {
{
return addAndCalcPrice(user, newPlace); return addAndCalcPrice(user, newPlace);
} }
...@@ -493,10 +491,14 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -493,10 +491,14 @@ public class PlaceBean implements PlaceBeanLocal {
@RolesAllowed({ MapPermission.S_BUY_PLACES, MapPermission.S_MANAGE_OTHERS }) @RolesAllowed({ MapPermission.S_BUY_PLACES, MapPermission.S_MANAGE_OTHERS })
public boolean releasePlace(Place place) { public boolean releasePlace(Place place) {
place = placeFacade.reload(place); place = placeFacade.reload(place);
EventUser user = permbean.getCurrentUser(); return releasePlacePriv(place) != null;
}
if (place.getGroup() != null || (!permbean.hasPermission(MapPermission.MANAGE_OTHERS) && !place.getCurrentUser().equals(user))) { private PlaceSlot releasePlacePriv(Place place) {
return false; EventUser user = permbean.getCurrentUser();
if (place.getGroup() != null || place.getCurrentUser() == null
|| (!permbean.hasPermission(MapPermission.MANAGE_OTHERS) && !place.getCurrentUser().equals(user))) {
return null;
} }
place.setCurrentUser(null); place.setCurrentUser(null);
...@@ -507,9 +509,7 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -507,9 +509,7 @@ public class PlaceBean implements PlaceBeanLocal {
slot.setPlace(null); slot.setPlace(null);
slot.setUsed(null); slot.setUsed(null);
} }
return slot;
return true;
} }
@Override @Override
...@@ -544,8 +544,7 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -544,8 +544,7 @@ public class PlaceBean implements PlaceBeanLocal {
place.setCurrentUser(null); place.setCurrentUser(null);
place.setReserveTime(null); place.setReserveTime(null);
if (place.getPlaceReserver() != null) if (place.getPlaceReserver() != null) {
{
GroupMembership res = place.getPlaceReserver(); GroupMembership res = place.getPlaceReserver();
if (res.getPlaceGroup().getMembers() != null) { if (res.getPlaceGroup().getMembers() != null) {
...@@ -821,13 +820,12 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -821,13 +820,12 @@ public class PlaceBean implements PlaceBeanLocal {
return ret; return ret;
} }
@Override @Override
public boolean isUnlockedPlaces(EventUser user) { public boolean isUnlockedPlaces(EventUser user) {
List<Place> places = placeFacade.findUsersReservations(user.getEvent(), user); List<Place> places = placeFacade.findUsersReservations(user.getEvent(), user);
for(Place p : places) { for (Place p : places) {
if(p.isReservedFor(user)) { if (p.isReservedFor(user)) {
return true; return true;
} }
} }
...@@ -835,4 +833,36 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -835,4 +833,36 @@ public class PlaceBean implements PlaceBeanLocal {
return false; return false;
} }
/**
* Allow user to move their places around.
*/
@Override
public void movePlaces(HashMap<Place, Place> change) {
EventUser user = permbean.getCurrentUser();
boolean manageOthers = permbean.hasPermission(MapPermission.MANAGE_OTHERS);
for (Entry<Place, Place> s : change.entrySet()) {
Place src = placeFacade.reload(s.getKey());
if (!manageOthers && !user.equals(src.getCurrentUser())
&& (src.getGroup() == null || !user.equals(src.getGroup().getCreator()))) {
throw new EJBAccessException("Trying to move places for another user without permissions!");
}
Place dst = placeFacade.reload(s.getValue());
if (!dst.isBuyable() || dst.isTaken()) {
throw new EJBException("Place already taken!!");
}
PlaceSlot srcSlot = releasePlacePriv(src);
if (srcSlot != null) {
// this place was reserved via a slot...
srcSlot.setPlace(dst);
srcSlot.setUsed(new Date());
}
dst.setCurrentUser(user);
dst.setReserveTime(Calendar.getInstance());
}
}
} }
...@@ -40,7 +40,6 @@ public class ApiApplicationFacade extends IntegerPkGenericFacade<ApiApplication> ...@@ -40,7 +40,6 @@ public class ApiApplicationFacade extends IntegerPkGenericFacade<ApiApplication>
} }
@EJB
public ApiApplication findByAppid(String appId) { public ApiApplication findByAppid(String appId) {
CriteriaBuilder cb = getEm().getCriteriaBuilder(); CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<ApiApplication> q = cb.createQuery(ApiApplication.class); CriteriaQuery<ApiApplication> q = cb.createQuery(ApiApplication.class);
......
...@@ -109,6 +109,7 @@ public class PlaceSlotFacade extends IntegerPkGenericFacade<PlaceSlot> { ...@@ -109,6 +109,7 @@ public class PlaceSlotFacade extends IntegerPkGenericFacade<PlaceSlot> {
CriteriaQuery<PlaceSlot> q = cb.createQuery(PlaceSlot.class); CriteriaQuery<PlaceSlot> q = cb.createQuery(PlaceSlot.class);
Root<PlaceSlot> root = q.from(PlaceSlot.class); Root<PlaceSlot> root = q.from(PlaceSlot.class);
Path<Bill> bill = root.get(PlaceSlot_.bill); Path<Bill> bill = root.get(PlaceSlot_.bill);
q.where(cb.equal(bill.get(Bill_.user), user), q.where(cb.equal(bill.get(Bill_.user), user),
cb.isNotNull(bill.get(Bill_.paidDate))); cb.isNotNull(bill.get(Bill_.paidDate)));
......
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:map="http://java.sun.com/jsf/composite/cditools/map"
xmlns:tools="http://java.sun.com/jsf/composite/cditools"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui">
<h:body>
<ui:composition template="#{sessionHandler.template}">
<f:metadata>
<f:event type="preRenderView"
listener="#{mapPlacechangeView.initView()}" />
</f:metadata>
<ui:define name="content">
<h:outputScript target="head" library="seatjs" name="d3.min.js" />
<h:outputScript target="head" library="seatjs" name="d3-tip.js" />
<h:outputScript target="head" library="seatjs" name="seatmap.js" />
<h:outputStylesheet library="seatjs" name="placemap.css" />
<!-- Place slot count -->
<h3>
<h:outputText value="#{i18n['mapView.yourPlaces']}" />
</h3>
<p:fragment id="placeselector">
<h:form>
<p:dataTable id="slottable" tableStyle="width: auto;" var="slot"
value="#{mapPlacechangeView.slots}">
<!-- rowStyleClass="#{mapPlacechangeView.srcPlace.contains(slot.place) ? 'selected' : 'unselected'}" -->
<p:column headerText="#{i18n['mapView.productcount.productname']}">
<h:outputText value="#{slot.src.product.name}" />
</p:column>
<p:column headerText="#{i18n['mapView.productcount.unused']}">
<h:outputText renderer="#{!empty slot.src.place}"
value="#{slot.src.place.name}" />
</p:column>
<p:column headerText="#{i18n['mapView.productcount.selected']}">
<h:outputText renderer="#{!empty slot.moving}"
value="#{slot.moving}" />
</p:column>
<p:column headerText="#{i18n['mapView.productcount.selected']}">
<h:outputText renderer="#{!empty slot.dst}"
value="#{slot.dst.name}" />
</p:column>
<p:column>
<ui:fragment rendered="#{empty slot.dst}">
<p:commandButton
actionListener="#{mapPlacechangeView.selectSlot}"
rendered="#{!slot.isMoving()}"
value="#{i18n['placemove.selectSlotForMove']}"
update="placeselector" />
<p:commandButton
actionListener="#{mapPlacechangeView.unselectSlot}"
rendered="#{slot.moving}" value="#{i18n['placemove.deselect']}"
update="placeselector" />
</ui:fragment>
</p:column>
</p:dataTable>
</h:form>
<script type="text/javascript">
toggleSuccess = #{mapPlacechangeView.toggleSuccess};
</script>
</p:fragment>
<h:form id="placemove">
<p:commandButton
rendered="#{ajaxMapView.canUserBuy()}"
value="#{i18n['mapPlacechange.commitMove']}"
actionListener="#{mapPlacechangeView.commitMove()}" />
</h:form>
<svg id="seatmap" style="margin: auto; border: 1px solid black;"
width="#{ajaxMapView.map.width}px"
height="#{ajaxMapView.map.height}px" />
<h:form>
<p:remoteCommand name="toggleDstPlace"
action="#{mapPlacechangeView.toggleDstPlace()}"
update="placeselector" oncomplete="afterToggle()"></p:remoteCommand>
</h:form>
<script type="text/javascript">
// <![CDATA[
px = placemap({
element: document.getElementById("seatmap"),
moyaurl: "#{request.contextPath}",
map_id: #{ajaxMapView.map.id},
});
px.toggleaction = function(d){
latestPlace = d;
toggleDstPlace([{name:"placeId", value:d.id} ])
};
function afterToggle(){
if(toggleSuccess){
if(latestPlace.state === "F"){
latestPlace.state = "T";
}else {
latestPlace.state = "F";
}
px.update_placeobj([latestPlace]);
}
}
// ]]>
</script>
<map:legend />
</ui:define>
</ui:composition>
</h:body>
</html>
\ No newline at end of file
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:map="http://java.sun.com/jsf/composite/cditools/map"
xmlns:tools="http://java.sun.com/jsf/composite/cditools"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui">
<h:body>
<ui:composition template="#{sessionHandler.template}">
<f:metadata>
<f:event type="preRenderView" listener="#{ajaxMapView.initViewMap()}" />
</f:metadata>
<ui:param name="thispage" value="page.place.placemap" />
<ui:define name="content">
<!-- <h:form>
<p:remoteCommand name="placeClicker" update=":fbdiag"
action="#{ajaxMapView.placeClicked()}" />
</h:form>
-->
<p:dialog rendered="#{ajaxMapView.isMgmtPermission()}"
visible="#{!empty ajaxMapView.place}" id="fbdiag">
Clicked place name : #{ajaxMapView.place.name};
<h:link rendered="#{!empty ajaxMapView.place}" outcome="/place/edit">
<f:param name="placeid" value="#{ajaxMapView.place.id}" />
Muokkaa
</h:link>
</p:dialog>
<h:outputScript target="head" library="seatjs" name="d3.min.js" />
<h:outputScript target="head" library="seatjs" name="d3-tip.js" />
<h:outputScript target="head" library="seatjs" name="seatmap.js" />
<h:outputStylesheet library="seatjs" name="placemap.css" />
<ui:fragment rendered="#{not ajaxMapView.queueEnabled}">
<div style="margin: 5px;">
<h:form id="placeselectform">
<p:commandButton rendered="#{ajaxMapView.canUserBuy()}"
value="#{i18n['mapView.buyPlaces']}"
action="#{ajaxMapView.buySelectedPlaces()}" ajax="false" />
</h:form>
</div>
</ui:fragment>
<button onclick="px.update()">#{i18n['neomap.updateMap']}</button>
<br />
<svg id="seatmap" style="margin: auto; border: 1px solid black;"
width="#{ajaxMapView.map.width}px"
height="#{ajaxMapView.map.height}px" />
<script type="text/javascript">
// If queue is enabled, do not allow clicking of places.
px = placemap({
element : document.getElementById("seatmap"),
moyaurl : "#{request.contextPath}",
map_id : #{ajaxMapView.map.id},
placeurl : "/rest/placemap/v1/#{ajaxMapView.map.id}/allplaces",
});
px.toggleaction = #{ajaxMapView.queueEnabled?'undefined':'px.toggle_place'};
</script>
<map:legend />
</ui:define>
</ui:composition>
</h:body>
</html>
\ No newline at end of file
...@@ -53,11 +53,13 @@ ...@@ -53,11 +53,13 @@
<p:outputPanel rendered="#{!cart.product.usershopAutoproduct}"> <p:outputPanel rendered="#{!cart.product.usershopAutoproduct}">
<p:commandButton action="#{productShopView.addMinusOne}" value="#{i18n['productshop.minusOne']}" update="billcart" /> <p:commandButton action="#{productShopView.addMinusOne}" value="#{i18n['productshop.minusOne']}" update="billcart" />
<p:inputText size="2" id="cartcount" escape="false" value="#{cart.count}">
<f:ajax render="@form" <p:inputText onblur="$('.focusdisabler').attr('disabled',false).removeClass('ui-state-disabled'); $('.focusenabler').attr('disabled',true).addClass('ui-state-disabled')" onfocus="$('.focusdisabler').attr('disabled',true).addClass('ui-state-disabled'); $('.focusenabler').attr('disabled',false).removeClass('ui-state-disabled');"
listener="#{productShopView.countChangeListener}" /> size="2" id="cartcount" escape="false" value="#{cart.count}" >
<f:ajax render="@form" listener="#{productShopView.countChangeListener}" />
<f:convertNumber maxFractionDigits="2" minFractionDigits="0" /> <f:convertNumber maxFractionDigits="2" minFractionDigits="0" />
</p:inputText> </p:inputText>
<p:commandButton action="#{productShopView.addOne}" update="billcart" value="#{i18n['productshop.plusOne']}" /> <p:commandButton action="#{productShopView.addOne}" update="billcart" value="#{i18n['productshop.plusOne']}" />
</p:outputPanel> </p:outputPanel>
</p:column> </p:column>
...@@ -146,10 +148,13 @@ ...@@ -146,10 +148,13 @@
function initPaymentButtons() { function initPaymentButtons() {
}; };
</script> </script>
<p:commandButton ajax="false" onerror="location.reload(true);" <p:commandButton styleClass="focusdisabler" ajax="false" onerror="location.reload(true);"
action="#{cc.attrs.commitaction}" id="commitbutton-botton" action="#{cc.attrs.commitaction}" id="commitbutton-botton"
value="#{cc.attrs.commitValue}" /> value="#{cc.attrs.commitValue}" />
<p:commandButton actionListener="#{productShopView.countChangeListener}" onclick="return false;" styleClass="focusenabler" disabled="true" value="#{i18n['shop.updatePrices']}">
</p:commandButton>
......
...@@ -438,6 +438,10 @@ function placemap(opts) ...@@ -438,6 +438,10 @@ function placemap(opts)
} }
}; };
px.update_placeobj = function (d) {
draw_places(d, false);
}
px.update_place = function (place_id) px.update_place = function (place_id)
{ {
if (place_id === undefined) place_id = px.clicked_place; if (place_id === undefined) place_id = px.clicked_place;
......
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:body>
<ui:composition template="#{sessionHandler.template}">
<f:metadata>
</f:metadata>
<ui:define name="title">
<h1>#{i18n['page.product.shopClosed.header']}</h1>
</ui:define>
<ui:define name="content">
Shop Closed!!
</ui:define>
</ui:composition>
</h:body>
</html>
\ No newline at end of file
package fi.codecrew.moya.rest.placemap.v1;
import javax.enterprise.context.RequestScoped;
import javax.ws.rs.Consumes;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@RequestScoped
@Path("/placemap/v1")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON + "; charset=UTF-8" })
public class EventInfoRestViewV1 {
}
package fi.codecrew.moya.rest.placemap.v1;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fi.codecrew.moya.beans.BarcodeBeanLocal;
import fi.codecrew.moya.beans.EventBeanLocal;
import fi.codecrew.moya.beans.PermissionBeanLocal;
import fi.codecrew.moya.beans.PlaceBeanLocal;
import fi.codecrew.moya.beans.UserBeanLocal;
import fi.codecrew.moya.beans.map.QueueBeanLocal;
import fi.codecrew.moya.enums.apps.MapPermission;
import fi.codecrew.moya.enums.apps.UserPermission;
import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.LanEvent;
import fi.codecrew.moya.model.Place;
import fi.codecrew.moya.rest.PojoUtils;
import fi.codecrew.moya.rest.pojo.placemap.v1.IntegerRoot;
import fi.codecrew.moya.rest.pojo.placemap.v1.PlacemapMapRootPojo;
import fi.codecrew.moya.rest.pojo.placemap.v1.SimplePlacePojo;
import fi.codecrew.moya.rest.pojo.placemap.v1.SimplePlacelistRoot;
import fi.codecrew.moya.utilities.PasswordFunctions;
import fi.codecrew.moya.web.cdiview.map.MapPlacechangeView;
import fi.codecrew.moya.web.cdiview.map.MapPlacechangeView.MoveContainer;
import fi.codecrew.moya.web.cdiview.user.UserView;
@RequestScoped
@Path("/placemove/v1")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON + "; charset=UTF-8" })
public class PlacechangeRestViewV1 {
@Inject
private MapPlacechangeView placechangeView;
@EJB
private PermissionBeanLocal permbean;
@GET
@Path("/destinations")
public SimplePlacelistRoot getDestinations() {
List<Place> dsts = new ArrayList<>();
for (MoveContainer mc : placechangeView.getMoveContainers()) {
dsts.add(mc.getDst());
}
SimplePlacelistRoot ret = PojoUtils.parseSimplePlaces(dsts, permbean.getCurrentUser(), false);
for (SimplePlacePojo p : ret.getPlaces()) {
p.setState("T");
}
return ret;
}
}
...@@ -48,7 +48,7 @@ public class UserRestViewV2 { ...@@ -48,7 +48,7 @@ public class UserRestViewV2 {
PojoFactoryV2 pojoFactory; PojoFactoryV2 pojoFactory;
@GET @GET
@Path("/") @Path("/get")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Find user", response = UserPojo.class) @ApiOperation(value = "Find user", response = UserPojo.class)
public Response getEventUser(@QueryParam("email") @ApiParam("Email address") String email, public Response getEventUser(@QueryParam("email") @ApiParam("Email address") String email,
......
package fi.codecrew.moya.web.cdiview.map;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.EJB;
import javax.enterprise.context.ConversationScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.ListDataModel;
import javax.inject.Named;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fi.codecrew.moya.beans.PlaceBeanLocal;
import fi.codecrew.moya.beans.UserBeanLocal;
import fi.codecrew.moya.enums.apps.MapPermission;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.Place;
import fi.codecrew.moya.model.PlaceSlot;
import fi.codecrew.moya.web.cdiview.GenericCDIView;
@Named
@ConversationScoped
public class MapPlacechangeView extends GenericCDIView {
private static final Logger logger = LoggerFactory.getLogger(MapPlacechangeView.class);
private static final long serialVersionUID = 1L;
private Integer userId;
private EventUser user;
@EJB
private UserBeanLocal userbean;
@EJB
private PlaceBeanLocal placebean;
private ListDataModel<MoveContainer> slots;
private List<MoveContainer> moveContainers;
private boolean toggleSuccess;
public static class MoveContainer {
private boolean moving = false;
private final PlaceSlot src;
private Place dst;
public MoveContainer(PlaceSlot p) {
this.src = p;
}
public static List<MoveContainer> init(List<PlaceSlot> placeslots) {
ArrayList<MoveContainer> ret = new ArrayList<>();
for (PlaceSlot p : placeslots) {
ret.add(new MoveContainer(p));
}
return ret;
}
public boolean isMoving() {
return moving;
}
public void setMoving(boolean moving) {
this.moving = moving;
}
public Place getDst() {
return dst;
}
public void setDst(Place dst) {
this.dst = dst;
}
public PlaceSlot getSrc() {
return src;
}
}
public void initView() {
// If we are overriding user, check permission.
if (getSlots() == null) {
if (userId != null && super.requirePermissions(MapPermission.MANAGE_OTHERS)) {
user = userbean.findByUserId(userId, false);
} else if (super.requirePermissions(MapPermission.BUY_PLACES)) {
user = permbean.getCurrentUser();
} else {
return;
}
super.beginConversation();
moveContainers = MoveContainer.init(placebean.getPlaceslots(user));
slots = new ListDataModel<MoveContainer>(moveContainers);
}
}
public void commitMove(){
HashMap<Place, Place> change = new HashMap<Place,Place>();
for(MoveContainer s : slots){
if(s.isMoving() && s.getDst() != null){
change.put(s.getSrc().getPlace(), s.getDst());
}
}
placebean.movePlaces(change);
}
public void toggleDstPlace() {
Map<String, String> paramMap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
Integer placeId = new Integer(paramMap.get("placeId"));
Place place = placebean.find(placeId);
setToggleSuccess(false);
for (MoveContainer mc : getMoveContainers()) {
if (place.equals(mc.getSrc().getPlace())) {
setSlotState(mc, !mc.isMoving());
return;
}
if (place.equals(mc.getDst())) {
setToggleSuccess(true);
mc.setDst(null);
return;
}
}
if (!place.isBuyable() || place.isTaken()) {
return;
}
for (MoveContainer mc : moveContainers) {
if (mc.isMoving() && mc.dst == null && mc.getSrc().getProduct().equals(place.getProduct())) {
setToggleSuccess(true);
mc.setDst(place);
return;
}
}
}
public String selectSlot() {
setSlotState(slots.getRowData(), true);
return null;
}
private void setSlotState(MoveContainer mc, boolean moving) {
if (!moving && mc.getDst() != null) {
return;
}
mc.setMoving(moving);
}
public String unselectSlot() {
setSlotState(getSlots().getRowData(), false);
return null;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public EventUser getUser() {
return user;
}
public void setUser(EventUser user) {
this.user = user;
}
public List<MoveContainer> getMoveContainers() {
return moveContainers;
}
public void setMoveContainers(List<MoveContainer> moveContainers) {
this.moveContainers = moveContainers;
}
public ListDataModel<MoveContainer> getSlots() {
return slots;
}
public void setSlots(ListDataModel<MoveContainer> slots) {
this.slots = slots;
}
public boolean isToggleSuccess() {
return toggleSuccess;
}
public void setToggleSuccess(boolean toggleSuccess) {
this.toggleSuccess = toggleSuccess;
}
}
...@@ -20,6 +20,7 @@ package fi.codecrew.moya.web.cdiview.shop; ...@@ -20,6 +20,7 @@ package fi.codecrew.moya.web.cdiview.shop;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
...@@ -27,6 +28,8 @@ import java.util.Map; ...@@ -27,6 +28,8 @@ import java.util.Map;
import javax.ejb.EJB; import javax.ejb.EJB;
import javax.enterprise.context.ConversationScoped; import javax.enterprise.context.ConversationScoped;
import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import javax.faces.model.ListDataModel; import javax.faces.model.ListDataModel;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
...@@ -41,6 +44,7 @@ import fi.codecrew.moya.beans.UserBeanLocal; ...@@ -41,6 +44,7 @@ import fi.codecrew.moya.beans.UserBeanLocal;
import fi.codecrew.moya.enums.apps.ShopPermission; import fi.codecrew.moya.enums.apps.ShopPermission;
import fi.codecrew.moya.model.Bill; import fi.codecrew.moya.model.Bill;
import fi.codecrew.moya.model.EventUser; import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.LanEvent;
import fi.codecrew.moya.model.LanEventProperty; import fi.codecrew.moya.model.LanEventProperty;
import fi.codecrew.moya.model.LanEventPropertyKey; import fi.codecrew.moya.model.LanEventPropertyKey;
import fi.codecrew.moya.model.Product; import fi.codecrew.moya.model.Product;
...@@ -118,7 +122,19 @@ public class ProductShopView extends GenericCDIView { ...@@ -118,7 +122,19 @@ public class ProductShopView extends GenericCDIView {
public void initBillView() { public void initBillView() {
if (requirePermissions(ShopPermission.LIST_USERPRODUCTS) && shoppingcart == null) { if (requirePermissions(ShopPermission.LIST_USERPRODUCTS) && shoppingcart == null) {
shoppingcart = new ListDataModel<ProductShopItem>(ProductShopItem.productList(productBean.listUserShoppableProducts(), userView.getSelectedUser()));
LanEvent event = eventbean.getCurrentEvent();
Date now = new Date();
if ((event.getTicketSalesBegin() != null && now.before(event.getTicketSalesBegin()))
|| (event.getEndTime() != null && now.after(event.getEndTime()))) {
FacesContext fc = FacesContext.getCurrentInstance();
NavigationHandler nh = fc.getApplication().getNavigationHandler();
nh.handleNavigation(fc, null, "/shop/shopClosed?faces-redirect=true");
return;
}
shoppingcart = new ListDataModel<ProductShopItem>(
ProductShopItem.productList(productBean.listUserShoppableProducts(), userView.getSelectedUser()));
for (ProductShopItem item : shoppingcart) { for (ProductShopItem item : shoppingcart) {
psiHelper.updateProductShopItemCount(item); psiHelper.updateProductShopItemCount(item);
...@@ -301,8 +317,7 @@ public class ProductShopView extends GenericCDIView { ...@@ -301,8 +317,7 @@ public class ProductShopView extends GenericCDIView {
ret = ret.add(getCash()); ret = ret.add(getCash());
ret = ret.subtract(getCartPrice()); ret = ret.subtract(getCartPrice());
logger.info("User accountbalance {}, cash{}, total {}. retBalance {}", logger.info("User accountbalance {}, cash{}, total {}. retBalance {}",
new Object[] { userView.getSelectedUser().getAccountBalance(), getCash(), new Object[] { userView.getSelectedUser().getAccountBalance(), getCash(), getCartPrice(), ret });
getCartPrice(), ret });
return ret; return ret;
} }
...@@ -320,6 +335,10 @@ public class ProductShopView extends GenericCDIView { ...@@ -320,6 +335,10 @@ public class ProductShopView extends GenericCDIView {
} }
public String commitBillCart() { public String commitBillCart() {
for(ProductShopItem i : shoppingcart){
psiHelper.updateProductShopItemCount(i);
}
updateAllCartLimits(); updateAllCartLimits();
logger.debug("Committing billCart"); logger.debug("Committing billCart");
......
...@@ -616,6 +616,8 @@ off = Off ...@@ -616,6 +616,8 @@ off = Off
on = On on = On
option.setAsDefault = set as default
orgRoleRequest.discardRequest = Discard request orgRoleRequest.discardRequest = Discard request
orgRoleRequest.handledNotes = Handling notes orgRoleRequest.handledNotes = Handling notes
orgRoleRequest.id = ID orgRoleRequest.id = ID
...@@ -725,6 +727,7 @@ place.product = Product ...@@ -725,6 +727,7 @@ place.product = Product
place.release = Release this place place.release = Release this place
place.releasetime = Release time place.releasetime = Release time
place.reserveForUser = Reserve for the user place.reserveForUser = Reserve for the user
place.reservetime = Reservetime
place.send = Transfer place place.send = Transfer place
place.width = Width place.width = Width
...@@ -762,7 +765,7 @@ placegroupView.editplace = Edit place ...@@ -762,7 +765,7 @@ placegroupView.editplace = Edit place
placegroupview.groupCreator = Orderer placegroupview.groupCreator = Orderer
placegroupview.header = My places placegroupview.header = My places
placegroupview.lockPlaces=Lock places placegroupview.lockPlaces = Lock places
placegroupview.noMemberships = No places placegroupview.noMemberships = No places
placegroupview.owner = Owner placegroupview.owner = Owner
placegroupview.placeReleaseFailed = Releasing place failed! placegroupview.placeReleaseFailed = Releasing place failed!
...@@ -774,8 +777,8 @@ placegroupview.reservationProduct = Ticket ...@@ -774,8 +777,8 @@ placegroupview.reservationProduct = Ticket
placegroupview.reserveForSelf = Select the place for yourself placegroupview.reserveForSelf = Select the place for yourself
placegroupview.token = Place token / user placegroupview.token = Place token / user
placegroupview.toptext = \ placegroupview.toptext = \
placegroupview.unlockedPlacesNotification = You have unlocked places, you must lock them before you can see your tickets!
placegroupview.unlockedPlacesNotification=You have unlocked places, you must lock them before you can see your tickets\!
placeslot.add = Add place slot placeslot.add = Add place slot
placeslot.bill = Bill placeslot.bill = Bill
placeslot.id = ID placeslot.id = ID
...@@ -823,10 +826,12 @@ product.color = Color in UI ...@@ -823,10 +826,12 @@ product.color = Color in UI
product.create = Create product product.create = Create product
product.createDiscount = Add volume discount product.createDiscount = Add volume discount
product.createLimit = Create product limit product.createLimit = Create product limit
product.createProductOptionGroup = Create product feature
product.description = Description product.description = Description
product.edit = Edit product.edit = Edit
product.expired = Expired product.expired = Expired
product.inventoryQuantity = Inventory count product.inventoryQuantity = Inventory count
product.minBuyCount = Minium buy count
product.name = Product name product.name = Product name
product.paid = Paid product.paid = Paid
product.prepaid = Prepaid product.prepaid = Prepaid
...@@ -859,6 +864,15 @@ productLimit.sort = Sort number ...@@ -859,6 +864,15 @@ productLimit.sort = Sort number
productLimit.type = Limit type productLimit.type = Limit type
productLimit.upperLimit = Upper limit productLimit.upperLimit = Upper limit
productOption.add = Add new option
productOption.name = Option name
productOption.title = Options
productOptionGroup.default = Default option
productOptionGroup.name = Name
productOptionGroup.required = Required
productOptionGroup.title = Product feature
productShopView.readBarcode = Read barcode productShopView.readBarcode = Read barcode
products.create = Create product products.create = Create product
...@@ -1002,6 +1016,7 @@ shop.toAccountValue = To account ...@@ -1002,6 +1016,7 @@ shop.toAccountValue = To account
shop.totalPrice = Total shop.totalPrice = Total
shop.transactionTotal = Transaction total shop.transactionTotal = Transaction total
shop.unitdiscount = Discount shop.unitdiscount = Discount
shop.updatePrices = Update prices
shop.user = Selling to shop.user = Selling to
sidebar.bill.list = My bills sidebar.bill.list = My bills
...@@ -1285,6 +1300,7 @@ tournaments.admin.edit_rules = Edit rules ...@@ -1285,6 +1300,7 @@ tournaments.admin.edit_rules = Edit rules
tournaments.admin.edit_tournament = Edit tournament tournaments.admin.edit_tournament = Edit tournament
tournaments.admin.game_description = Game description tournaments.admin.game_description = Game description
tournaments.admin.game_name = Game name tournaments.admin.game_name = Game name
tournaments.admin.open_for_roles = Roles allowing registeration
tournaments.admin.registration_time_constraints = Registration time tournaments.admin.registration_time_constraints = Registration time
tournaments.admin.remove_confirmation_text = Are you sure you want to remove this tournament? THIS CANNOT BE REVERSED! tournaments.admin.remove_confirmation_text = Are you sure you want to remove this tournament? THIS CANNOT BE REVERSED!
tournaments.admin.remove_title = Confirm tournament removal tournaments.admin.remove_title = Confirm tournament removal
...@@ -1560,15 +1576,3 @@ voting.create.voteEnd = Voting close ...@@ -1560,15 +1576,3 @@ voting.create.voteEnd = Voting close
voting.create.voteStart = Voting start voting.create.voteStart = Voting start
yes = Yes yes = Yes
tournaments.admin.open_for_roles=Roles allowing registeration
productOptionGroup.name=Name
product.createProductOptionGroup=Create product feature
productOptionGroup.required=Required
productOption.name=Option name
productOption.add=Add new option
productOption.title=Options
productOptionGroup.title=Product feature
productOptionGroup.default=Default option
option.setAsDefault=set as default
place.reservetime=Reservetime
product.minBuyCount=Minium buy count
...@@ -846,6 +846,8 @@ off = Off ...@@ -846,6 +846,8 @@ off = Off
on = On on = On
option.setAsDefault = set as default
org.hibernate.validator.constraints.Email.message = not a well-formed email address org.hibernate.validator.constraints.Email.message = not a well-formed email address
org.hibernate.validator.constraints.Length.message = length must be between {min} and {max} org.hibernate.validator.constraints.Length.message = length must be between {min} and {max}
org.hibernate.validator.constraints.NotEmpty.message = may not be empty org.hibernate.validator.constraints.NotEmpty.message = may not be empty
...@@ -984,6 +986,7 @@ place.product = Product ...@@ -984,6 +986,7 @@ place.product = Product
place.release = Release this place place.release = Release this place
place.releasetime = Release time place.releasetime = Release time
place.reserveForUser = Reserve for the user place.reserveForUser = Reserve for the user
place.reservetime = Reservetime
place.send = Transfer place place.send = Transfer place
place.width = Width place.width = Width
...@@ -1021,7 +1024,7 @@ placegroupView.editplace = Edit place ...@@ -1021,7 +1024,7 @@ placegroupView.editplace = Edit place
placegroupview.groupCreator = Orderer placegroupview.groupCreator = Orderer
placegroupview.header = My places placegroupview.header = My places
placegroupview.lockPlaces=Lock places placegroupview.lockPlaces = Lock places
placegroupview.noMemberships = No places placegroupview.noMemberships = No places
placegroupview.owner = Owner placegroupview.owner = Owner
placegroupview.placeReleaseFailed = Releasing place failed! placegroupview.placeReleaseFailed = Releasing place failed!
...@@ -1032,8 +1035,8 @@ placegroupview.reservationName = Place ...@@ -1032,8 +1035,8 @@ placegroupview.reservationName = Place
placegroupview.reservationProduct = Ticket placegroupview.reservationProduct = Ticket
placegroupview.reserveForSelf = Select the place for yourself placegroupview.reserveForSelf = Select the place for yourself
placegroupview.token = Place token / user placegroupview.token = Place token / user
placegroupview.unlockedPlacesNotification = You have unlocked places, you must lock them before you can see your tickets!
placegroupview.unlockedPlacesNotification=You have unlocked places, you must lock them before you can see your tickets\!
placeslot.add = Add place slot placeslot.add = Add place slot
placeslot.bill = Bill placeslot.bill = Bill
placeslot.id = ID placeslot.id = ID
...@@ -1083,10 +1086,12 @@ product.color = Color in UI ...@@ -1083,10 +1086,12 @@ product.color = Color in UI
product.create = Create product product.create = Create product
product.createDiscount = Add volume discount product.createDiscount = Add volume discount
product.createLimit = Create product limit product.createLimit = Create product limit
product.createProductOptionGroup = Create product feature
product.description = Description product.description = Description
product.edit = Edit product.edit = Edit
product.expired = Expired product.expired = Expired
product.inventoryQuantity = Inventory count product.inventoryQuantity = Inventory count
product.minBuyCount = Minium buy count
product.name = Product name product.name = Product name
product.paid = Paid product.paid = Paid
product.prepaid = Prepaid product.prepaid = Prepaid
...@@ -1121,6 +1126,15 @@ productLimit.sort = Sort number ...@@ -1121,6 +1126,15 @@ productLimit.sort = Sort number
productLimit.type = Limit type productLimit.type = Limit type
productLimit.upperLimit = Upper limit productLimit.upperLimit = Upper limit
productOption.add = Add new option
productOption.name = Option name
productOption.title = Options
productOptionGroup.default = Default option
productOptionGroup.name = Name
productOptionGroup.required = Required
productOptionGroup.title = Product feature
productShopView.readBarcode = Read barcode productShopView.readBarcode = Read barcode
products.create = Create product products.create = Create product
...@@ -1268,6 +1282,7 @@ shop.toAccountValue = To account ...@@ -1268,6 +1282,7 @@ shop.toAccountValue = To account
shop.totalPrice = Total shop.totalPrice = Total
shop.transactionTotal = Transaction total shop.transactionTotal = Transaction total
shop.unitdiscount = Discount shop.unitdiscount = Discount
shop.updatePrices = Update prices
shop.user = Selling to shop.user = Selling to
sidebar.bill.list = My bills sidebar.bill.list = My bills
...@@ -1556,6 +1571,7 @@ tournaments.admin.edit_rules = Edit rules ...@@ -1556,6 +1571,7 @@ tournaments.admin.edit_rules = Edit rules
tournaments.admin.edit_tournament = Edit tournament tournaments.admin.edit_tournament = Edit tournament
tournaments.admin.game_description = Game description tournaments.admin.game_description = Game description
tournaments.admin.game_name = Game name tournaments.admin.game_name = Game name
tournaments.admin.open_for_roles = Roles allowing registeration
tournaments.admin.registration_time_constraints = Registration time tournaments.admin.registration_time_constraints = Registration time
tournaments.admin.remove_confirmation_text = Are you sure you want to remove this tournament? THIS CANNOT BE REVERSED! tournaments.admin.remove_confirmation_text = Are you sure you want to remove this tournament? THIS CANNOT BE REVERSED!
tournaments.admin.remove_title = Confirm tournament removal tournaments.admin.remove_title = Confirm tournament removal
...@@ -1836,15 +1852,3 @@ voting.create.voteEnd = Voting close ...@@ -1836,15 +1852,3 @@ voting.create.voteEnd = Voting close
voting.create.voteStart = Voting start voting.create.voteStart = Voting start
yes = Yes yes = Yes
tournaments.admin.open_for_roles=Roles allowing registeration
productOptionGroup.name=Name
product.createProductOptionGroup=Create product feature
productOptionGroup.required=Required
productOption.name=Option name
productOption.add=Add new option
productOption.title=Options
productOptionGroup.title=Product feature
productOptionGroup.default=Default option
option.setAsDefault=set as default
place.reservetime=Reservetime
product.minBuyCount=Minium buy count
...@@ -849,6 +849,8 @@ off = Poissa ...@@ -849,6 +849,8 @@ off = Poissa
on = P\u00E4\u00E4ll\u00E4 on = P\u00E4\u00E4ll\u00E4
option.setAsDefault = Aseta oletukseksi
org.hibernate.validator.constraints.Email.message = V\u00E4\u00E4rin muotoiltu s\u00E4hk\u00F6postiosoite org.hibernate.validator.constraints.Email.message = V\u00E4\u00E4rin muotoiltu s\u00E4hk\u00F6postiosoite
org.hibernate.validator.constraints.Length.message = length must be between {min} and {max} org.hibernate.validator.constraints.Length.message = length must be between {min} and {max}
org.hibernate.validator.constraints.NotEmpty.message = may not be empty org.hibernate.validator.constraints.NotEmpty.message = may not be empty
...@@ -971,6 +973,7 @@ place.product = Tuote ...@@ -971,6 +973,7 @@ place.product = Tuote
place.release = Vapauta paikka place.release = Vapauta paikka
place.releasetime = Vapautusaika place.releasetime = Vapautusaika
place.reserveForUser = Varaa k\u00E4ytt\u00E4j\u00E4lle place.reserveForUser = Varaa k\u00E4ytt\u00E4j\u00E4lle
place.reservetime = Varaamisaika
place.send = Siirr\u00E4 paikka place.send = Siirr\u00E4 paikka
place.width = Leveys place.width = Leveys
...@@ -1008,7 +1011,7 @@ placegroupView.editplace = Muokkaa paikkaa ...@@ -1008,7 +1011,7 @@ placegroupView.editplace = Muokkaa paikkaa
placegroupview.groupCreator = Tilaaja placegroupview.groupCreator = Tilaaja
placegroupview.header = Omat paikat placegroupview.header = Omat paikat
placegroupview.lockPlaces=Lukitse paikat placegroupview.lockPlaces = Lukitse paikat
placegroupview.noMemberships = Ei omia paikkoja placegroupview.noMemberships = Ei omia paikkoja
placegroupview.owner = Omistaja placegroupview.owner = Omistaja
placegroupview.placeReleaseFailed = Paikan vapauttaminen ep\u00E4onnistui! placegroupview.placeReleaseFailed = Paikan vapauttaminen ep\u00E4onnistui!
...@@ -1019,8 +1022,8 @@ placegroupview.reservationName = Paikka ...@@ -1019,8 +1022,8 @@ placegroupview.reservationName = Paikka
placegroupview.reservationProduct = Lippu placegroupview.reservationProduct = Lippu
placegroupview.reserveForSelf = Valitse paikka itsellesi placegroupview.reserveForSelf = Valitse paikka itsellesi
placegroupview.token = Paikkakoodi / k\u00E4ytt\u00E4j\u00E4 placegroupview.token = Paikkakoodi / k\u00E4ytt\u00E4j\u00E4
placegroupview.unlockedPlacesNotification = Sinulla on lukitsemattomia paikkoja, sinun tulee lukita ne ennenkuin voit tarkastella lippuasi!
placegroupview.unlockedPlacesNotification=Sinulla on lukitsemattomia paikkoja, sinun tulee lukita ne ennenkuin voit tarkastella lippuasi\!
placeslot.add = Lis\u00E4\u00E4 paikkaslotti placeslot.add = Lis\u00E4\u00E4 paikkaslotti
placeslot.bill = Lasku placeslot.bill = Lasku
placeslot.id = ID placeslot.id = ID
...@@ -1070,10 +1073,12 @@ product.color = V\u00E4ri k\u00E4ytt\u00F6liittym\u00 ...@@ -1070,10 +1073,12 @@ product.color = V\u00E4ri k\u00E4ytt\u00F6liittym\u00
product.create = Luo tuote product.create = Luo tuote
product.createDiscount = Lis\u00E4\u00E4 m\u00E4\u00E4r\u00E4alennus product.createDiscount = Lis\u00E4\u00E4 m\u00E4\u00E4r\u00E4alennus
product.createLimit = Luo tuoterajoite product.createLimit = Luo tuoterajoite
product.createProductOptionGroup = Luo ominaisuus
product.description = Kuvaus product.description = Kuvaus
product.edit = Muokkaa product.edit = Muokkaa
product.expired = Vanhentuneet product.expired = Vanhentuneet
product.inventoryQuantity = Varastotilanne product.inventoryQuantity = Varastotilanne
product.minBuyCount = Ostettava v\u00E4hint\u00E4\u00E4n
product.name = Tuotteen nimi product.name = Tuotteen nimi
product.paid = Maksettu product.paid = Maksettu
product.prepaid = Prepaid product.prepaid = Prepaid
...@@ -1108,6 +1113,15 @@ productLimit.sort = J\u00E4rjestysnumero ...@@ -1108,6 +1113,15 @@ productLimit.sort = J\u00E4rjestysnumero
productLimit.type = Rajoitteen tyyppi productLimit.type = Rajoitteen tyyppi
productLimit.upperLimit = Yl\u00E4rajoite productLimit.upperLimit = Yl\u00E4rajoite
productOption.add = Lis\u00E4\u00E4 uusi vaihtoehto
productOption.name = Vaihtoehdon nimi
productOption.title = Ominaisuuden vaihtoehdot
productOptionGroup.default = Oletusvaihtoehto
productOptionGroup.name = Nimi
productOptionGroup.required = Vaaditaan
productOptionGroup.title = Tuotevaihtoehto
productShopView.readBarcode = Lue viivakoodi productShopView.readBarcode = Lue viivakoodi
products.create = Luo tuote products.create = Luo tuote
...@@ -1255,6 +1269,7 @@ shop.toAccountValue = Tilille ...@@ -1255,6 +1269,7 @@ shop.toAccountValue = Tilille
shop.totalPrice = Yhteens\u00E4 shop.totalPrice = Yhteens\u00E4
shop.transactionTotal = Tapahtuma yhteens\u00E4 shop.transactionTotal = Tapahtuma yhteens\u00E4
shop.unitdiscount = Alennus shop.unitdiscount = Alennus
shop.updatePrices = P\u00E4ivit\u00E4 hinnat
shop.user = Myyd\u00E4\u00E4n shop.user = Myyd\u00E4\u00E4n
sidebar.bill.list = Omat laskut sidebar.bill.list = Omat laskut
...@@ -1543,6 +1558,7 @@ tournaments.admin.edit_rules = Muokkaa s\u00E ...@@ -1543,6 +1558,7 @@ tournaments.admin.edit_rules = Muokkaa s\u00E
tournaments.admin.edit_tournament = Muokkaa turnausta tournaments.admin.edit_tournament = Muokkaa turnausta
tournaments.admin.game_description = Pelin kuvaus tournaments.admin.game_description = Pelin kuvaus
tournaments.admin.game_name = Pelin nimi tournaments.admin.game_name = Pelin nimi
tournaments.admin.open_for_roles = Rekister\u00F6itymiseen oikeuttavat ryhm\u00E4t
tournaments.admin.registration_time_constraints = Rekister\u00F6itymisaika tournaments.admin.registration_time_constraints = Rekister\u00F6itymisaika
tournaments.admin.remove_confirmation_text = Oletko varma ett\u00E4 haluat poistaa turnauksen? T\u00C4T\u00C4 EI VOI PERUUTTAA! tournaments.admin.remove_confirmation_text = Oletko varma ett\u00E4 haluat poistaa turnauksen? T\u00C4T\u00C4 EI VOI PERUUTTAA!
tournaments.admin.remove_title = Vahvista turnauksen poisto tournaments.admin.remove_title = Vahvista turnauksen poisto
...@@ -1823,15 +1839,3 @@ voting.create.voteEnd = \u00C4\u00E4nestys kiinni ...@@ -1823,15 +1839,3 @@ voting.create.voteEnd = \u00C4\u00E4nestys kiinni
voting.create.voteStart = \u00C4\u00E4nestys auki voting.create.voteStart = \u00C4\u00E4nestys auki
yes = Kyll\u00E4 yes = Kyll\u00E4
tournaments.admin.open_for_roles=Rekister\u00F6itymiseen oikeuttavat ryhm\u00E4t
productOptionGroup.name=Nimi
product.createProductOptionGroup=Luo ominaisuus
productOptionGroup.required=Vaaditaan
productOption.name=Vaihtoehdon nimi
productOption.add=Lis\u00E4\u00E4 uusi vaihtoehto
productOption.title=Ominaisuuden vaihtoehdot
productOptionGroup.title=Tuotevaihtoehto
productOptionGroup.default=Oletusvaihtoehto
option.setAsDefault=Aseta oletukseksi
place.reservetime=Varaamisaika
product.minBuyCount=Ostettava v\u00E4hint\u00E4\u00E4n
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!