Commit 7a515e8e by Tuukka Kivilahti

Merge branch 'placeChange' into 'master'

Selfservice placechange



See merge request !366
2 parents 8d71ba5f 55018d3e
package fi.codecrew.moya.exceptions;
import fi.codecrew.moya.model.Place;
import javax.ejb.EJBException;
public class PlaceAlreadyTakenException extends EJBException {
public PlaceAlreadyTakenException(Place p) {
super("Place " + (p != null ? p.toString():"") + "already taken");
this.place = p;
}
private final Place place;
public Place getPlace() {
return place;
}
}
...@@ -145,6 +145,7 @@ public class MenuBean implements MenuBeanLocal { ...@@ -145,6 +145,7 @@ public class MenuBean implements MenuBeanLocal {
userkauppa.addPage(menuitemfacade.findOrCreate("/shop/createBill"), BillPermission.CREATE_BILL); userkauppa.addPage(menuitemfacade.findOrCreate("/shop/createBill"), BillPermission.CREATE_BILL);
userkauppa.addPage(menuitemfacade.findOrCreate("/neomap/reserve"), MapPermission.BUY_PLACES); userkauppa.addPage(menuitemfacade.findOrCreate("/neomap/reserve"), MapPermission.BUY_PLACES);
userkauppa.addPage(menuitemfacade.findOrCreate("/neomap/moveplaces"), MapPermission.MOVE_PLACES);
userkauppa.addPage(menuitemfacade.findOrCreate("/neomap/notenoughslots"), UserPermission.ANYUSER).setVisible(false); userkauppa.addPage(menuitemfacade.findOrCreate("/neomap/notenoughslots"), UserPermission.ANYUSER).setVisible(false);
userkauppa.addPage(menuitemfacade.findOrCreate("/shop/shopClosed"), BillPermission.CREATE_BILL).setVisible(false); userkauppa.addPage(menuitemfacade.findOrCreate("/shop/shopClosed"), BillPermission.CREATE_BILL).setVisible(false);
......
/* /*
* Copyright Codecrew Ry * Copyright Codecrew Ry
* *
* All rights reserved. * All rights reserved.
* *
* This license applies to any software containing a notice placed by the * This license applies to any software containing a notice placed by the
* copyright holder. Such software is herein referred to as the Software. * copyright holder. Such software is herein referred to as the Software.
* This license covers modification, distribution and use of the Software. * This license covers modification, distribution and use of the Software.
* *
* Any distribution and use in source and binary forms, with or without * Any distribution and use in source and binary forms, with or without
* modification is not permitted without explicit written permission from the * modification is not permitted without explicit written permission from the
* copyright owner. * copyright owner.
* *
* A non-exclusive royalty-free right is granted to the copyright owner of the * 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 * Software to use, modify and distribute all modifications to the Software in
* future versions of the Software. * future versions of the Software.
* *
*/ */
package fi.codecrew.moya.beans; package fi.codecrew.moya.beans;
import java.security.Principal; import java.security.Principal;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.annotation.security.DeclareRoles; import javax.annotation.security.DeclareRoles;
import javax.ejb.EJB; import javax.ejb.EJB;
import javax.ejb.LocalBean; import javax.ejb.LocalBean;
import javax.ejb.SessionContext; import javax.ejb.SessionContext;
import javax.ejb.Stateless; import javax.ejb.Stateless;
import javax.resource.spi.IllegalStateException; import javax.resource.spi.IllegalStateException;
import fi.codecrew.moya.enums.apps.*; import fi.codecrew.moya.enums.apps.*;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import fi.codecrew.moya.facade.EventUserFacade; import fi.codecrew.moya.facade.EventUserFacade;
import fi.codecrew.moya.facade.UserFacade; import fi.codecrew.moya.facade.UserFacade;
import fi.codecrew.moya.model.EventUser; import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.User; import fi.codecrew.moya.model.User;
@Stateless @Stateless
@DeclareRoles({ @DeclareRoles({
UserPermission.S_CREATE_NEW, UserPermission.S_CREATE_NEW,
UserPermission.S_LOGIN, UserPermission.S_LOGIN,
UserPermission.S_LOGOUT, UserPermission.S_LOGOUT,
UserPermission.S_MODIFY, UserPermission.S_MODIFY,
UserPermission.S_MODIFY_ACCOUNTEVENTS, UserPermission.S_MODIFY_ACCOUNTEVENTS,
UserPermission.S_VIEW_ACCOUNTEVENTS, UserPermission.S_VIEW_ACCOUNTEVENTS,
UserPermission.S_VIEW_OWN_ACCOUNTEVENTS, UserPermission.S_VIEW_OWN_ACCOUNTEVENTS,
UserPermission.S_VIEW_ALL, UserPermission.S_VIEW_ALL,
UserPermission.S_VIEW_SELF, UserPermission.S_VIEW_SELF,
UserPermission.S_WRITE_ROLES, UserPermission.S_WRITE_ROLES,
UserPermission.S_READ_ROLES, UserPermission.S_READ_ROLES,
UserPermission.S_ANYUSER, UserPermission.S_ANYUSER,
UserPermission.S_MANAGE_HTTP_SESSION, UserPermission.S_MANAGE_HTTP_SESSION,
UserPermission.S_INVITE_USERS, UserPermission.S_INVITE_USERS,
UserPermission.S_READ_ORGROLES, UserPermission.S_READ_ORGROLES,
UserPermission.S_WRITE_ORGROLES, UserPermission.S_WRITE_ORGROLES,
UserPermission.S_VITUTTAAKO, UserPermission.S_VITUTTAAKO,
UserPermission.S_HELPPAGE, UserPermission.S_HELPPAGE,
MapPermission.S_VIEW, MapPermission.S_VIEW,
MapPermission.S_MANAGE_MAPS, MapPermission.S_MANAGE_MAPS,
MapPermission.S_MANAGE_OTHERS, MapPermission.S_MANAGE_OTHERS,
MapPermission.S_BUY_PLACES, MapPermission.S_BUY_PLACES,
// MapPermission.S_RELEASE_PLACE, MapPermission.S_MOVE_PLACES,
ShopPermission.S_LIST_ALL_PRODUCTS, ShopPermission.S_LIST_ALL_PRODUCTS,
ShopPermission.S_LIST_USERPRODUCTS, ShopPermission.S_LIST_USERPRODUCTS,
ShopPermission.S_SHOP_TO_OTHERS, ShopPermission.S_SHOP_TO_OTHERS,
ShopPermission.S_MANAGE_PRODUCTS, ShopPermission.S_MANAGE_PRODUCTS,
ShopPermission.S_SHOP_PRODUCTS, ShopPermission.S_SHOP_PRODUCTS,
ShopPermission.S_SHOP_FOODWAVE, ShopPermission.S_SHOP_FOODWAVE,
ShopPermission.S_MANAGE_FOODWAVES, ShopPermission.S_MANAGE_FOODWAVES,
BillPermission.S_CREATE_BILL, BillPermission.S_CREATE_BILL,
BillPermission.S_READ_ALL, BillPermission.S_READ_ALL,
BillPermission.S_WRITE_ALL, BillPermission.S_WRITE_ALL,
BillPermission.S_VIEW_OWN, BillPermission.S_VIEW_OWN,
ContentPermission.S_MANAGE_NEWS, ContentPermission.S_MANAGE_NEWS,
ContentPermission.S_MANAGE_PAGES, ContentPermission.S_MANAGE_PAGES,
ContentPermission.S_MANAGE_ACTIONLOG, ContentPermission.S_MANAGE_ACTIONLOG,
ContentPermission.S_MANAGE_MENU, ContentPermission.S_MANAGE_MENU,
PollPermission.S_ANSWER, PollPermission.S_ANSWER,
PollPermission.S_VIEW_RESULTS, PollPermission.S_VIEW_RESULTS,
PollPermission.S_CREATE, PollPermission.S_CREATE,
SpecialPermission.S_SUPERADMIN, SpecialPermission.S_SUPERADMIN,
SpecialPermission.S_USER, SpecialPermission.S_USER,
SpecialPermission.S_ANONYMOUS, SpecialPermission.S_ANONYMOUS,
TerminalPermission.S_INFO_TERMINAL, TerminalPermission.S_INFO_TERMINAL,
TerminalPermission.S_USER_TERMINAL, TerminalPermission.S_USER_TERMINAL,
TerminalPermission.S_ADMIN_TERMINAL, TerminalPermission.S_ADMIN_TERMINAL,
CompoPermission.S_MANAGE, CompoPermission.S_MANAGE,
CompoPermission.S_VOTE, CompoPermission.S_VOTE,
CompoPermission.S_SUBMIT_ENTRY, CompoPermission.S_SUBMIT_ENTRY,
CompoPermission.S_VIEW_COMPOS, CompoPermission.S_VIEW_COMPOS,
EventPermission.S_MANAGE_PRIVATE_PROPERTIES, EventPermission.S_MANAGE_PRIVATE_PROPERTIES,
EventPermission.S_MANAGE_PROPERTIES, EventPermission.S_MANAGE_PROPERTIES,
LicensePermission.S_MANAGE, LicensePermission.S_MANAGE,
LicensePermission.S_VIEW_OWN_CODES, LicensePermission.S_VIEW_OWN_CODES,
PmsCodePermission.S_VIEW PmsCodePermission.S_VIEW
}) })
@LocalBean @LocalBean
public class PermissionBean implements PermissionBeanLocal { public class PermissionBean implements PermissionBeanLocal {
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static final Logger logger = LoggerFactory.getLogger(PermissionBean.class); private static final Logger logger = LoggerFactory.getLogger(PermissionBean.class);
@Resource @Resource
private SessionContext context; private SessionContext context;
@EJB @EJB
private LoggingBeanLocal loggingbean; private LoggingBeanLocal loggingbean;
@EJB @EJB
private UserFacade userfacade; private UserFacade userfacade;
@EJB @EJB
private EventUserFacade eventUserFacade; private EventUserFacade eventUserFacade;
@EJB @EJB
private EventBeanLocal eventbean; private EventBeanLocal eventbean;
@Override @Override
public boolean hasPermission(SpecialPermission perm) { public boolean hasPermission(SpecialPermission perm) {
if (perm == null) { if (perm == null) {
return false; return false;
} }
return context.isCallerInRole(perm.toString()); return context.isCallerInRole(perm.toString());
} }
@Override @Override
public boolean hasPermission(IAppPermission perm) { public boolean hasPermission(IAppPermission perm) {
if (perm == null) { if (perm == null) {
return false; return false;
} }
return context.isCallerInRole(perm.getFullName()); return context.isCallerInRole(perm.getFullName());
} }
@Override @Override
public boolean isCurrentUser(User user) { public boolean isCurrentUser(User user) {
return user != null && isCurrentUser(user.getLogin()); return user != null && isCurrentUser(user.getLogin());
} }
@Override @Override
public boolean isCurrentUser(String login) { public boolean isCurrentUser(String login) {
return (context.getCallerPrincipal() == null || login == null) ? false : context.getCallerPrincipal().getName().equals(login); return (context.getCallerPrincipal() == null || login == null) ? false : context.getCallerPrincipal().getName().equals(login);
} }
@Override @Override
public boolean isCurrentUser(EventUser user) { public boolean isCurrentUser(EventUser user) {
return user != null && isCurrentUser(user.getUser()); return user != null && isCurrentUser(user.getUser());
} }
@Override @Override
public boolean isLoggedIn() { public boolean isLoggedIn() {
Principal principal = context.getCallerPrincipal(); Principal principal = context.getCallerPrincipal();
boolean ret = principal != null && !User.ANONYMOUS_LOGINNAME.equalsIgnoreCase(principal.getName()); boolean ret = principal != null && !User.ANONYMOUS_LOGINNAME.equalsIgnoreCase(principal.getName());
// logger.info("Checking principal {} against anon: {}", principal, // logger.info("Checking principal {} against anon: {}", principal,
// ret); // ret);
return ret; return ret;
} }
@Override @Override
public EventUser getCurrentUser() { public EventUser getCurrentUser() {
Principal principal = context.getCallerPrincipal(); Principal principal = context.getCallerPrincipal();
EventUser ret = eventUserFacade.findByLogin(principal.getName()); EventUser ret = eventUserFacade.findByLogin(principal.getName());
if (ret == null) { if (ret == null) {
ret = getAnonEventUser(); ret = getAnonEventUser();
} }
return ret; return ret;
} }
/** /**
* Makes sure default user and public role exist and the user is member of * Makes sure default user and public role exist and the user is member of
* the role. * the role.
*/ */
@Override @Override
public EventUser getAnonEventUser() { public EventUser getAnonEventUser() {
EventUser defaultUser = eventUserFacade.findByLogin(User.ANONYMOUS_LOGINNAME); EventUser defaultUser = eventUserFacade.findByLogin(User.ANONYMOUS_LOGINNAME);
if (defaultUser == null) { if (defaultUser == null) {
User user = userfacade.findByLogin(User.ANONYMOUS_LOGINNAME); User user = userfacade.findByLogin(User.ANONYMOUS_LOGINNAME);
if (user == null) if (user == null) {
{ defaultUser = new EventUser(new User(), eventbean.getCurrentEvent(), null);
defaultUser = new EventUser(new User(), eventbean.getCurrentEvent(), null); defaultUser.getUser().setLogin(User.ANONYMOUS_LOGINNAME);
defaultUser.getUser().setLogin(User.ANONYMOUS_LOGINNAME); defaultUser.getUser().setNick(User.ANONYMOUS_LOGINNAME);
defaultUser.getUser().setNick(User.ANONYMOUS_LOGINNAME);
} else {
} else { defaultUser = new EventUser(user, eventbean.getCurrentEvent(), null);
defaultUser = new EventUser(user, eventbean.getCurrentEvent(), null); }
} eventUserFacade.create(defaultUser);
eventUserFacade.create(defaultUser); eventUserFacade.flush();
eventUserFacade.flush();
}
} return defaultUser;
return defaultUser; }
}
public String getPrincipal() {
public String getPrincipal() {
Principal principal = context.getCallerPrincipal();
Principal principal = context.getCallerPrincipal(); //logger.debug("Principal: {}", principal);
//logger.debug("Principal: {}", principal);
String principalName = principal.getName();
String principalName = principal.getName(); // logger.debug("Principal is {}", principalName);
// logger.debug("Principal is {}", principalName);
return principalName;
return principalName; }
}
@Override
@Override public String getCommonName() throws IllegalStateException {
public String getCommonName() throws IllegalStateException {
String dn = context.getCallerPrincipal().getName();
String dn = context.getCallerPrincipal().getName(); String[] parts = dn.split(",");
String[] parts = dn.split(",");
for (String part : parts) {
for (String part : parts) { if (part.trim().toUpperCase().startsWith("CN=")) {
if (part.trim().toUpperCase().startsWith("CN=")) { String cn = part.substring("CN=".length());
String cn = part.substring("CN=".length()); return cn;
return cn; }
} }
}
throw new IllegalStateException("Current security principal has no CN");
throw new IllegalStateException("Current security principal has no CN"); }
}
}
}
/* /*
* Copyright Codecrew Ry * Copyright Codecrew Ry
* *
* All rights reserved. * All rights reserved.
* *
* This license applies to any software containing a notice placed by the * This license applies to any software containing a notice placed by the
* copyright holder. Such software is herein referred to as the Software. * copyright holder. Such software is herein referred to as the Software.
* This license covers modification, distribution and use of the Software. * This license covers modification, distribution and use of the Software.
* *
* Any distribution and use in source and binary forms, with or without * Any distribution and use in source and binary forms, with or without
* modification is not permitted without explicit written permission from the * modification is not permitted without explicit written permission from the
* copyright owner. * copyright owner.
* *
* A non-exclusive royalty-free right is granted to the copyright owner of the * 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 * Software to use, modify and distribute all modifications to the Software in
* future versions of the Software. * future versions of the Software.
* *
*/ */
/* /*
* To change this template, choose Tools | Templates * To change this template, choose Tools | Templates
...@@ -49,6 +49,8 @@ import javax.ejb.Stateless; ...@@ -49,6 +49,8 @@ import javax.ejb.Stateless;
import javax.ejb.Timeout; import javax.ejb.Timeout;
import javax.ejb.Timer; import javax.ejb.Timer;
import javax.ejb.TimerService; import javax.ejb.TimerService;
import fi.codecrew.moya.exceptions.PlaceAlreadyTakenException;
import fi.codecrew.moya.facade.*; import fi.codecrew.moya.facade.*;
import fi.codecrew.moya.model.*; import fi.codecrew.moya.model.*;
...@@ -66,16 +68,15 @@ import fi.codecrew.moya.exceptions.BortalCatchableException; ...@@ -66,16 +68,15 @@ import fi.codecrew.moya.exceptions.BortalCatchableException;
import fi.codecrew.moya.utilities.moyamessage.MoyaEventType; import fi.codecrew.moya.utilities.moyamessage.MoyaEventType;
/** /**
*
* @author tuukka * @author tuukka
*/ */
@Stateless @Stateless
@LocalBean @LocalBean
@DeclareRoles({ @DeclareRoles({
MapPermission.S_BUY_PLACES, MapPermission.S_BUY_PLACES,
MapPermission.S_MANAGE_MAPS, MapPermission.S_MANAGE_MAPS,
MapPermission.S_VIEW, MapPermission.S_VIEW,
MapPermission.S_MANAGE_OTHERS, MapPermission.S_MANAGE_OTHERS,
}) })
public class PlaceBean implements PlaceBeanLocal { public class PlaceBean implements PlaceBeanLocal {
private static final Logger logger = LoggerFactory.getLogger(PlaceBean.class); private static final Logger logger = LoggerFactory.getLogger(PlaceBean.class);
...@@ -132,11 +133,10 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -132,11 +133,10 @@ public class PlaceBean implements PlaceBeanLocal {
/** /**
* Calculate the price of reserved places for the user Optional parameter * Calculate the price of reserved places for the user Optional parameter
* newPlace can be given when the place is added to the price calculations; * newPlace can be given when the place is added to the price calculations;
* * <p>
* User parameter can be used to select another user than the currently * User parameter can be used to select another user than the currently
* logged in user, but if user does not have enough rights an exception will * logged in user, but if user does not have enough rights an exception will
* be thrown * be thrown
*
*/ */
@RolesAllowed(SpecialPermission.S_USER) @RolesAllowed(SpecialPermission.S_USER)
...@@ -156,7 +156,9 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -156,7 +156,9 @@ public class PlaceBean implements PlaceBeanLocal {
} }
/** Use place slots */ /**
* Use place slots
*/
@Deprecated() @Deprecated()
private BigDecimal addAndCalcPrice(EventUser user, Place newPlace) { private BigDecimal addAndCalcPrice(EventUser user, Place newPlace) {
...@@ -208,11 +210,9 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -208,11 +210,9 @@ public class PlaceBean implements PlaceBeanLocal {
/** /**
* Reserve the place for user. This reservation will timeout after a while * Reserve the place for user. This reservation will timeout after a while
* buy() method should be called after this when buying place; * buy() method should be called after this when buying place;
* *
* @param place * @param place place to be reserved
* place to be reserved * @param user User for whom the place should be reserved.
* @param user
* User for whom the place should be reserved.
* @return true when successfull. On any error false. * @return true when successfull. On any error false.
*/ */
@Override @Override
...@@ -234,8 +234,7 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -234,8 +234,7 @@ public class PlaceBean implements PlaceBeanLocal {
boolean canReserve = (price.compareTo(balance) <= 0); boolean canReserve = (price.compareTo(balance) <= 0);
logger.debug("Balance {}, price {}", balance, price); logger.debug("Balance {}, price {}", balance, price);
if (!canReserve && !permbean.hasPermission(MapPermission.MANAGE_OTHERS)) if (!canReserve && !permbean.hasPermission(MapPermission.MANAGE_OTHERS)) {
{
logger.debug("Did not have enought credits to reserve place! required {} , got {}", price, balance); logger.debug("Did not have enought credits to reserve place! required {} , got {}", price, balance);
return false; return false;
} }
...@@ -268,21 +267,20 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -268,21 +267,20 @@ public class PlaceBean implements PlaceBeanLocal {
} }
@Override @Override
@RolesAllowed({ MapPermission.S_BUY_PLACES, MapPermission.S_MANAGE_OTHERS }) @RolesAllowed({MapPermission.S_BUY_PLACES, MapPermission.S_MANAGE_OTHERS})
public PlaceGroup buySelectedPlaces(EventUser user) throws BortalCatchableException { public PlaceGroup buySelectedPlaces(EventUser user) throws BortalCatchableException {
return buyOrReserveSelectedPlaces(user, true); return buyOrReserveSelectedPlaces(user, true);
} }
@Override @Override
@RolesAllowed({ MapPermission.S_BUY_PLACES, MapPermission.S_MANAGE_OTHERS }) @RolesAllowed({MapPermission.S_BUY_PLACES, MapPermission.S_MANAGE_OTHERS})
public PlaceGroup buySelectedPlaces(List<Place> selectedPlaces, EventUser user) throws BortalCatchableException { public PlaceGroup buySelectedPlaces(List<Place> selectedPlaces, EventUser user) throws BortalCatchableException {
return buyOrReserveSelectedPlaces(user, selectedPlaces, true); return buyOrReserveSelectedPlaces(user, selectedPlaces, true);
} }
@Override @Override
@RolesAllowed({ MapPermission.S_MANAGE_OTHERS }) @RolesAllowed({MapPermission.S_MANAGE_OTHERS})
public PlaceGroup reserveSelectedPlaces(EventUser eventuser) throws BortalCatchableException { public PlaceGroup reserveSelectedPlaces(EventUser eventuser) throws BortalCatchableException {
return buyOrReserveSelectedPlaces(eventuser, false); return buyOrReserveSelectedPlaces(eventuser, false);
} }
...@@ -311,10 +309,10 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -311,10 +309,10 @@ public class PlaceBean implements PlaceBeanLocal {
List<Place> places = placeFacade.findUsersReservations(event, user); List<Place> places = placeFacade.findUsersReservations(event, user);
if(selectedPlaces != null) { if (selectedPlaces != null) {
List<Place> newPlaces = new ArrayList<>(); List<Place> newPlaces = new ArrayList<>();
for(Place p : selectedPlaces) { for (Place p : selectedPlaces) {
if(!p.isReservedFor(permbean.getCurrentUser()) && p.isTaken()) if (!p.isReservedFor(permbean.getCurrentUser()) && p.isTaken())
continue; continue;
p = placeFacade.reload(p); // persist teh shit p = placeFacade.reload(p); // persist teh shit
...@@ -331,12 +329,11 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -331,12 +329,11 @@ public class PlaceBean implements PlaceBeanLocal {
// Check wether we should reserve places via credit or plcaeslot // Check wether we should reserve places via credit or plcaeslot
boolean placePrepaidcredit = places.get(0).getProduct().getProductFlags().contains(ProductFlag.PREPAID_CREDIT); boolean placePrepaidcredit = places.get(0).getProduct().getProductFlags().contains(ProductFlag.PREPAID_CREDIT);
// PlaceGroup pg = pgbean.createPlaceGroup(user); // PlaceGroup pg = pgbean.createPlaceGroup(user);
if (placePrepaidcredit && createAccountevents) if (placePrepaidcredit && createAccountevents) {
{
BigDecimal totalprice = addAndCalcPrice(user, null); BigDecimal totalprice = addAndCalcPrice(user, null);
BigDecimal balance = user.getAccountBalance(); BigDecimal balance = user.getAccountBalance();
if (balance.compareTo(totalprice) < 0 && !permbean.hasPermission(MapPermission.MANAGE_OTHERS)) { if (balance.compareTo(totalprice) < 0 && !permbean.hasPermission(MapPermission.MANAGE_OTHERS)) {
logger.info("User {} Could not buy things because account balance {} is too low for purchase {}", new Object[] { user, balance, totalprice }); logger.info("User {} Could not buy things because account balance {} is too low for purchase {}", new Object[]{user, balance, totalprice});
return null; return null;
} }
...@@ -353,7 +350,7 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -353,7 +350,7 @@ public class PlaceBean implements PlaceBeanLocal {
boolean associatedToPlace = isUserMember(user, places.get(0).getProduct()); boolean associatedToPlace = isUserMember(user, places.get(0).getProduct());
StringBuilder logSb = new StringBuilder(); StringBuilder logSb = new StringBuilder();
logSb.append("User Locked ").append(places.size()).append(" places: "); logSb.append("User Locked ").append(places.size()).append(" places: ");
for (Place p : places) { for (Place p : places) {
if (!p.isReservedFor(user)) { if (!p.isReservedFor(user)) {
...@@ -366,8 +363,7 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -366,8 +363,7 @@ public class PlaceBean implements PlaceBeanLocal {
logSb.append(p.getName()).append(", "); logSb.append(p.getName()).append(", ");
GroupMembership gm = buy(p, pg); GroupMembership gm = buy(p, pg);
if (!associatedToPlace) if (!associatedToPlace) {
{
logger.info("Associating buyer {} to place {}", user, gm); logger.info("Associating buyer {} to place {}", user, gm);
associatedToPlace = true; associatedToPlace = true;
gm.setUser(user); gm.setUser(user);
...@@ -398,12 +394,10 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -398,12 +394,10 @@ public class PlaceBean implements PlaceBeanLocal {
// If user is not yet associated to this type of product, find it out... // If user is not yet associated to this type of product, find it out...
for (int i = 0; i < quantity.intValue(); ++i) for (int i = 0; i < quantity.intValue(); ++i) {
{
Place freePlace = null; Place freePlace = null;
if (prod.getProductFlags().contains(ProductFlag.CREATE_NEW_PLACE_WHEN_BOUGHT)) if (prod.getProductFlags().contains(ProductFlag.CREATE_NEW_PLACE_WHEN_BOUGHT)) {
{
freePlace = new Place(); freePlace = new Place();
freePlace.setProduct(prod); freePlace.setProduct(prod);
freePlace.setProvidesRole(prod.getProvides()); freePlace.setProvidesRole(prod.getProvides());
...@@ -423,8 +417,7 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -423,8 +417,7 @@ public class PlaceBean implements PlaceBeanLocal {
} }
GroupMembership gm = buy(freePlace, pg); GroupMembership gm = buy(freePlace, pg);
if (!associatedToPlace) if (!associatedToPlace) {
{
logger.info("Associating buyer {} to place {}", user, gm); logger.info("Associating buyer {} to place {}", user, gm);
associatedToPlace = true; associatedToPlace = true;
gm.setUser(user); gm.setUser(user);
...@@ -440,8 +433,7 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -440,8 +433,7 @@ public class PlaceBean implements PlaceBeanLocal {
private static boolean isUserMember(EventUser user, Product prod) { private static boolean isUserMember(EventUser user, Product prod) {
boolean ret = false; boolean ret = false;
if (user.getGroupMemberships() != null) if (user.getGroupMemberships() != null) {
{
for (GroupMembership gm : user.getGroupMemberships()) { for (GroupMembership gm : user.getGroupMemberships()) {
if (gm.getPlaceReservation() != null && prod.equals(gm.getPlaceReservation().getProduct())) { if (gm.getPlaceReservation() != null && prod.equals(gm.getPlaceReservation().getProduct())) {
...@@ -466,8 +458,7 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -466,8 +458,7 @@ public class PlaceBean implements PlaceBeanLocal {
if (pg.getPlaces() == null) { if (pg.getPlaces() == null) {
pg.setPlaces(new ArrayList<Place>()); pg.setPlaces(new ArrayList<Place>());
} }
if (!pg.getPlaces().contains(p)) if (!pg.getPlaces().contains(p)) {
{
pg.getPlaces().add(p); pg.getPlaces().add(p);
} }
return membership; return membership;
...@@ -482,13 +473,12 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -482,13 +473,12 @@ public class PlaceBean implements PlaceBeanLocal {
/** /**
* Release reservation from user * Release reservation from user
* *
* @param place * @param place The place to be released
* The place to be released
* @return true when successfull, on any erroro false. * @return true when successfull, on any erroro false.
*/ */
@Override @Override
@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);
return releasePlacePriv(place) != null; return releasePlacePriv(place) != null;
...@@ -501,7 +491,7 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -501,7 +491,7 @@ public class PlaceBean implements PlaceBeanLocal {
* @return true when successfull, on any erroro false. * @return true when successfull, on any erroro false.
*/ */
@Override @Override
@RolesAllowed({ MapPermission.S_BUY_PLACES, MapPermission.S_MANAGE_OTHERS }) @RolesAllowed({MapPermission.S_BUY_PLACES, MapPermission.S_MANAGE_OTHERS})
public boolean userReleasePlace(Place place) { public boolean userReleasePlace(Place place) {
place = placeFacade.reload(place); place = placeFacade.reload(place);
PlaceSlot s = releasePlacePriv(place); PlaceSlot s = releasePlacePriv(place);
...@@ -510,23 +500,50 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -510,23 +500,50 @@ public class PlaceBean implements PlaceBeanLocal {
} }
private PlaceSlot releasePlacePriv(Place place) { private PlaceSlot releasePlacePriv(Place place) {
EventUser user = permbean.getCurrentUser();
if (place.getGroup() != null || place.getCurrentUser() == null
|| (!permbean.hasPermission(MapPermission.MANAGE_OTHERS) && !place.getCurrentUser().equals(user))) {
return null;
}
if (place.getGroup() != null) {
place.getGroup().getPlaces().remove(place);
}
place.setGroup(null);
place.setCurrentUser(null); place.setCurrentUser(null);
place.setReserveTime(null); place.setReserveTime(null);
if (place.getPlaceReserver() != null) {
place.getPlaceReserver().setPlaceReservation(null);
place.setPlaceReserver(null);
}
PlaceSlot slot = placeSlotFacade.findSlotForPlace(place); PlaceSlot slot = placeSlotFacade.findSlotForPlace(place);
// remove also slot from place
if (slot != null) { if (slot != null) {
slot.setPlace(null); slot.setPlace(null);
slot.setUsed(null); slot.setUsed(null);
place.setReserverSlot(null);
} }
return slot; return slot;
} }
public GroupMembership removeGroupMembership(Place place) {
GroupMembership res = place.getPlaceReserver();
if (res != null) {
if (res.getPlaceGroup().getMembers() != null) {
res.getPlaceGroup().getMembers().remove(res);
}
if (res.getUser() != null && res.getUser().getGroupMemberships() != null) {
res.getUser().getGroupMemberships().remove(res);
}
place.setPlaceReserver(null);
gmemfacade.remove(res);
}
return res;
}
@Override @Override
@RolesAllowed(MapPermission.S_VIEW) @RolesAllowed(MapPermission.S_VIEW)
public Place find(int placeId) { public Place find(int placeId) {
...@@ -552,36 +569,9 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -552,36 +569,9 @@ public class PlaceBean implements PlaceBeanLocal {
@RolesAllowed(MapPermission.S_MANAGE_OTHERS) @RolesAllowed(MapPermission.S_MANAGE_OTHERS)
public Place unbuyPlace(Place place) { public Place unbuyPlace(Place place) {
place = placeFacade.reload(place); place = placeFacade.reload(place);
if (place.getGroup() != null) { removeGroupMembership(place);
place.getGroup().getPlaces().remove(place); releasePlacePriv(place);
}
place.setGroup(null);
place.setCurrentUser(null);
place.setReserveTime(null);
if (place.getPlaceReserver() != null) {
GroupMembership res = place.getPlaceReserver();
if (res.getPlaceGroup().getMembers() != null) {
res.getPlaceGroup().getMembers().remove(res);
}
if (res.getUser() != null && res.getUser().getGroupMemberships() != null) {
res.getUser().getGroupMemberships().remove(res);
}
place.setPlaceReserver(null);
gmemfacade.remove(res);
}
PlaceSlot slot = placeSlotFacade.findSlotForPlace(place);
// remove also slot from place
if (slot != null) {
slot.setPlace(null);
slot.setUsed(null);
place.setReserverSlot(null);
}
return place; return place;
} }
...@@ -604,12 +594,12 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -604,12 +594,12 @@ public class PlaceBean implements PlaceBeanLocal {
pdf.setTitle("Place"); pdf.setTitle("Place");
float pointInMillim = (25.4f / 72.0f); // 1 point is 1/72 inches. 1 inch float pointInMillim = (25.4f / 72.0f); // 1 point is 1/72 inches. 1 inch
// = 25.4mm // = 25.4mm
float pagex = width / pointInMillim; float pagex = width / pointInMillim;
float pagey = height / pointInMillim; float pagey = height / pointInMillim;
for (Place place : places) { for (Place place : places) {
Page page = new Page(pdf, new float[] { pagex, pagey }); Page page = new Page(pdf, new float[]{pagex, pagey});
// place code // place code
com.pdfjet.Font font = new com.pdfjet.Font(pdf, CoreFont.HELVETICA); com.pdfjet.Font font = new com.pdfjet.Font(pdf, CoreFont.HELVETICA);
...@@ -618,7 +608,7 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -618,7 +608,7 @@ public class PlaceBean implements PlaceBeanLocal {
TextLine textLine = new TextLine(font); TextLine textLine = new TextLine(font);
textLine.setText(place.getName()); textLine.setText(place.getName());
textLine.setPosition(5, 15); textLine.setPosition(5, 15);
textLine.setColor(new int[] { 0, 0, 0 }); textLine.setColor(new int[]{0, 0, 0});
textLine.drawOn(page); textLine.drawOn(page);
double currentX = 42; double currentX = 42;
...@@ -631,7 +621,7 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -631,7 +621,7 @@ public class PlaceBean implements PlaceBeanLocal {
textLine = new TextLine(font); textLine = new TextLine(font);
textLine.setText(place.getPlaceReserver().getUser().getNick()); textLine.setText(place.getPlaceReserver().getUser().getNick());
textLine.setPosition(currentX, 15); textLine.setPosition(currentX, 15);
textLine.setColor(new int[] { 0, 0, 0 }); textLine.setColor(new int[]{0, 0, 0});
textLine.drawOn(page); textLine.drawOn(page);
} }
...@@ -642,7 +632,7 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -642,7 +632,7 @@ public class PlaceBean implements PlaceBeanLocal {
textLine = new TextLine(font); textLine = new TextLine(font);
textLine.setText(barcodeBean.getPlaceTextCode(place)); textLine.setText(barcodeBean.getPlaceTextCode(place));
textLine.setPosition(currentX, (pagey / 2) + font1); textLine.setPosition(currentX, (pagey / 2) + font1);
textLine.setColor(new int[] { 0, 0, 0 }); textLine.setColor(new int[]{0, 0, 0});
textLine.drawOn(page); textLine.drawOn(page);
} }
...@@ -858,24 +848,45 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -858,24 +848,45 @@ public class PlaceBean implements PlaceBeanLocal {
for (Entry<Place, Place> s : change.entrySet()) { for (Entry<Place, Place> s : change.entrySet()) {
Place src = placeFacade.reload(s.getKey()); Place src = placeFacade.reload(s.getKey());
Place dst = placeFacade.reload(s.getValue());
if (!src.getProduct().equals(dst.getProduct())) {
throw new EJBException("src and dst product types differ for {}, {}" + src + " " + dst);
}
if (!manageOthers && !user.equals(src.getCurrentUser()) if (!manageOthers && !user.equals(src.getCurrentUser())
&& (src.getGroup() == null || !user.equals(src.getGroup().getCreator()))) { && (src.getGroup() == null || !user.equals(src.getGroup().getCreator()))) {
throw new EJBAccessException("Trying to move places for another user without permissions!"); throw new EJBAccessException("Trying to move places for another user without permissions!");
} }
Place dst = placeFacade.reload(s.getValue());
if (!dst.isBuyable() || dst.isTaken()) { if (!dst.isBuyable() || dst.isTaken()) {
throw new EJBException("Place already taken!!"); throw new PlaceAlreadyTakenException(dst);
} }
// Store values we want to store to the destination place
PlaceGroup grp = src.getGroup();
GroupMembership gmem = src.getPlaceReserver();
EventUser currentUser = src.getCurrentUser();
PlaceSlot srcSlot = releasePlacePriv(src); PlaceSlot srcSlot = releasePlacePriv(src);
if (srcSlot != null) { if (srcSlot != null) {
// this place was reserved via a slot... // this place was reserved via a slot...
srcSlot.setPlace(dst); srcSlot.setPlace(dst);
dst.setReserverSlot(srcSlot);
srcSlot.setUsed(new Date()); srcSlot.setUsed(new Date());
} }
dst.setCurrentUser(user); dst.setCurrentUser(currentUser);
dst.setReserveTime(Calendar.getInstance());
if (gmem != null) {
dst.setPlaceReserver(gmem);
gmem.setPlaceReservation(dst);
}
dst.setGroup(grp);
if (grp != null) {
grp.getPlaces().add(dst);
}
} }
} }
......
/* /*
* Copyright Codecrew Ry * Copyright Codecrew Ry
* *
* All rights reserved. * All rights reserved.
* *
* This license applies to any software containing a notice placed by the * This license applies to any software containing a notice placed by the
* copyright holder. Such software is herein referred to as the Software. * copyright holder. Such software is herein referred to as the Software.
* This license covers modification, distribution and use of the Software. * This license covers modification, distribution and use of the Software.
* *
* Any distribution and use in source and binary forms, with or without * Any distribution and use in source and binary forms, with or without
* modification is not permitted without explicit written permission from the * modification is not permitted without explicit written permission from the
* copyright owner. * copyright owner.
* *
* A non-exclusive royalty-free right is granted to the copyright owner of the * 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 * Software to use, modify and distribute all modifications to the Software in
* future versions of the Software. * future versions of the Software.
* *
*/ */
package fi.codecrew.moya.enums.apps; package fi.codecrew.moya.enums.apps;
...@@ -25,6 +25,7 @@ public enum MapPermission implements IAppPermission { ...@@ -25,6 +25,7 @@ public enum MapPermission implements IAppPermission {
BUY_PLACES, // ("Reserve and buy places from map"), BUY_PLACES, // ("Reserve and buy places from map"),
VIEW, // ("View maps"), VIEW, // ("View maps"),
MANAGE_MAPS, MANAGE_MAPS,
MOVE_PLACES,
//RELEASE_PLACE, // ("Create and modify maps") //RELEASE_PLACE, // ("Create and modify maps")
; ;
...@@ -33,14 +34,15 @@ public enum MapPermission implements IAppPermission { ...@@ -33,14 +34,15 @@ public enum MapPermission implements IAppPermission {
public static final String S_BUY_PLACES = "MAP/BUY_PLACES"; public static final String S_BUY_PLACES = "MAP/BUY_PLACES";
public static final String S_VIEW = "MAP/VIEW"; public static final String S_VIEW = "MAP/VIEW";
public static final String S_MANAGE_MAPS = "MAP/MANAGE_MAPS"; public static final String S_MANAGE_MAPS = "MAP/MANAGE_MAPS";
public static final String S_RELEASE_PLACE = "MAP/RELEASE_PLACE"; public static final String S_MOVE_PLACES = "MAP/MOVE_PLACES";
private final String fullName; private final String fullName;
private final String key; private final String key;
private static final String I18N_HEADER = "bortalApplication.map."; private static final String I18N_HEADER = "bortalApplication.map.";
private MapPermission() { private MapPermission() {
key = I18N_HEADER + name(); key = I18N_HEADER + name();
fullName = new StringBuilder().append(getParent().toString()).append(DELIMITER).append(toString()).toString(); fullName = getParent().toString() + DELIMITER + this.toString();
} }
......
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" <html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core" xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" xmlns:h="http://java.sun.com/jsf/html"
xmlns:map="http://java.sun.com/jsf/composite/cditools/map" xmlns:map="http://java.sun.com/jsf/composite/cditools/map"
xmlns:tools="http://java.sun.com/jsf/composite/cditools" xmlns:tools="http://java.sun.com/jsf/composite/cditools"
xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui"> xmlns:p="http://primefaces.org/ui">
<h:body> <h:body>
<ui:composition template="#{sessionHandler.template}"> <ui:composition template="#{sessionHandler.template}">
<f:metadata> <f:metadata>
<f:event type="preRenderView" <f:viewParam name="userId" value="#{mapPlacechangeView.userId}"/>
listener="#{mapPlacechangeView.initView()}" /> <f:event type="preRenderView" listener="#{mapPlacechangeView.initView()}"/>
</f:metadata> </f:metadata>
<ui:define name="content"> <ui:define name="content">
<h:outputScript target="head" library="seatjs" name="d3.min.js" /> <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="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"/>
<!-- Place slot count --> <!-- Place slot count -->
<h3> <h3>
<h:outputText value="#{i18n['mapView.yourPlaces']}" /> <h:outputText value="#{i18n['placemove.header']}"/>
</h3> </h3>
<p:fragment id="placeselector"> <p:fragment id="placeselector">
<h:form> <h:form>
<p:dataTable id="slottable" tableStyle="width: auto;" var="slot" <p:dataTable id="slottable" tableStyle="width: auto;" var="slot"
value="#{mapPlacechangeView.slots}"> value="#{mapPlacechangeView.slots}">
<!-- rowStyleClass="#{mapPlacechangeView.srcPlace.contains(slot.place) ? 'selected' : 'unselected'}" --> <!-- rowStyleClass="#{mapPlacechangeView.srcPlace.contains(slot.place) ? 'selected' : 'unselected'}" -->
<p:column headerText="#{i18n['mapView.productcount.productname']}"> <p:column headerText="#{i18n['placemove.productname']}">
<h:outputText value="#{slot.src.product.name}" /> <h:outputText value="#{slot.src.product.name}"/>
</p:column> </p:column>
<p:column headerText="#{i18n['mapView.productcount.unused']}"> <p:column headerText="#{i18n['placemove.placename']}">
<h:outputText renderer="#{!empty slot.src.place}" <h:outputText renderer="#{!empty slot.src.place}"
value="#{slot.src.place.name}" /> 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>
<p:column headerText="#{i18n['mapView.productcount.selected']}"> <p:column headerText="#{i18n['placemove.placeuser']}">
<h:outputText renderer="#{!empty slot.dst}" <h:outputText rendered="#{!empty slot.src.place.currentUser}"
value="#{slot.dst.name}" /> value="#{slot.src.place.currentUser.wholeNmae}"/>
<h:outputText rendered="#{empty slot.src.place.currentUser}"
value="-"/>
</p:column>
<p:column headerText="#{i18n['placemove.dstplace']}">
<div style="padding: 0.3em 0;">
<h:outputText renderer="#{!empty slot.dst}"
value="#{slot.dst.name}"/>
</div>
</p:column> </p:column>
<p:column> <p:column>
...@@ -61,67 +64,70 @@ ...@@ -61,67 +64,70 @@
actionListener="#{mapPlacechangeView.selectSlot}" actionListener="#{mapPlacechangeView.selectSlot}"
rendered="#{!slot.isMoving()}" rendered="#{!slot.isMoving()}"
value="#{i18n['placemove.selectSlotForMove']}" value="#{i18n['placemove.selectSlotForMove']}"
update="placeselector" /> update="placeselector"/>
<p:commandButton <p:commandButton
actionListener="#{mapPlacechangeView.unselectSlot}" actionListener="#{mapPlacechangeView.unselectSlot}"
rendered="#{slot.moving}" value="#{i18n['placemove.deselect']}" rendered="#{slot.moving}" value="#{i18n['placemove.deselect']}"
update="placeselector" /> update="placeselector"/>
</ui:fragment> </ui:fragment>
</p:column> </p:column>
</p:dataTable> </p:dataTable>
</h:form> </h:form>
<script type="text/javascript"> <script type="text/javascript">
toggleSuccess = #{mapPlacechangeView.toggleSuccess}; var toggleSuccess = #{mapPlacechangeView.toggleSuccess};
</script> </script>
</p:fragment>
<h:form id="placemove">
<p:commandButton
rendered="#{ajaxMapView.canUserBuy()}"
value="#{i18n['mapPlacechange.commitMove']}"
action="#{mapPlacechangeView.commitMove()}" />
</h:form>
<div style="padding: 1em 0;">
<h:form id="placemove">
<p:commandButton
disabled="#{!mapPlacechangeView.isReadyForCommit()}"
rendered="#{ajaxMapView.canUserBuy()}"
value="#{i18n['placemove.commitMove']}"
action="#{mapPlacechangeView.commitMove()}" ajax="false"/>
</h:form>
</div>
</p:fragment>
<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"/>
<h:form> <h:form>
<p:remoteCommand name="toggleDstPlace" <p:remoteCommand name="toggleDstPlace"
action="#{mapPlacechangeView.toggleDstPlace()}" action="#{mapPlacechangeView.toggleDstPlace()}"
update="placeselector" oncomplete="afterToggle()"></p:remoteCommand> update="placeselector" oncomplete="afterToggle()"/>
</h:form> </h:form>
<script type="text/javascript"> <script type="text/javascript">
// <![CDATA[ // <![CDATA[
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},
}); });
px.toggleaction = function(d){ px.toggleaction = function (d) {
latestPlace = d; latestPlace = d;
toggleDstPlace([{name:"placeId", value:d.id} ]) toggleDstPlace([{name: "placeId", value: d.id}])
}; };
function afterToggle(){ function afterToggle() {
if(toggleSuccess){ if (toggleSuccess) {
if(latestPlace.state === "F"){ if (latestPlace.state === "F") {
latestPlace.state = "T"; latestPlace.state = "T";
}else { } else {
latestPlace.state = "F"; latestPlace.state = "F";
} }
px.update_placeobj([latestPlace]); px.update_placeobj([latestPlace]);
} }
} }
// ]]> // ]]>
</script> </script>
<map:legend /> <map:legend/>
</ui:define> </ui:define>
</ui:composition> </ui:composition>
......
<!DOCTYPE html <!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> "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:c="http://java.sun.com/jsp/jstl/core" <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:users="http://java.sun.com/jsf/composite/cditools/user" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui"> xmlns:h="http://java.sun.com/jsf/html" xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:users="http://java.sun.com/jsf/composite/cditools/user" xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:body> <h:body>
<ui:composition template="#{sessionHandler.template}"> <ui:composition template="#{sessionHandler.template}">
<ui:param name="thispage" value="page.place.mygroups" /> <ui:param name="thispage" value="page.place.mygroups"/>
<f:metadata> <f:metadata>
<f:viewParam name="userid" value="#{userView.userid}" /> <f:viewParam name="userid" value="#{userView.userid}"/>
<f:event type="preRenderView" listener="#{userView.initView}" /> <f:event type="preRenderView" listener="#{userView.initView}"/>
</f:metadata> </f:metadata>
<ui:define name="title"> <ui:define name="title">
...@@ -16,57 +18,70 @@ ...@@ -16,57 +18,70 @@
<!-- <users:usertabs tabId="groups" /> --> <!-- <users:usertabs tabId="groups" /> -->
</ui:define> </ui:define>
<ui:define name="edittab"> <ui:define name="edittab">
<users:usertabs tabId="groups" /> <users:usertabs tabId="groups"/>
</ui:define> </ui:define>
<ui:define name="content"> <ui:define name="content">
<h:outputText rendered="#{empty placeGroupView.groupMemberships}" value="#{i18n['placegroupview.noMemberships']}" /> <h:link outcome="/neomap/moveplaces" value="#{i18n['placegroupview.moveUsersPlaces']}">
<f:param name="userId" value="#{userView.user.user.id}"/>
</h:link>
<h:outputText rendered="#{empty placeGroupView.groupMemberships}"
value="#{i18n['placegroupview.noMemberships']}"/>
<h:form rendered="#{!empty placeGroupView.groupMemberships}" id="placelistform"> <h:form rendered="#{!empty placeGroupView.groupMemberships}" id="placelistform">
<h:dataTable value="#{placeGroupView.groupMemberships}" var="member"> <h:dataTable value="#{placeGroupView.groupMemberships}" var="member">
<h:column> <h:column>
<f:facet name="header"> <f:facet name="header">
<h:outputText value="#{i18n['placegroupview.reservationName']}" /> <h:outputText value="#{i18n['placegroupview.reservationName']}"/>
</f:facet> </f:facet>
<h:link value="#{member.placeReservation.name}" outcome="/place/edit"> <h:link value="#{member.placeReservation.name}" outcome="/place/edit">
<f:param name="placeid" value="#{member.placeReservation.id}" /> <f:param name="placeid" value="#{member.placeReservation.id}"/>
</h:link> </h:link>
</h:column> </h:column>
<h:column> <h:column>
<f:facet name="header"> <f:facet name="header">
<h:outputText value="#{i18n['placegroupview.token']}" /> <h:outputText value="#{i18n['placegroupview.token']}"/>
</f:facet> </f:facet>
<h:outputText rendered="#{empty member.user}" value="#{member.inviteToken}" /> <h:outputText rendered="#{empty member.user}" value="#{member.inviteToken}"/>
<h:link rendered="#{!empty member.user}" value="#{member.user.firstnames} #{member.user.lastname} (#{member.user.nick})" outcome="/place/adminGroups"> <h:link rendered="#{!empty member.user}"
<f:param name="userid" value="#{member.user.user.id}" /> value="#{member.user.firstnames} #{member.user.lastname} (#{member.user.nick})"
outcome="/place/adminGroups">
<f:param name="userid" value="#{member.user.user.id}"/>
</h:link> </h:link>
</h:column> </h:column>
<h:column> <h:column>
<f:facet name="header"> <f:facet name="header">
<h:outputText value="#{i18n['placegroupview.groupCreator']}" /> <h:outputText value="#{i18n['placegroupview.groupCreator']}"/>
</f:facet> </f:facet>
<h:link value="#{member.placeGroup.creator.firstnames} #{member.placeGroup.creator.lastname} (#{member.placeGroup.creator.nick})" outcome="/place/adminGroups"> <h:link
<f:param name="userid" value="#{member.placeGroup.creator.user.id}" /> value="#{member.placeGroup.creator.firstnames} #{member.placeGroup.creator.lastname} (#{member.placeGroup.creator.nick})"
outcome="/place/adminGroups">
<f:param name="userid" value="#{member.placeGroup.creator.user.id}"/>
</h:link> </h:link>
</h:column> </h:column>
<h:column> <h:column>
<h:commandButton rendered="#{placeGroupView.canModifyCurrent and placeGroupView.currentMemberUserNotNull}" action="#{placeGroupView.releasePlace()}" <h:commandButton
value="#{i18n['placegroupview.releasePlace']}" /> rendered="#{placeGroupView.canModifyCurrent and placeGroupView.currentMemberUserNotNull}"
action="#{placeGroupView.releasePlace()}"
value="#{i18n['placegroupview.releasePlace']}"/>
</h:column> </h:column>
</h:dataTable> </h:dataTable>
</h:form> </h:form>
<p> <p>
<input type="button" onclick="location.replace('#{request.contextPath}/PlaceGroupPdf?eventuserId=#{placeGroupView.user.id}');" value="#{i18n['placegroup.printPdf']}" /> <input type="button"
onclick="location.replace('#{request.contextPath}/PlaceGroupPdf?eventuserId=#{placeGroupView.user.id}');"
value="#{i18n['placegroup.printPdf']}"/>
</p> </p>
<h2>#{i18n['placetoken.pageHeader']}</h2> <h2>#{i18n['placetoken.pageHeader']}</h2>
<p>#{i18n['placetoken.topText']}</p> <p>#{i18n['placetoken.topText']}</p>
<h:form id="placeTokenForm"> <h:form id="placeTokenForm">
<h:outputLabel value="#{i18n['placetoken.token']}:" /> <h:outputLabel value="#{i18n['placetoken.token']}:"/>
<h:inputText value="#{tokenView.token}" /> <h:inputText value="#{tokenView.token}"/>
<h:commandButton id="commitbtn" action="#{tokenView.saveToken()}" value="#{i18n['placetoken.commit']}" /> <h:commandButton id="commitbtn" action="#{tokenView.saveToken()}" value="#{i18n['placetoken.commit']}"/>
</h:form> </h:form>
<h2>Place slots</h2> <h2>Place slots</h2>
...@@ -74,38 +89,43 @@ ...@@ -74,38 +89,43 @@
<p:dataTable var="slot" value="#{placeGroupView.placeslots}" id="placeslots"> <p:dataTable var="slot" value="#{placeGroupView.placeslots}" id="placeslots">
<p:column headerText="#{i18n['placeslot.id']}"> <p:column headerText="#{i18n['placeslot.id']}">
<h:outputText value="#{slot.id}" /> <h:outputText value="#{slot.id}"/>
</p:column> </p:column>
<p:column headerText="#{i18n['placeslot.state']}"> <p:column headerText="#{i18n['placeslot.state']}">
<h:outputText value="#{slot.bill.expired ? i18n['placeslot.state.expired'] : ( slot.bill.paid ? i18n['placeslot.state.paid'] : i18n['placeslot.state.notPaid'])}" /> <h:outputText
value="#{slot.bill.expired ? i18n['placeslot.state.expired'] : ( slot.bill.paid ? i18n['placeslot.state.paid'] : i18n['placeslot.state.notPaid'])}"/>
</p:column> </p:column>
<p:column headerText="#{i18n['placeslot.product']}"> <p:column headerText="#{i18n['placeslot.product']}">
<h:outputText value="#{slot.product.name}" /> <h:outputText value="#{slot.product.name}"/>
</p:column> </p:column>
<p:column headerText="#{i18n['placeslot.place']}"> <p:column headerText="#{i18n['placeslot.place']}">
<h:link value="#{slot.place.name}" rendered="#{!empty slot.place}" outcome="/place/edit"> <h:link value="#{slot.place.name}" rendered="#{!empty slot.place}" outcome="/place/edit">
<f:param name="placeid" value="#{slot.place.id}" /> <f:param name="placeid" value="#{slot.place.id}"/>
</h:link> </h:link>
</p:column> </p:column>
<p:column headerText="#{i18n['placeslot.used']}"> <p:column headerText="#{i18n['placeslot.used']}">
<h:outputText value="#{slot.used}"> <h:outputText value="#{slot.used}">
<f:convertDateTime timeZone="#{sessionHandler.timezone}" pattern="#{sessionHandler.shortDatetimeFormat}" /> <f:convertDateTime timeZone="#{sessionHandler.timezone}"
pattern="#{sessionHandler.shortDatetimeFormat}"/>
</h:outputText> </h:outputText>
</p:column> </p:column>
<p:column headerText="#{i18n['placeslot.bill']}"> <p:column headerText="#{i18n['placeslot.bill']}">
<h:link outcome="/bill/showBill" value="#{i18n['bill.billNumber']}: #{slot.bill.id}"> <h:link outcome="/bill/showBill" value="#{i18n['bill.billNumber']}: #{slot.bill.id}">
<f:param name="billid" value="#{slot.bill.id}" /> <f:param name="billid" value="#{slot.bill.id}"/>
</h:link> </h:link>
</p:column> </p:column>
<p:column> <p:column>
<p:commandButton rendered="#{empty slot.place and empty slot.used}" value="#{i18n['placeslot.lockSlot']}" actionListener="#{placeGroupView.lockSlot}" update="placeslots" /> <p:commandButton rendered="#{empty slot.place and empty slot.used}"
<p:commandButton rendered="#{empty slot.place and not empty slot.used}" value="#{i18n['placeslot.releaseSlot']}" actionListener="#{placeGroupView.releaseSlot}" update="placeslots" /> value="#{i18n['placeslot.lockSlot']}"
actionListener="#{placeGroupView.lockSlot}" update="placeslots"/>
<p:commandButton rendered="#{empty slot.place and not empty slot.used}"
value="#{i18n['placeslot.releaseSlot']}"
actionListener="#{placeGroupView.releaseSlot}" update="placeslots"/>
</p:column> </p:column>
</p:dataTable> </p:dataTable>
</h:form> </h:form>
</ui:define> </ui:define>
</ui:composition> </ui:composition>
</h:body> </h:body>
......
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
<h:outputText value="#{dependency.priority}"/> <h:outputText value="#{dependency.priority}"/>
</h:column> </h:column>
<h:column> <h:column>
<p:commandButton action="#{productView.deleteProductDependency}" value="#{i18n['productDependency.delete']}" update=":dependencies"/> <p:commandButton action="#{productView.deleteProductDependency}" value="#{i18n['product.dependency.delete']}" update=":dependencies"/>
</h:column> </h:column>
<!-- Not yet in use. <!-- Not yet in use.
......
...@@ -11,6 +11,7 @@ import javax.faces.context.FacesContext; ...@@ -11,6 +11,7 @@ import javax.faces.context.FacesContext;
import javax.faces.model.ListDataModel; import javax.faces.model.ListDataModel;
import javax.inject.Named; import javax.inject.Named;
import fi.codecrew.moya.exceptions.PlaceAlreadyTakenException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -79,10 +80,30 @@ public class MapPlacechangeView extends GenericCDIView { ...@@ -79,10 +80,30 @@ public class MapPlacechangeView extends GenericCDIView {
} }
public boolean isReadyForCommit() {
// If anything is not selected for commit, we are not ready..
boolean movingAny = false;
for (MoveContainer mc : moveContainers) {
// If we are moving, but destination is not selected, we are not ready..
if (mc.isMoving()) {
movingAny = true;
if (mc.getDst() == null) {
return false;
}
}
}
return movingAny;
}
public void initView() { public void initView() {
// If we are overriding user, check permission. // If we are overriding user, check permission.
if (getSlots() == null) { if (super.requirePermissions(
super.hasPermission(MapPermission.MOVE_PLACES) ||
super.hasPermission(MapPermission.MANAGE_MAPS)
) && getSlots() == null) {
if (userId != null && super.requirePermissions(MapPermission.MANAGE_OTHERS)) { if (userId != null && super.requirePermissions(MapPermission.MANAGE_OTHERS)) {
user = userbean.findByUserId(userId, false); user = userbean.findByUserId(userId, false);
} else if (super.requirePermissions(MapPermission.BUY_PLACES)) { } else if (super.requirePermissions(MapPermission.BUY_PLACES)) {
...@@ -93,23 +114,38 @@ public class MapPlacechangeView extends GenericCDIView { ...@@ -93,23 +114,38 @@ public class MapPlacechangeView extends GenericCDIView {
super.beginConversation(); super.beginConversation();
moveContainers = MoveContainer.init(placebean.getPlaceslots(user)); moveContainers = MoveContainer.init(placebean.getPlaceslots(user));
slots = new ListDataModel<MoveContainer>(moveContainers); slots = new ListDataModel<>(moveContainers);
} }
} }
public void commitMove(){ public String commitMove() {
HashMap<Place, Place> change = new HashMap<Place,Place>(); HashMap<Place, Place> change = new HashMap<Place, Place>();
for(MoveContainer s : slots){ for (MoveContainer s : slots) {
if(s.isMoving() && s.getDst() != null){ if (s.isMoving() && s.getDst() != null) {
change.put(s.getSrc().getPlace(), s.getDst()); change.put(s.getSrc().getPlace(), s.getDst());
} }
} }
placebean.movePlaces(change); try {
placebean.movePlaces(change);
} catch (PlaceAlreadyTakenException pt) {
String placename = "";
if (pt.getPlace() != null) {
placename = pt.getPlace().getName();
for (MoveContainer mv : slots) {
if (pt.getPlace().equals(mv.getDst())) {
mv.setDst(null);
}
}
}
super.addFaceMessage("placemove.alreadyTaken", placename);
return null;
slots = null; }
initView(); // slots = null;
// initView();
return "/place/myGroups?faces_redirect=true";
} }
public void toggleDstPlace() { public void toggleDstPlace() {
...@@ -117,14 +153,14 @@ public class MapPlacechangeView extends GenericCDIView { ...@@ -117,14 +153,14 @@ public class MapPlacechangeView extends GenericCDIView {
Integer placeId = new Integer(paramMap.get("placeId")); Integer placeId = new Integer(paramMap.get("placeId"));
Place place = placebean.find(placeId); Place place = placebean.find(placeId);
setToggleSuccess(false); toggleSuccess = false;
for (MoveContainer mc : getMoveContainers()) { for (MoveContainer mc : getMoveContainers()) {
if (place.equals(mc.getSrc().getPlace())) { if (place.equals(mc.getSrc().getPlace())) {
setSlotState(mc, !mc.isMoving()); setSlotState(mc, !mc.isMoving());
return; return;
} }
if (place.equals(mc.getDst())) { if (place.equals(mc.getDst())) {
setToggleSuccess(true); toggleSuccess = true;
mc.setDst(null); mc.setDst(null);
return; return;
} }
...@@ -135,7 +171,7 @@ public class MapPlacechangeView extends GenericCDIView { ...@@ -135,7 +171,7 @@ public class MapPlacechangeView extends GenericCDIView {
} }
for (MoveContainer mc : moveContainers) { for (MoveContainer mc : moveContainers) {
if (mc.isMoving() && mc.dst == null && mc.getSrc().getProduct().equals(place.getProduct())) { if (mc.isMoving() && mc.dst == null && mc.getSrc().getProduct().equals(place.getProduct())) {
setToggleSuccess(true); toggleSuccess = true;
mc.setDst(place); mc.setDst(place);
return; return;
} }
......
...@@ -731,7 +731,7 @@ place.release = Release this place ...@@ -731,7 +731,7 @@ 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.reservetime = Reservetime
place.send = Transfer place place.send = Assign to user
place.width = Width place.width = Width
placeReservation.buyConfirm.content = Are you sure, this is difficult to cancel? placeReservation.buyConfirm.content = Are you sure, this is difficult to cancel?
...@@ -782,6 +782,15 @@ placegroupview.token = Place token / user ...@@ -782,6 +782,15 @@ 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!
placemove.commitMove = Move places
placemove.deselect = Cancel relocation
placemove.dstplace = New location
placemove.header = Relocate places
placemove.placename = Place
placemove.placeuser = User
placemove.productname = Ticket type
placemove.selectSlotForMove = Select for relocation
placeslot.add = Add place slot placeslot.add = Add place slot
placeslot.bill = Bill placeslot.bill = Bill
placeslot.id = ID placeslot.id = ID
...@@ -1589,6 +1598,7 @@ reservequeue.reservingTimeIsUpAlert=Timeslot for your place reservation has time ...@@ -1589,6 +1598,7 @@ reservequeue.reservingTimeIsUpAlert=Timeslot for your place reservation has time
mapView.reserveTimeLeft=Time to reserve places mapView.reserveTimeLeft=Time to reserve places
queuemgmt.queueEnabled=Queue is ENABLED queuemgmt.queueEnabled=Queue is ENABLED
queuemgmt.queueDisabled=Queue is DISABLED (enable from Edit event -page) queuemgmt.queueDisabled=Queue is DISABLED (enable from Edit event -page)
product.dependency.add=Add product dependency product.dependency.add=Add product dependency
product.dependency.create=Create product.dependency.create=Create
product.dependency.supporter=Depended product product.dependency.supporter=Depended product
...@@ -1597,3 +1607,5 @@ product.dependency.priority=Priority ...@@ -1597,3 +1607,5 @@ product.dependency.priority=Priority
productDependency.delete=Delete productDependency.delete=Delete
product.dependency.multiplier=Multiplier product.dependency.multiplier=Multiplier
product.dependency.MAX_SUPPORTED_COUNT=Only up to same number of products can be bought product.dependency.MAX_SUPPORTED_COUNT=Only up to same number of products can be bought
submenu.neomap.moveplaces=Change places
...@@ -992,7 +992,7 @@ place.release = Release this place ...@@ -992,7 +992,7 @@ 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.reservetime = Reservetime
place.send = Transfer place place.send = Assign to user
place.width = Width place.width = Width
placeReservation.buyConfirm.content = Are you sure, this is difficult to cancel? placeReservation.buyConfirm.content = Are you sure, this is difficult to cancel?
...@@ -1042,6 +1042,15 @@ placegroupview.reserveForSelf = Select the place for yourself ...@@ -1042,6 +1042,15 @@ 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!
placemove.commitMove = Move places
placemove.deselect = Cancel relocation
placemove.dstplace = New location
placemove.header = Relocate places
placemove.placename = Place
placemove.placeuser = User
placemove.productname = Ticket type
placemove.selectSlotForMove = Select for relocation
placeslot.add = Add place slot placeslot.add = Add place slot
placeslot.bill = Bill placeslot.bill = Bill
placeslot.id = ID placeslot.id = ID
...@@ -1867,11 +1876,17 @@ reservequeue.reservingTimeIsUpAlert=Timeslot for your place reservation has time ...@@ -1867,11 +1876,17 @@ reservequeue.reservingTimeIsUpAlert=Timeslot for your place reservation has time
mapView.reserveTimeLeft=Time to reserve places mapView.reserveTimeLeft=Time to reserve places
queuemgmt.queueEnabled=Queue is ENABLED queuemgmt.queueEnabled=Queue is ENABLED
queuemgmt.queueDisabled=Queue is DISABLED (enable from Edit event -page) queuemgmt.queueDisabled=Queue is DISABLED (enable from Edit event -page)
product.dependency.add=Add product dependency product.dependency.add=Add product dependency
product.dependency.create=Create product.dependency.create=Create
product.dependency.supporter=Depended product product.dependency.supporter=Depended product
product.dependency.type=Dependency type product.dependency.type=Dependency type
product.dependency.priority=Priority product.dependency.priority=Priority
productDependency.delete=Delete product.dependency.delete=Delete
product.dependency.multiplier=Multiplier product.dependency.multiplier=Multiplier
product.dependency.MAX_SUPPORTED_COUNT=Only up to same number of products can be bought product.dependency.MAX_SUPPORTED_COUNT=Only up to same number of products can be bought
placemove.alreadyTaken=Moving the places was cancelled because place {0} was already taken.
placegroupview.moveUsersPlaces=Move users places
submenu.neomap.moveplaces=Change places
...@@ -979,7 +979,7 @@ place.release = Vapauta paikka ...@@ -979,7 +979,7 @@ 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.reservetime = Varaamisaika
place.send = Siirr\u00E4 paikka place.send = Luovuta k\u00E4ytt\u00E4j\u00E4lle
place.width = Leveys place.width = Leveys
placeReservation.buyConfirm.content = Oletko varma, t\u00E4t\u00E4 on vaikea peruuttaa? placeReservation.buyConfirm.content = Oletko varma, t\u00E4t\u00E4 on vaikea peruuttaa?
...@@ -1029,6 +1029,15 @@ placegroupview.reserveForSelf = Valitse paikka itsellesi ...@@ -1029,6 +1029,15 @@ 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!
placemove.commitMove = Siirr\u00E4 paikat
placemove.deselect = Peru siirto
placemove.dstplace = Uusi paikka
placemove.header = Siirr\u00E4 paikkoja
placemove.placename = Paikka
placemove.placeuser = K\u00E4ytt\u00E4j\u00E4
placemove.productname = Lipputyyppi
placemove.selectSlotForMove = Valitse siirrett\u00E4v\u00E4ksi
placeslot.add = Lis\u00E4\u00E4 paikkaslotti placeslot.add = Lis\u00E4\u00E4 paikkaslotti
placeslot.bill = Lasku placeslot.bill = Lasku
placeslot.id = ID placeslot.id = ID
...@@ -1854,11 +1863,16 @@ reservequeue.reservingTimeIsUpAlert=Sinulle varattu varausauka on kulunut loppuu ...@@ -1854,11 +1863,16 @@ reservequeue.reservingTimeIsUpAlert=Sinulle varattu varausauka on kulunut loppuu
mapView.reserveTimeLeft=Aikaa varata paikkasi mapView.reserveTimeLeft=Aikaa varata paikkasi
queuemgmt.queueEnabled=Varausjono ON k\u00E4yt\u00F6ss\u00E4 queuemgmt.queueEnabled=Varausjono ON k\u00E4yt\u00F6ss\u00E4
queuemgmt.queueDisabled=K\u00E4ytt\u00E4j\u00E4jono EI OLE k\u00E4yt\u00F6ss\u00E4 (ota k\u00E4yttoon tapahtuman tiedot -sivulta) queuemgmt.queueDisabled=K\u00E4ytt\u00E4j\u00E4jono EI OLE k\u00E4yt\u00F6ss\u00E4 (ota k\u00E4yttoon tapahtuman tiedot -sivulta)
product.dependency.add=Lis\u00E4\u00E4 tuoteriippuvuus product.dependency.add=Lis\u00E4\u00E4 tuoteriippuvuus
product.dependency.create=Luo uusi product.dependency.create=Luo uusi
product.dependency.supporter=Tuote josta on riippuvuus product.dependency.supporter=Tuote josta on riippuvuus
product.dependency.type=Riippuvuuden tyyppi product.dependency.type=Riippuvuuden tyyppi
product.dependency.priority=Prioriteetti product.dependency.priority=Prioriteetti
productDependency.delete=Poista product.dependency.delete=Poista
product.dependency.multiplier=Kerroin product.dependency.multiplier=Kerroin
product.dependency.MAX_SUPPORTED_COUNT=Tuotteita voi ostaa enint\u00E4\u00E4n saman m\u00E4\u00E4r\u00E4n product.dependency.MAX_SUPPORTED_COUNT=Tuotteita voi ostaa enint\u00E4\u00E4n saman m\u00E4\u00E4r\u00E4n
placemove.alreadyTaken=Paikkojen siirto peruuntui koska paikka {0} oli jo varattu.
placegroupview.moveUsersPlaces=Siirr\u00E4 k\u00E4ytt\u00E4j\u00E4n paikkoja
submenu.neomap.moveplaces=Vaihda paikkoja
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!