Commit 25e294c8 by Tuukka Kivilahti

Merge branch 'viplist' into 'master'

Viplist

Viplist deploy version

See merge request !225
2 parents e3c61103 62ec027a
Showing with 1799 additions and 129 deletions
package fi.codecrew.moya.beans;
import java.math.BigDecimal;
import java.util.List;
import javax.ejb.Local;
import fi.codecrew.moya.model.Vip;
import fi.codecrew.moya.model.VipProduct;
import fi.codecrew.moya.model.VipProductDelivery;
import fi.codecrew.moya.utilities.SearchQuery;
import fi.codecrew.moya.utilities.SearchResult;
@Local
public interface VipBeanLocal {
List<Vip> getAvailableVips();
SearchResult<Vip> search(SearchQuery sq);
void create(Vip vip);
Vip find(Integer id);
Vip createProduct(VipProduct l);
Vip save(Vip vip);
Vip saveProduct(VipProduct rowData);
Vip deleteProduct(VipProduct l);
VipProductDelivery createDelivery(VipProduct prod, BigDecimal quantity, String notes);
}
......@@ -29,7 +29,7 @@ import javax.ejb.Startup;
import fi.codecrew.moya.facade.DBModelFacade;
import fi.codecrew.moya.facade.UserFacade;
import fi.codecrew.moya.model.DBModel;
import fi.codecrew.moya.model.User;
import fi.codecrew.moya.sql.DDLBuilder;
@Singleton
@Startup
......@@ -254,7 +254,30 @@ public class BootstrapBean implements BootstrapBeanLocal {
"DELETE FROM product_limitations_roles where productlimitation_id in (SELECT id FROM product_limitations WHERE TYPE = 'PLACE')",
"DELETE FROM products_product_limitations where productlimits_id in (SELECT id FROM product_limitations WHERE TYPE = 'PLACE')",
"DELETE FROM product_limitations WHERE TYPE = 'PLACE'",
});
dbUpdates.add(new String[] {
new DDLBuilder().createTable("vips")
.serialPK("id")
.text("description", false)
.timestampTZ("created", false, "default", "now()")
.reference("event_id", false, "events")
.reference("vip_event_user_id", true, "event_users")
.reference("creator_event_user_id", false, "event_users")
.reference("host_event_user_id", false, "event_users")
.field("meta", "json", true)
.toString()
});
dbUpdates.add(new String[] {
"CREATE TABLE vip_product_deliveries (id SERIAL NOT NULL, DELIVERYTIME TIMESTAMPTZ NOT NULL, meta json, NOTES TEXT, quantity DECIMAL(24,4) NOT NULL, DELIVERER_id INTEGER NOT NULL, VIPPRODUCT_id INTEGER NOT NULL, PRIMARY KEY (id))",
"CREATE TABLE vip_products (id SERIAL NOT NULL, meta json, NAME TEXT, NOTES TEXT, quantity DECIMAL(24,4) NOT NULL, PRODUCT_id INTEGER, VIP_id INTEGER NOT NULL, PRIMARY KEY (id))",
"ALTER TABLE vip_product_deliveries ADD CONSTRAINT FK_vip_product_deliveries_DELIVERER_id FOREIGN KEY (DELIVERER_id) REFERENCES event_users (id)",
"ALTER TABLE vip_product_deliveries ADD CONSTRAINT FK_vip_product_deliveries_VIPPRODUCT_id FOREIGN KEY (VIPPRODUCT_id) REFERENCES vip_products (id)",
"ALTER TABLE vip_products ADD CONSTRAINT FK_vip_products_PRODUCT_id FOREIGN KEY (PRODUCT_id) REFERENCES products (id)",
"ALTER TABLE vip_products ADD CONSTRAINT FK_vip_products_VIP_id FOREIGN KEY (VIP_id) REFERENCES vips (id)",
"ALTER TABLE vips ADD shortdescr TEXT"
});
}
......
......@@ -43,6 +43,7 @@ import fi.codecrew.moya.enums.apps.SpecialPermission;
import fi.codecrew.moya.enums.apps.TerminalPermission;
import fi.codecrew.moya.enums.apps.TournamentPermission;
import fi.codecrew.moya.enums.apps.UserPermission;
import fi.codecrew.moya.enums.apps.VipPermission;
import fi.codecrew.moya.facade.MenuNavigationFacade;
import fi.codecrew.moya.facade.MenuitemFacade;
import fi.codecrew.moya.model.LanEvent;
......@@ -109,7 +110,7 @@ public class MenuBean implements MenuBeanLocal {
MenuNavigation usermenu = new MenuNavigation(ev, "topmenu.user", 5);
usermenu.addPage(menuitemfacade.findOrCreate("/frontpage"), UserPermission.ANYUSER);
usermenu.addPage(menuitemfacade.findOrCreate("/frontpage"), UserPermission.ANYUSER);
usermenu.addPage(menuitemfacade.findOrCreate("/checkout/return"), null).setVisible(false);
usermenu.addPage(menuitemfacade.findOrCreate("/checkout/delayed"), null).setVisible(false);
usermenu.addPage(menuitemfacade.findOrCreate("/checkout/reject"), null).setVisible(false);
......@@ -124,7 +125,6 @@ public class MenuBean implements MenuBeanLocal {
usermenu.addPage(menuitemfacade.findOrCreate("/auth/resetmailSent"), null).setVisible(false);
usermenu.addPage(menuitemfacade.findOrCreate("/auth/passwordChanged"), null).setVisible(false);
usermenu.addPage(menuitemfacade.findOrCreate("/auth/notauthorized"), null).setVisible(false);
MenuNavigation userEvent = usermenu.addPage(null, null);
userEvent.setKey("topnavi.userevent");
......@@ -133,23 +133,24 @@ public class MenuBean implements MenuBeanLocal {
userEvent.addPage(menuitemfacade.findOrCreate("/user/invite"), UserPermission.INVITE_USERS);
userEvent.addPage(menuitemfacade.findOrCreate("/feedback/index"), UserPermission.VITUTTAAKO);
MenuNavigation helpmenu = usermenu.addPage(null, null);
helpmenu.setKey("topnavi.help");
helpmenu.addPage(menuitemfacade.findOrCreate("/help"), UserPermission.HELPPAGE);
MenuNavigation userkauppa = usermenu.addPage(null, null);
userkauppa.setKey("topnavi.usershop");
userkauppa.addPage(menuitemfacade.findOrCreate("/shop/createBill"), BillPermission.CREATE_BILL);
userkauppa.addPage(menuitemfacade.findOrCreate("/neomap/reserve"), MapPermission.BUY_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("/foodwave/list"), ShopPermission.SHOP_FOODWAVE);
userkauppa.addPage(menuitemfacade.findOrCreate("/foodwave/listProducts"), ShopPermission.SHOP_FOODWAVE).setVisible(false);
userkauppa.addPage(menuitemfacade.findOrCreate("/foodwave/ThanksForOrderingFromCounter"), ShopPermission.SHOP_FOODWAVE).setVisible(false);
userkauppa.addPage(menuitemfacade.findOrCreate("/svm/success"), UserPermission.ANYUSER).setVisible(false); // landingpages are always "anyuser"
userkauppa.addPage(menuitemfacade.findOrCreate("/svm/notification"), UserPermission.ANYUSER).setVisible(false);
userkauppa.addPage(menuitemfacade.findOrCreate("/svm/pending"), UserPermission.ANYUSER).setVisible(false);
userkauppa.addPage(menuitemfacade.findOrCreate("/svm/notification"), UserPermission.ANYUSER).setVisible(false);
userkauppa.addPage(menuitemfacade.findOrCreate("/svm/pending"), UserPermission.ANYUSER).setVisible(false);
userkauppa.addPage(menuitemfacade.findOrCreate("/bill/list"), BillPermission.VIEW_OWN);
userkauppa.addPage(menuitemfacade.findOrCreate("/bill/edit"), BillPermission.VIEW_OWN).setVisible(false);
userkauppa.addPage(menuitemfacade.findOrCreate("/bill/showBill"), BillPermission.VIEW_OWN).setVisible(false);
......@@ -193,7 +194,7 @@ public class MenuBean implements MenuBeanLocal {
MenuNavigation createuser = usermenu.addPage(null, null);
createuser.setKey("topnavi.createuser");
createuser.addPage(menuitemfacade.findOrCreate("/user/create"), UserPermission.CREATE_NEW).setVisible(false);
MenuNavigation userlectures = usermenu.addPage(null, null);
userlectures.setKey("topnavi.userlectures");
userlectures.addPage(menuitemfacade.findOrCreate("/lectures/viewLectures"), LecturePermission.VIEW);
......@@ -242,10 +243,19 @@ public class MenuBean implements MenuBeanLocal {
adminEventCards.addPage(menuitemfacade.findOrCreate("/shop/shopToUser"), null).setVisible(false);
adminEventCards.addPage(menuitemfacade.findOrCreate("/shop/assocToUser"), null).setVisible(false);
MenuNavigation vips = adminuser.addPage(null, null);
vips.setKey("subnavi.vips");
vips.addPage(menuitemfacade.findOrCreate("/vip/viplist"), VipPermission.VIEW);
vips.addPage(menuitemfacade.findOrCreate("/vip/create"), VipPermission.VIEW).setVisible(false);
vips.addPage(menuitemfacade.findOrCreate("/vip/edit"), VipPermission.VIEW).setVisible(false);
MenuNavigation adminAssociation = adminmenu.addPage(null, null);
adminAssociation.setKey("topnavi.adminassoc");
adminAssociation.addPage(menuitemfacade.findOrCreate("/networkassociation/index"), NetworkAssociationPermission.CAN_ADMINISTER_ASSOCIATIONS);
// shop
MenuNavigation adminshop = adminmenu.addPage(null, null);
adminshop.setKey("topnavi.adminshop");
......@@ -317,10 +327,8 @@ public class MenuBean implements MenuBeanLocal {
adminevent.addPage(menuitemfacade.findOrCreate("/eventorg/editEvent"), EventPermission.MANAGE_PROPERTIES);
adminevent.addPage(menuitemfacade.findOrCreate("/eventorg/edit"), EventPermission.MANAGE_PROPERTIES).setVisible(false);
adminevent.addPage(menuitemfacade.findOrCreate("/reports/basicStatistics"), EventPermission.VIEW_STATISTICS);
MenuNavigation tournamentsadm = adminmenu.addPage(null, null);
tournamentsadm.setKey("tournaments.menutitle");
......@@ -332,20 +340,17 @@ public class MenuBean implements MenuBeanLocal {
tournamentsadm.addPage(menuitemfacade.findOrCreate("/tournaments/admin/delete"), TournamentPermission.MANAGE_ALL).setVisible(false);
tournamentsadm.addPage(menuitemfacade.findOrCreate("/tournaments/admin/editrules"), TournamentPermission.MANAGE_ALL).setVisible(false);
MenuNavigation adminlectures = adminmenu.addPage(null, null);
adminlectures.setKey("topnavi.adminlectures");
adminlectures.addPage(menuitemfacade.findOrCreate("/lectureadmin/manageLectureGroups"), LecturePermission.MANAGE);
adminlectures.addPage(menuitemfacade.findOrCreate("/lectureadmin/lectureParticipants"), LecturePermission.MANAGE);
adminlectures.addPage(menuitemfacade.findOrCreate("/lectureadmin/manageLectures"), LecturePermission.MANAGE).setVisible(false);
adminlectures.addPage(menuitemfacade.findOrCreate("/lectureadmin/manageParticipants"), LecturePermission.MANAGE).setVisible(false);
MenuNavigation infoviews = adminmenu.addPage(null, null);
infoviews.setKey("topnavi.infoviews");
infoviews.addPage(menuitemfacade.findOrCreate("/admin/adduser/index"), TerminalPermission.INFO);
MenuNavigation infonavi = infoviews.addPage(null, null);
infonavi.setKey("subnavi.info");
infonavi.addPage(menuitemfacade.findOrCreate("/info/index"), TerminalPermission.INFO);
......@@ -514,7 +519,7 @@ public class MenuBean implements MenuBeanLocal {
MenuNavigation foodwaveTopmenu = usernavi.addPage(null, null);
foodwaveTopmenu.setKey("topnavi.foodwave");
foodwaveTopmenu.addPage(menuitemfacade.findOrCreate("/foodwave/list"), ShopPermission.SHOP_FOODWAVE);
// foodwaveTopmenu.addPage(menuitemfacade.findOrCreate("/foodwave/listTemplates"),
// ShopPermission.SHOP_FOODWAVE);
foodwaveTopmenu.addPage(menuitemfacade.findOrCreate("/foodwave/listProducts"), ShopPermission.SHOP_FOODWAVE).setVisible(false);
......
package fi.codecrew.moya.beans;
import fi.codecrew.moya.enums.apps.VipPermission;
import fi.codecrew.moya.facade.VipFacade;
import fi.codecrew.moya.facade.VipProductDeliveryFacade;
import fi.codecrew.moya.facade.VipProductFacade;
import fi.codecrew.moya.model.Vip;
import fi.codecrew.moya.model.VipProduct;
import fi.codecrew.moya.model.VipProductDelivery;
import fi.codecrew.moya.utilities.SearchQuery;
import fi.codecrew.moya.utilities.SearchResult;
import fi.codecrew.moya.utilities.jpa.GenericFacade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@Stateless
@LocalBean
@DeclareRoles({
VipPermission.S_VIEW,
VipPermission.S_USAGE,
VipPermission.S_EDIT
})
public class VipBean implements VipBeanLocal {
private static final Logger log = LoggerFactory.getLogger(VipBean.class);
//@EJB
//private PermissionBeanLocal permissionBean;
@EJB
private VipFacade vipFacade;
@EJB
private PermissionBeanLocal permbean;
@EJB
private EventBeanLocal eventbean;
@EJB
private VipProductFacade vipProductFacade;
@EJB
private VipProductDeliveryFacade vpdFacade;
@Override
@RolesAllowed({ VipPermission.S_VIEW })
public List<Vip> getAvailableVips() {
return vipFacade.findForEvent();
}
@Override
public void create(Vip vip) {
vip.setCreated(new Date());
vip.setCreator(permbean.getCurrentUser());
vip.setEvent(eventbean.getCurrentEvent());
if (vip.getHost() == null) {
vip.setHost(vip.getCreator());
}
vipFacade.create(vip);
}
@Override
public Vip find(Integer id) {
return vipFacade.find(id);
}
// @Override
// public SearchResult<Vip> search(SearchQuery sq) {
// // TODO Auto-generated method stub
// return null;
// }
@Override
public Vip createProduct(VipProduct l) {
Vip vip = vipFacade.reload(l.getVip());
l.setVip(vip);
if (!vip.getProducts().contains(l))
vip.getProducts().add(0, l);
vipProductFacade.create(l);
return vip;
}
@Override
public SearchResult<Vip> search(SearchQuery sq) {
// TODO Auto-generated method stub
return null;
}
@Override
public Vip save(Vip vip) {
return vipFacade.merge(vip);
}
@Override
public Vip saveProduct(VipProduct prod) {
VipProduct ret = vipProductFacade.merge(prod);
return ret.getVip();
}
@Override
public Vip deleteProduct(VipProduct l) {
l = vipProductFacade.reload(l);
Vip vip = l.getVip();
vip.getProducts().remove(l);
vipProductFacade.remove(l);
return vip;
}
@Override
public VipProductDelivery createDelivery(VipProduct prod, BigDecimal quantity, String notes) {
prod = vipProductFacade.reload(prod);
VipProductDelivery vpd = new VipProductDelivery();
vpd.setVipProduct(prod);
vpd.setDeliverer(permbean.getCurrentUser());
vpd.setNotes(notes);
vpd.setDeliveryTime(new Date());
vpd.setQuantity(quantity);
vpdFacade.create(vpd);
prod.getDeliveries().add(vpd);
return vpd;
}
}
package fi.codecrew.moya.facade;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import fi.codecrew.moya.beans.EventBeanLocal;
import fi.codecrew.moya.model.LanEvent;
import fi.codecrew.moya.model.Vip;
import fi.codecrew.moya.model.Vip_;
@Stateless
@LocalBean
public class VipFacade extends IntegerPkGenericFacade<Vip> {
public VipFacade() {
super(Vip.class);
}
@EJB
private EventBeanLocal eventBean;
public List<Vip> findForEvent() {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<Vip> cq = cb.createQuery(Vip.class);
Root<Vip> root = cq.from(Vip.class);
LanEvent event = eventBean.getCurrentEvent();
cq.where(cb.equal(root.get(Vip_.event), event));
return getEm().createQuery(cq).getResultList();
}
}
package fi.codecrew.moya.facade;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import fi.codecrew.moya.model.VipProduct;
import fi.codecrew.moya.model.VipProductDelivery;
@Stateless
@LocalBean
public class VipProductDeliveryFacade extends IntegerPkGenericFacade<VipProductDelivery> {
public VipProductDeliveryFacade() {
super(VipProductDelivery.class);
}
}
package fi.codecrew.moya.facade;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import fi.codecrew.moya.beans.EventBeanLocal;
import fi.codecrew.moya.model.LanEvent;
import fi.codecrew.moya.model.Vip;
import fi.codecrew.moya.model.VipProduct;
import fi.codecrew.moya.model.Vip_;
@Stateless
@LocalBean
public class VipProductFacade extends IntegerPkGenericFacade<VipProduct> {
public VipProductFacade() {
super(VipProduct.class);
}
}
......@@ -39,6 +39,21 @@
<version>${moya.version}</version>
</dependency>
<!--
<dependency>
<groupId>javax.ejb</groupId>
<artifactId>javax.ejb-api</artifactId>
<version>3.2</version>
<scope>test</scope>
</dependency>
-->
<dependency>
<groupId>org.glassfish.main.extras</groupId>
<artifactId>glassfish-embedded-web</artifactId>
<version>4.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<parent>
<groupId>fi.codecrew.moya</groupId>
......
package fi.codecrew.moya.beans;
import org.testng.annotations.BeforeTest;
import javax.ejb.embeddable.EJBContainer;
import javax.naming.NamingException;
public abstract class AbstractEjbTest {
@BeforeTest
public void setUpInjector() throws NamingException {
EJBContainer container = EJBContainer.createEJBContainer();
container.getContext().bind("inject", this);
}
}
package fi.codecrew.moya.beans;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.Test;
@Test
public class VipBeanTest {
private static final Logger log = LoggerFactory.getLogger(VipBeanTest.class);
@Test
public void testVip() {
log.info("testVip");
VipBean vipBean = new VipBean();
}
}
......@@ -19,6 +19,7 @@
package fi.codecrew.moya.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
......@@ -128,6 +129,9 @@ public class LanEvent extends GenericEntity {
@OneToMany(mappedBy = "event", cascade = CascadeType.ALL)
private List<LanEventProperty> properties = new ArrayList<LanEventProperty>();
// @OneToMany(mappedBy = "event")
// private List<Vip> vips;
public LanEvent() {
}
......@@ -333,4 +337,11 @@ public class LanEvent extends GenericEntity {
this.theme = theme;
}
// public List<Vip> getVips() {
// return vips;
// }
//
// public void setVips(List<Vip> vips) {
// this.vips = vips;
// }
}
package fi.codecrew.moya.model;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* VIP list. Info staff will use the VIP list information to allow certain
* special treatment of people :)
*
* The VIP list entry can be just a free form description containing the names
* of VIPs and what makes them VIP, or the entry may refer to an EventUser.
*
* Every VIP entry must have a responsible person in the organization. Creator
* must also be recorder.
*
*/
@Entity
@Table(name = "vips")
public class Vip extends GenericEntity {
private static final long serialVersionUID = 1L;
private static final String EVENT_ID_COLUMN = "event_id";
private static final String VIP_EVENT_USER_ID_COLUMN = "vip_event_user_id";
private static final String CREATOR_EVENT_USER_ID_COLUMN = "creator_event_user_id";
private static final String HOST_EVENT_USER_ID_COLUMN = "host_event_user_id";
@Column(name = "description", nullable = false)
@Lob
private String description;
@Column(name = "shortdescr", nullable = false)
@Lob
private String shortdescr;
@Column(name = "created", nullable = false, updatable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date created = new Date();
@ManyToOne
@JoinColumn(name = EVENT_ID_COLUMN, referencedColumnName = LanEvent.ID_COLUMN, nullable = false)
private LanEvent event;
@ManyToOne
@JoinColumn(name = VIP_EVENT_USER_ID_COLUMN, referencedColumnName = EventUser.ID_COLUMN, nullable = true)
private EventUser eventUser;
/**
* Mandatory creator of this VIP list entry.
*/
@ManyToOne
@JoinColumn(name = CREATOR_EVENT_USER_ID_COLUMN, referencedColumnName = EventUser.ID_COLUMN, nullable = false)
private EventUser creator;
/**
* Mandatory responsible person of this VIP list entry.
*/
@ManyToOne
@JoinColumn(name = HOST_EVENT_USER_ID_COLUMN, referencedColumnName = EventUser.ID_COLUMN, nullable = false)
private EventUser host;
@OneToMany(mappedBy = "vip")
private List<VipProduct> products = new ArrayList<>();
public String getShortDisplayDescr() {
String ret = shortdescr;
if ((ret == null || ret.trim().isEmpty()) && description != null) {
ret = description;
if (description.length() > 85)
ret = description.substring(0, 80);
}
return ret;
}
public String getSearchableProductnames()
{
StringBuilder sb = new StringBuilder();
for (VipProduct p : products) {
sb.append(p.getProductName());
sb.append(" ");
}
return sb.toString();
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public LanEvent getEvent() {
return event;
}
public void setEvent(LanEvent event) {
this.event = event;
}
public EventUser getEventUser() {
return eventUser;
}
public void setEventUser(EventUser eventUser) {
this.eventUser = eventUser;
}
public EventUser getCreator() {
return creator;
}
public void setCreator(EventUser creator) {
this.creator = creator;
}
public EventUser getHost() {
return host;
}
public void setHost(EventUser host) {
this.host = host;
}
public String getShortdescr() {
return shortdescr;
}
public void setShortdescr(String shortdescr) {
this.shortdescr = shortdescr;
}
public List<VipProduct> getProducts() {
return products;
}
public void setProducts(List<VipProduct> products) {
this.products = products;
}
}
package fi.codecrew.moya.model;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity
@Table(name = "vip_products")
public class VipProduct extends GenericEntity {
/**
*
*/
private static final long serialVersionUID = 1L;
@ManyToOne()
@JoinColumn(nullable = false)
private Vip vip;
/**
* If product is null this is used as the name of the product
*/
private String name;
@ManyToOne()
@JoinColumn(nullable = true)
private Product product;
@Lob
private String notes;
/** How many products should be given to the vip */
@Column(name = "quantity", nullable = false, precision = 24, scale = 4)
private BigDecimal quantity = BigDecimal.ONE;
@OneToMany(mappedBy = "vipProduct")
private List<VipProductDelivery> deliveries = new ArrayList<>();
public VipProduct() {
super();
}
public VipProduct(Vip v) {
this();
this.vip = v;
}
/**
* Returns name of the product. If @Field product is empty, use @Field name
*
* @return
*/
@Transient
public String getProductName() {
String ret = name;
if (product != null) {
ret = product.getName();
}
return ret;
}
/**
* Have all products been delivered?
*
* @return
*/
public boolean isAllDelivered()
{
return quantity.compareTo(getDelivered()) <= 0;
}
public BigDecimal getDelivered()
{
BigDecimal delivered = BigDecimal.ZERO;
if (deliveries != null) {
for (VipProductDelivery d : deliveries) {
delivered = delivered.add(d.getQuantity());
}
}
return delivered;
}
public Vip getVip() {
return vip;
}
public void setVip(Vip vip) {
this.vip = vip;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public BigDecimal getQuantity() {
return quantity;
}
public void setQuantity(BigDecimal quantity) {
this.quantity = quantity;
}
public List<VipProductDelivery> getDeliveries() {
return deliveries;
}
public void setDeliveries(List<VipProductDelivery> deliveries) {
this.deliveries = deliveries;
}
}
package fi.codecrew.moya.model;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@Entity
@Table(name = "vip_product_deliveries")
public class VipProductDelivery extends GenericEntity {
private static final long serialVersionUID = 1L;
@Temporal(TemporalType.TIMESTAMP)
@Column(nullable = false)
private Date deliveryTime;
@JoinColumn(nullable = false)
@ManyToOne
private VipProduct vipProduct;
@JoinColumn(nullable = false)
@ManyToOne
private EventUser deliverer;
/** How many products has been given to the vip */
@Column(name = "quantity", nullable = false, precision = 24, scale = 4)
private BigDecimal quantity = BigDecimal.ONE;
@Lob
private String notes;
public Date getDeliveryTime() {
return deliveryTime;
}
public void setDeliveryTime(Date deliveryTime) {
this.deliveryTime = deliveryTime;
}
public VipProduct getVipProduct() {
return vipProduct;
}
public void setVipProduct(VipProduct vipProduct) {
this.vipProduct = vipProduct;
}
public EventUser getDeliverer() {
return deliverer;
}
public void setDeliverer(EventUser deliverer) {
this.deliverer = deliverer;
}
public BigDecimal getQuantity() {
return quantity;
}
public void setQuantity(BigDecimal quantity) {
this.quantity = quantity;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
}
......@@ -18,21 +18,7 @@
*/
package fi.codecrew.moya.enums;
import fi.codecrew.moya.enums.apps.BillPermission;
import fi.codecrew.moya.enums.apps.CompoPermission;
import fi.codecrew.moya.enums.apps.ContentPermission;
import fi.codecrew.moya.enums.apps.EventPermission;
import fi.codecrew.moya.enums.apps.IAppPermission;
import fi.codecrew.moya.enums.apps.LecturePermission;
import fi.codecrew.moya.enums.apps.LicensePermission;
import fi.codecrew.moya.enums.apps.MapPermission;
import fi.codecrew.moya.enums.apps.NetworkAssociationPermission;
import fi.codecrew.moya.enums.apps.PollPermission;
import fi.codecrew.moya.enums.apps.SalespointPermission;
import fi.codecrew.moya.enums.apps.ShopPermission;
import fi.codecrew.moya.enums.apps.TerminalPermission;
import fi.codecrew.moya.enums.apps.TournamentPermission;
import fi.codecrew.moya.enums.apps.UserPermission;
import fi.codecrew.moya.enums.apps.*;
public enum BortalApplication {
USER(UserPermission.class),
......@@ -48,7 +34,8 @@ public enum BortalApplication {
EVENT(EventPermission.class),
LICENSE(LicensePermission.class),
TOURNAMENT(TournamentPermission.class),
NETWORKASSOCIATION(NetworkAssociationPermission.class)
NETWORKASSOCIATION(NetworkAssociationPermission.class),
VIP(VipPermission.class)
;
private final String key;
......
package fi.codecrew.moya.enums.apps;
import fi.codecrew.moya.enums.BortalApplication;
/**
* Created by jkj on 2015-01-11.
*/
public enum VipPermission implements IAppPermission {
VIEW,
USAGE,
EDIT;
public static final String S_VIEW = "VIP/VIEW";
public static final String S_USAGE = "VIP/USAGE";
public static final String S_EDIT = "VIP/EDIT";
private final String fullName;
private final String key;
public static final String I18N_HEADER = "bortalApplication.vip.";
private VipPermission() {
fullName = new StringBuilder().append(getParent().toString()).append(DELIMITER).append(toString()).toString();
key = I18N_HEADER + name();
}
@Override
public BortalApplication getParent() {
return BortalApplication.VIP;
}
@Override
public String getFullName() {
return fullName;
}
@Override
public String getI18nKey() {
return key;
}
}
package fi.codecrew.moya.sql;
import java.util.ArrayList;
import java.util.List;
/**
* CREATE TABLE tableName
*/
public class CreateTableDDL {
private final String tableName;
private final boolean ifNotExists;
private final List<Field> tableFields;
public CreateTableDDL(String tableName) {
this.tableName = tableName;
this.ifNotExists = false;
this.tableFields = new ArrayList<Field>();
}
public CreateTableDDL(String tableName, boolean iFNotExists) {
this.tableName = tableName;
this.ifNotExists = iFNotExists;
this.tableFields = new ArrayList<Field>();
}
CreateTableDDL(String tableName, boolean ifNotExists, List<Field> fields) {
this.tableName = tableName;
this.ifNotExists = ifNotExists;
this.tableFields = new ArrayList<Field>(fields);
}
private CreateTableDDL withNewField(Field field) {
ArrayList<Field> newFieldSet = new ArrayList<Field>(tableFields.size() + 1);
newFieldSet.addAll(tableFields);
newFieldSet.add(field);
return new CreateTableDDL(tableName, ifNotExists, newFieldSet);
}
private String fieldsString() {
String[] strs = new String[tableFields.size()];
for (int i = 0; i<strs.length; i++) {
strs[i] = tableFields.get(i).toString();
}
return String.join(", ", strs);
}
@Override
public String toString() {
return String.join(" ", "CREATE TABLE", tableName, "(" + fieldsString() + ");");
}
public CreateTableDDL serialPK(String name) {
return withNewField(new Field(name, "serial", false, "PRIMARY KEY"));
}
public CreateTableDDL integerField(String name, boolean nullable, String... params) {
return withNewField(new Field(name, "integer", nullable, params));
}
public CreateTableDDL reference(String name, boolean nullable, String targetTable) {
return withNewField(new Field(name, "integer", nullable, "REFERENCES", targetTable));
}
public CreateTableDDL reference(String name, boolean nullable, String targetTable, String targetColumn) {
return withNewField(new Field(name, "integer", nullable, "REFERENCES", targetTable, "(" + targetColumn + ")"));
}
public CreateTableDDL text(String name, boolean nullable, String... params) {
return withNewField(new Field(name, "text", nullable, params));
}
public CreateTableDDL timestampTZ(String name, boolean nullable, String... params) {
return withNewField(new Field(name, "timestamptz", nullable, params));
}
public CreateTableDDL field(String name, String type, boolean nullable, String... params) {
return withNewField(new Field(name, type, nullable, params));
}
}
package fi.codecrew.moya.sql;
/**
* Make PostgreSQL DDL for table creation, etc.
*/
public class DDLBuilder {
public CreateTableDDL createTable(String tableName) {
return new CreateTableDDL(tableName);
}
public CreateTableDDL createTable(String tableName, boolean iFNotExists) {
return new CreateTableDDL(tableName, iFNotExists);
}
/**
* @param tableName
* @param params extra params such as CASCADE or RESTRICT
* @return
*/
public DropTableDDL dropTable(String tableName, String... params) {
return new DropTableDDL(tableName, params);
}
/**
* @param tableName
* @param ifExists use IF EXISTS flag to ignore error when table is not found
* @param params extra params such as CASCADE or RESTRICT
* @return
*/
public DropTableDDL dropTable(String tableName, boolean ifExists, String... params) {
return new DropTableDDL(tableName, ifExists, params);
}
}
package fi.codecrew.moya.sql;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class DropTableDDL {
private final String tableName;
private final String[] params;
private final boolean ifExists;
public DropTableDDL(String tableName, String... params) {
this.tableName = tableName;
this.ifExists = false;
this.params = params;
}
public DropTableDDL(String tableName, boolean ifExists, String... params) {
this.tableName = tableName;
this.ifExists = ifExists;
this.params = params;
}
@Override
public String toString() {
List<String> words = new ArrayList<String>();
words.add("DROP TABLE");
// IF EXISTS flag
if (ifExists) {
words.add("IF EXISTS");
}
// Extra params such as CASCADE or RESTRICT
if (params.length>0) {
words.addAll(Arrays.asList(params));
}
return String.join(" ", "DROP TABLE", tableName);
}
}
package fi.codecrew.moya.sql;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class Field {
private String fieldName;
private String fieldType;
private boolean nullable;
private final String[] params;
Field(String fieldName, String fieldType, boolean nullable) {
this.fieldName = fieldName;
this.fieldType = fieldType;
this.nullable = nullable;
this.params = new String[]{};
}
Field(String fieldName, String fieldType, boolean nullable, String... params) {
this.fieldName = fieldName;
this.fieldType = fieldType;
this.nullable = nullable;
this.params = params;
}
@Override
public String toString() {
List<String> words = new ArrayList<String>();
words.add(fieldName);
words.add(fieldType);
if (nullable == false) {
words.add("NOT NULL");
}
if (params.length>0) {
words.addAll(Arrays.asList(params));
}
return String.join(" ", words);
}
}
package fi.codecrew.moya.sql;
import org.testng.Assert;
import org.testng.annotations.Test;
@Test
public class CreateTableTest {
@Test
void testCreateSimpleTable() {
String expectedSql = "CREATE TABLE taulu (id serial NOT NULL PRIMARY KEY, numero integer);";
String actualSql = new DDLBuilder()
.createTable("taulu")
.serialPK("id")
.integerField("numero", true)
.toString();
Assert.assertEquals(actualSql, expectedSql);
}
@Test
void testCreateVipTable() {
String actual = new DDLBuilder().createTable("vips")
.serialPK("id")
.text("description", false)
.timestampTZ("created", false, "default", "now()")
.reference("event_id", false, "events")
.reference("vip_event_user_id", true, "event_users")
.reference("creator_event_user_id", false, "event_users")
.reference("host_event_user_id", false, "event_users")
.field("meta", "json", true)
.toString();
String expected = "CREATE TABLE vips (id serial NOT NULL PRIMARY KEY, description text NOT NULL, created timestamptz NOT NULL default now(), event_id integer NOT NULL REFERENCES events, vip_event_user_id integer REFERENCES event_users, creator_event_user_id integer NOT NULL REFERENCES event_users, host_event_user_id integer NOT NULL REFERENCES event_users, meta json);";
Assert.assertEquals(actual, expected);
}
}
......@@ -9,10 +9,14 @@
<var>i18n</var>
</resource-bundle>
<message-bundle>fi.codecrew.moya.resources.i18n</message-bundle>
<locale-config>
<locale-config>
<default-locale>fi</default-locale>
<supported-locale>en</supported-locale>
</locale-config>
<action-listener>org.primefaces.application.DialogActionListener</action-listener>
<navigation-handler>org.primefaces.application.DialogNavigationHandler</navigation-handler>
<view-handler>org.primefaces.application.DialogViewHandler</view-handler>
</application>
<!-- <navigation-rule> -->
......
......@@ -19,11 +19,12 @@
<h1>#{i18n['userlist.header']}</h1>
<h:form styleClass="useradmin_list">
<h:form id="pageform" styleClass="useradmin_list">
<h:panelGrid columns="2">
<h:panelGroup>
<a id="show_advanced_search"><h:outputText value="#{i18n['userlist.showAdvancedSearch']}" /></a>
<a id="show_advanced_search" onclick="$('#advancedSearch').show(); $(this).hide();">
<h:outputText value="#{i18n['userlist.showAdvancedSearch']}" /></a>
<div id="advancedSearch" style="display: none;">
<h:selectBooleanCheckbox id="placeassoc" value="#{userSearchView.searchQuery.placeAssoc}" />
<h:outputLabel for="placeassoc" value="#{i18n['userlist.placeassoc']}" />
......
<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui">
<h:body>
<ui:composition template="#{sessionHandler.template}">
<f:metadata>
<f:event type="preRenderView" listener="#{vipView.initCreate}" />
</f:metadata>
<ui:define name="content">
<h:form id="vipcreate">
<h:panelGrid columns="2">
<h:outputLabel value="#{i18n['vip.host']}" for="hostselect" />
<p:autoComplete id="hostselect" value="#{vipView.vip.host}" completeMethod="#{vipView.usersearch}" converter="#{eventUserConverter}" var="usr" itemValue="#{usr}" itemLabel="#{usr.wholeName}" />
<h:outputLabel for="shortdescr" value="#{i18n['vip.shortdescr']}" />
<p:inputTextarea id="shortdescr" cols="50" rows="3" value="#{vipView.vip.shortdescr}" />
<h:outputLabel for="description" value="#{i18n['vip.description']}" />
<p:inputTextarea id="description" cols="50" rows="6" value="#{vipView.vip.description}" />
</h:panelGrid>
<p:commandButton action="#{vipView.create()}" value="#{i18n['vip.create']}" />
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html>
\ No newline at end of file
<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<!-- p:panel here because of http://forum.primefaces.org/viewtopic.php?f=3&t=37866 -->
<p:panel>
<h:panelGrid columns="2">
<h:outputLabel value="#{i18n['vip.host']}" for="host" />
<h:outputText id="host" value="#{vipDeliverView.vip.host.wholeName}" />
<h:outputLabel for="description" value="#{i18n['vip.description']}" />
<h:outputText id="description" value="#{vipDeliverView.vip.description}" />
</h:panelGrid>
<h:form>
<p:dataTable value="#{vipDeliverView.products}" var="wra">
<p:column headerText="#{i18n['vipProduct.name']}">
<h:outputText value="#{wra.product.productName}" />
</p:column>
<p:column headerText="#{i18n['vipProduct.quantity']}">
<h:outputText value="#{wra.product.quantity}">
<f:convertNumber minFractionDigits="0" maxFractionDigits="3" />
</h:outputText>
</p:column>
<p:column headerText="#{i18n['vipProduct.delivered']}">
<h:outputText value="#{wra.product.delivered}">
<f:convertNumber minFractionDigits="0" maxFractionDigits="3" />
</h:outputText>
</p:column>
<p:column headerText="#{i18n['vipProduct.deliver']}">
<h:inputText size="7" value="#{wra.deliver}">
<f:convertNumber minFractionDigits="0" maxFractionDigits="2" />
</h:inputText>
</p:column>
</p:dataTable>
<h:outputText value="#{i18n['vipProduct.deliverNotes']}" />
<p:inputTextarea cols="40" rows="3" value="#{vipDeliverView.notes}" />
<br />
<p:commandButton action="#{vipDeliverView.deliverProducts}" value="#{i18n['vipProduct.deliver']}" />
</h:form>
</p:panel>
</h:body>
</html>
\ No newline at end of file
<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui">
<h:body>
<ui:composition template="#{sessionHandler.template}">
<f:metadata>
<f:event type="preRenderView" listener="#{vipView.initEdit}" />
<f:viewParam name="id" value="#{vipView.id}" />
</f:metadata>
<ui:define name="content">
<h:form id="vipcreate">
<h:panelGrid columns="2">
<h:outputLabel value="#{i18n['vip.host']}" for="hostselect" />
<p:autoComplete id="hostselect" value="#{vipView.vip.host}" completeMethod="#{vipView.usersearch}" converter="#{eventUserConverter}" var="usr" itemValue="#{usr}" itemLabel="#{usr.wholeName}" />
<h:outputLabel for="shortdescr" value="#{i18n['vip.shortdescr']}" />
<p:inputTextarea id="shortdescr" cols="50" rows="3" value="#{vipView.vip.shortdescr}" />
<h:outputLabel for="description" value="#{i18n['vip.description']}" />
<p:inputTextarea id="description" cols="50" rows="6" value="#{vipView.vip.description}" />
</h:panelGrid>
<br />
<p:commandButton action="#{vipView.save()}" value="#{i18n['vip.save']}" />
<br />
</h:form>
<br />
<h:form>
<p:dataTable editable="true" styleClass="bordertable" id="vipProdList" var="prod" value="#{vipView.vipProducts}">
<p:ajax event="rowEdit" listener="#{vipView.productRowEdit}" />
<p:ajax event="rowEditCancel" listener="#{vipView.productRowEditCancel}" />
<p:column headerText="#{i18n['vipProduct.name']}">
<ui:fragment rendered="#{empty prod.id}">
<p:inputText value="#{prod.name}" />
<br />
<p:selectOneMenu value="#{prod.product}" converter="#{productConverter}">
<f:selectItem itemLabel="---" itemValue="0" />
<f:selectItems value="#{vipView.eventProducts}" var="p" itemLabel="#{p.name}" />
</p:selectOneMenu>
</ui:fragment>
<p:cellEditor rendered="#{not empty prod.id}">
<f:facet name="output">
<h:outputText value="#{prod.productName}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{prod.name}" />
<br />
<p:selectOneMenu value="#{prod.product}" converter="#{productConverter}">
<f:selectItem itemLabel="---" itemValue="0" />
<f:selectItems value="#{vipView.eventProducts}" var="p" itemLabel="#{p.name}" />
</p:selectOneMenu>
</f:facet>
</p:cellEditor>
</p:column>
<p:column style="width: 120px;" headerText="#{i18n['vipProduct.quantity']}">
<h:inputText size="15" rendered="#{empty prod.id}" value="#{prod.quantity}">
<f:convertNumber minFractionDigits="0" maxFractionDigits="3" />
</h:inputText>
<p:cellEditor rendered="#{not empty prod.id}">
<f:facet name="output">
<h:outputText value="#{prod.quantity}">
<f:convertNumber minFractionDigits="0" maxFractionDigits="3" />
</h:outputText>
</f:facet>
<f:facet name="input">
<h:inputText size="15" value="#{prod.quantity}">
<f:convertNumber minFractionDigits="0" maxFractionDigits="3" />
</h:inputText>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="#{i18n['vipProduct.delivered']}">
<h:outputText rendered="#{not empty prod.id}" value="#{prod.delivered}">
<f:convertNumber minFractionDigits="0" maxFractionDigits="3" />
</h:outputText>
</p:column>
<p:column style="width: 90px;">
<p:rowEditor rendered="#{not empty prod.id}" />
<p:commandButton action="#{vipView.createProduct()}" update="vipProdList" value="#{i18n['vipProduct.create']}" rendered="#{empty prod.id}" />
</p:column>
<p:column style="width: 35px;">
<p:commandButton rendered="#{not empty prod.id}" onclick="return confirm('#{i18n['vipProduct.deleteProductConfirm']}')" action="#{vipView.deleteProduct()}" update="vipProdList" icon="ui-icon-close" />
</p:column>
</p:dataTable>
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html>
\ No newline at end of file
<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui">
<h:body>
<ui:composition template="#{sessionHandler.template}">
<f:metadata>
<f:event type="preRenderView" listener="#{vipListView.initView}" />
</f:metadata>
<ui:define name="content">
<h:link rendered="#{vipListView.canCreate()}" outcome="/vip/create" value="#{i18n['vip.createNew']}" />
<br />
<h:form id="vipform">
<p:dataTable id="vip" value="#{vipListView.viplist}" widgetVar="viplist" styleClass="moya_datatable4" var="vip" filteredValue="#{vipListView.filteredVips}">
<f:facet name="header">
<p:outputPanel>
<h:outputText value="Search all fields:" />
<p:inputText id="globalFilter" onkeyup="PF('viplist').filter()" style="width:150px" placeholder="Enter keyword" />
</p:outputPanel>
</f:facet>
<p:column headerText="#{i18n['vip.hostsName']}" filterBy="#{vip.host.wholeName}" filterMatchMode="contains">
<h:outputText value="#{vip.host.wholeName}" />
</p:column>
<p:column headerText="#{i18n['vip.description']}" filterBy="#{vip.description}" filterMatchMode="contains">
<h:outputText id="vipdescr" value="#{vip.shortDisplayDescr}" title="#{vip.description}" />
<p:tooltip id="toolTipVipdescr" for="vipdescr" value="#{vip.description}" />
</p:column>
<p:column filterBy="#{vip.searchableProductnames}" filterMatchMode="contains" headerText="#{i18n['vip.products']} | #{i18n['vip.productQuantity']} | #{i18n['vip.productDelivered']}">
<h:dataTable border="0" var="prod" value="#{vip.products}">
<p:column>
<h:outputText title="#{prod.notes}" value="#{prod.productName}" />
</p:column>
<p:column>
<h:outputText value="#{prod.quantity}">
<f:convertNumber maxFractionDigits="3" minFractionDigits="0" />
</h:outputText>
</p:column>
<p:column>
<h:outputText value="#{prod.delivered}">
<f:convertNumber maxFractionDigits="3" minFractionDigits="0" />
</h:outputText>
</p:column>
</h:dataTable>
</p:column>
<p:column>
<p:commandButton id="delivebtn" rendered="#{not empty vip.id}" value="#{i18n['vip.deliver']}" actionListener="#{vipListView.deliverDialog}">
<p:ajax event="dialogReturn" listener="#{vipListView.updateViplist()}" update="vip" />
</p:commandButton>
</p:column>
<p:column>
<h:link outcome="/vip/edit" value="#{i18n['vip.edit']}">
<f:param name="id" value="#{vip.id}" />
</h:link>
</p:column>
</p:dataTable>
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html>
\ No newline at end of file
......@@ -40,7 +40,7 @@ public abstract class GenericCDIView implements Serializable {
private static final long serialVersionUID = -4000065015178815761L;
@Inject
private Conversation conversation;
protected Conversation conversation;
private static final Logger logger = LoggerFactory.getLogger(GenericCDIView.class);
......@@ -70,6 +70,16 @@ public abstract class GenericCDIView implements Serializable {
return permbean.hasPermission(perm);
}
/**
* Check that we have the permission in the first argument and also require
* that all of the booleans in varargs are true. If we don't have the perm
* or one of the booleans is false, we redirect to permission denied page and
* return false.
*
* @param perm IAppPermission to be checked
* @param externalChecks
* @return true if we had the permission and all of the externalChecks were true.
*/
protected boolean requirePermissions(IAppPermission perm, boolean... externalChecks) {
boolean ret = requirePermissions(hasPermission(perm));
......@@ -84,6 +94,13 @@ public abstract class GenericCDIView implements Serializable {
return ret;
}
/**
* Check that all of the given booleans are true. If any of them is false,
* redirect to permission denied page and return false.
* @param externalChecks bunch of booleans
* @return were all externalChecks true? false also means that we're redirecting
* to parmission denied page.
*/
protected boolean requirePermissions(boolean... externalChecks) {
boolean ret = true;
......
package fi.codecrew.moya.web.cdiview.vip;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJB;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Named;
import org.primefaces.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fi.codecrew.moya.beans.VipBeanLocal;
import fi.codecrew.moya.model.Vip;
import fi.codecrew.moya.model.VipProduct;
import fi.codecrew.moya.web.cdiview.GenericCDIView;
/**
* Created by jkj on 2015-01-11.
*/
@Named
@ConversationScoped
public class VipDeliverView extends GenericCDIView {
/**
*
*/
private static final long serialVersionUID = 1L;
private List<VipProductWrapper> products;
@EJB
private VipBeanLocal vipbean;
public List<VipProductWrapper> getProducts() {
if (products == null && vip != null) {
products = VipProductWrapper.wrap(vip.getProducts());
}
return products;
}
private Vip vip;
private static final Logger logger = LoggerFactory.getLogger(VipDeliverView.class);
private String notes;
public Vip getVip() {
return vip;
}
public void deliverProducts() {
for (VipProductWrapper p : products) {
logger.info("Product {}, count: {}", p.getProduct().getProductName(), p.getDeliver());
if (p.getDeliver().compareTo(BigDecimal.ZERO) > 0) {
vipbean.createDelivery(p.getProduct(), p.getDeliver(), notes);
}
}
notes = null;
vip = null;
products = null;
RequestContext.getCurrentInstance().closeDialog(null);
}
public void setVip(Vip vip) {
this.vip = vip;
products = null;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public static class VipProductWrapper
{
private final VipProduct product;
private BigDecimal deliver;
public VipProductWrapper(VipProduct prod) {
this.product = prod;
setDeliver(product.getQuantity().subtract(product.getDelivered()));
}
public static List<VipProductWrapper> wrap(List<VipProduct> products) {
List<VipProductWrapper> ret = new ArrayList<>();
for (VipProduct p : products) {
ret.add(new VipProductWrapper(p));
}
return ret;
}
public VipProduct getProduct() {
return product;
}
public BigDecimal getDeliver() {
return deliver;
}
public void setDeliver(BigDecimal deliver) {
this.deliver = deliver;
}
}
}
package fi.codecrew.moya.web.cdiview.vip;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.EJB;
import javax.enterprise.context.ConversationScoped;
import javax.faces.model.ListDataModel;
import javax.inject.Inject;
import javax.inject.Named;
import org.primefaces.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fi.codecrew.moya.beans.VipBeanLocal;
import fi.codecrew.moya.enums.apps.VipPermission;
import fi.codecrew.moya.model.Vip;
import fi.codecrew.moya.web.cdiview.PaginationView;
/**
* Created by jkj on 2015-01-11.
*/
@Named
@ConversationScoped
public class VipListView extends PaginationView<Vip> {
private static final long serialVersionUID = 4508923404658416898L;
@EJB
private VipBeanLocal vipBean;
private ListDataModel<Vip> viplist;
private List<Vip> filteredVips;
@Inject
private VipDeliverView deliverView;
private static final Logger logger = LoggerFactory.getLogger(VipListView.class);
public void initView() {
if (super.requirePermissions(VipPermission.VIEW) && viplist == null) {
viplist = new ListDataModel<Vip>(vipBean.getAvailableVips());
filteredVips = null;
super.beginConversation();
}
}
public boolean canCreate() {
return super.hasPermission(VipPermission.EDIT);
}
public void updateViplist() {
viplist = null;
initView();
}
public void deliverDialog() {
getDeliverView().setVip(viplist.getRowData());
logger.info("Set vip in deliverView to {}", deliverView.getVip());
Map<String, Object> options = new HashMap<>();
options.put("modal", true);
Map<String, List<String>> params = null;
if (conversation.getId() != null) {
params = new HashMap<>();
params.put("cid", Arrays.asList(conversation.getId()));
}
RequestContext.getCurrentInstance().openDialog("/vip/deliver", options, params);
}
public ListDataModel<Vip> getViplist() {
return viplist;
}
public void setViplist(ListDataModel<Vip> viplist) {
this.viplist = viplist;
}
public List<Vip> getFilteredVips() {
return filteredVips;
}
public void setFilteredVips(List<Vip> filteredVips) {
this.filteredVips = filteredVips;
}
public VipDeliverView getDeliverView() {
return deliverView;
}
public void setDeliverView(VipDeliverView deliverView) {
this.deliverView = deliverView;
}
}
package fi.codecrew.moya.web.cdiview.vip;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJB;
import javax.enterprise.context.ConversationScoped;
import javax.faces.model.ListDataModel;
import javax.inject.Inject;
import javax.inject.Named;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fi.codecrew.moya.beans.PermissionBeanLocal;
import fi.codecrew.moya.beans.ProductBeanLocal;
import fi.codecrew.moya.beans.UserBeanLocal;
import fi.codecrew.moya.beans.VipBeanLocal;
import fi.codecrew.moya.enums.apps.VipPermission;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.Product;
import fi.codecrew.moya.model.Vip;
import fi.codecrew.moya.model.VipProduct;
import fi.codecrew.moya.util.UserSearchQuery;
import fi.codecrew.moya.utilities.SearchResult;
import fi.codecrew.moya.web.cdiview.GenericCDIView;
/**
* Created by jkj on 2015-01-11.
*/
@Named
@ConversationScoped
public class VipView extends GenericCDIView {
/**
*
*/
private static final long serialVersionUID = 1L;
@EJB
private VipBeanLocal vipBean;
private Vip vip;
private Integer id;
@EJB
private UserBeanLocal userbean;
@EJB
private PermissionBeanLocal permbean;
@EJB
private ProductBeanLocal productBean;
private static final Logger logger = LoggerFactory.getLogger(VipView.class);
public void initEdit() {
if (super.requirePermissions(VipPermission.VIEW) && vip == null) {
vip = vipBean.find(id);
super.beginConversation();
}
}
public void createProduct() {
VipProduct l = vipProducts.getRowData();
vip = vipBean.createProduct(l);
vipProducts = null;
}
public void deleteProduct() {
VipProduct l = vipProducts.getRowData();
logger.info("Deleting product {}", l);
vip = vipBean.deleteProduct(l);
vipProducts = null;
}
public List<Product> getEventProducts() {
return productBean.getProducts();
}
private ListDataModel<VipProduct> vipProducts;
public ListDataModel<VipProduct> getVipProducts() {
if (vipProducts == null && vip != null) {
ArrayList<VipProduct> li = new ArrayList<>();
li.add(new VipProduct(vip));
li.addAll(vip.getProducts());
vipProducts = new ListDataModel<>(li);
}
return vipProducts;
}
public void initCreate() {
if (super.requirePermissions(VipPermission.VIEW) && vip == null) {
vip = new Vip();
vip.setHost(permbean.getCurrentUser());
super.beginConversation();
}
}
public void productRowEdit() {
vip = vipBean.saveProduct(getVipProducts().getRowData());
// logger.warn("Editing product: {}", getVipProducts().getRowData());
}
public void productRowEditCancel() {
logger.warn("Editing product cancelled: {}", getVipProducts().getRowData());
}
public void save() {
vip = vipBean.save(vip);
vipProducts = null;
}
public List<EventUser> usersearch(String search) {
UserSearchQuery usq = new UserSearchQuery();
usq.setSearch(search);
SearchResult<EventUser> ret = userbean.getThisEventsUsers(usq);
return ret.getResults();
}
public String create()
{
vipBean.create(vip);
return "/vip/edit";
}
public Vip getVip() {
return vip;
}
public void setVip(Vip vip) {
this.vip = vip;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
......@@ -27,6 +27,8 @@ adduser.update = Update profile picture
adduser.welcome = Welcome
adduser.welcometext = Here you can add new user or update your current user profile image. Please select desired action below.
barcodeReader.readBarcode = Lue viivakoodi
bill.billAmount = Tilauksen summa (sis. alv)
bill.billNumber = Tilausnumero
bill.cancel = Cancel bill
......@@ -141,6 +143,7 @@ error.contact = If this happens again, contact Info with the following code:
error.error = You have encountered an error.
etickets.eticketcode = Lippu
etickets.mailSended = Lippu l\u00E4hetetty s\u00E4hk\u00F6postiisi
etickets.place = Paikka
etickets.placeinfo = Paikkatiedot
etickets.placemap = Paikat kartalla
......@@ -215,24 +218,33 @@ global.save = Save
httpsession.creationTime = Created
incomingFlow.count = M\u00E4\u00E4r\u00E4
incomingFlow.leftCount = Noutamatta
incomingView.attach = Liit\u00E4
incomingView.attachDialogTitle = Liit\u00E4 koodi k\u00E4ytt\u00E4j\u00E4\u00E4n
incomingView.cancel = Peruuta
incomingflow.allGiven = Merkitty {0} lippu(a) annetuksi.
incomingflow.alreadyShowingUser.message = Piipattu k\u00E4ytt\u00E4j\u00E4 on jo n\u00E4kyviss\u00E4
incomingflow.alreadyShowingUser.title = Valmiiksi valittu
incomingflow.cardCodes = Kortin koodit
incomingflow.cardfiling.label = Card filing:
incomingflow.codeattached.message = Piipattu koodi liitetty n\u00E4ytett\u00E4v\u00E4\u00E4n korttiin
incomingflow.codeattached.title = Koodi liittetty
incomingflow.giveplace = Merkitse annetuksi
incomingflow.groupmemberships = Paikkakoodit
incomingflow.invalidbarcode.message = Viivakoodilla ei l\u00F6ytynyt mit\u00E4\u00E4n
incomingflow.invalidbarcode.title = virheellinen koodi
incomingflow.printedCard = Kortti
incomingflow.usereditor = K\u00E4ytt\u00E4j\u00E4
incomingflow.usereditor.info = Tiedot
incomingflow.usereditor.picture = Kuvanotto
incomingflow.alreadyShowingUser.title = Valmiiksi valittu
incomingflow.cardCodes = Kortin koodit
incomingflow.cardfiling.label = Card filing:
incomingflow.changereader = Vaihda / valitse lukija
incomingflow.codeattached.message = Piipattu koodi liitetty n\u00E4ytett\u00E4v\u00E4\u00E4n korttiin
incomingflow.codeattached.title = Koodi liittetty
incomingflow.giveplace = Merkitse annetuksi
incomingflow.groupmemberships = Paikkakoodit
incomingflow.invalidbarcode.message = Viivakoodilla ei l\u00F6ytynyt mit\u00E4\u00E4n
incomingflow.invalidbarcode.title = virheellinen koodi
incomingflow.markEverythingGiven = Anna kaikki antamattomat tuotteet
incomingflow.placesummary = Paikkayhteenveto
incomingflow.printedCard = Kortti
incomingflow.usereditor = K\u00E4ytt\u00E4j\u00E4
incomingflow.usereditor.info = Tiedot
incomingflow.usereditor.picture = Kuvanotto
infoview.multisearch = K\u00E4ytt\u00E4j\u00E4haku
invite.permissionDenied = Sinulla ei ole oikeutta luovuttaa paikkaa eteenp\u00E4in.
invite.userLoginSuccessfull = Kutsu vastaanotettu onnistuneesti
......@@ -381,6 +393,7 @@ productshop.plusOne = +1
productshop.plusTen = +10
reader.autopoll = Jatkuva lukijan seuraaminen
reader.noReader = Ei valittua lukijaa
refresh = P\u00E4ivit\u00E4
......@@ -410,7 +423,9 @@ shop.unitdiscount = Alennus
submenu.NotImplementedYet = Not implemented
submenu.admin.adduser = K\u00E4ytt\u00E4j\u00E4nlis\u00E4ys
submenu.admin.adduser.index = K\u00E4ytt\u00E4j\u00E4nlis\u00E4ys
submenu.admin.incoming.index = Sis\u00E4\u00E4ntulo
submenu.frontpage = Frontpage
submenu.info.cardlessIncoming = Sis\u00E4\u00E4ntulo
submenu.info.foodwave.foodwaveshop = Ruokakauppa
submenu.info.incoming = Laaja sis\u00E4\u00E4ntulon\u00E4kym\u00E4
submenu.info.index = Infon\u00E4kym\u00E4
......@@ -426,6 +441,7 @@ submenu.shop.createBill = Osta lippuja
subnavi.cards = \u0009\u0009
subnavi.info = Info
subnavi.vips = Vippilista
success = Onnistui
......@@ -447,6 +463,7 @@ user.imageUpload.imageNotFound = Select image to upload
user.info = K\u00E4ytt\u00E4j\u00E4
user.invite.placeInvite.header = Liit\u00E4 paikka itsellesi
user.meta.box.title = Metadata
user.roles = Pakotetut roolit
user.saveUserSelectableRoles = Tallenna
user.shirt.L = Unisex L
user.shirt.LadyL = Ladyfit L
......@@ -470,21 +487,24 @@ usercart.showoverview = Vie tarkastusn\u00E4kym\u00E4\u00E4n
viewlectures.title = Kurssit ja luennot
vip.create = Luo
vip.createNew = Luo uusi
vip.deliver = Toimita
vip.description = Kuvaus
vip.edit = Muokkaa
vip.host = Is\u00E4nt\u00E4
vip.hostsName = Is\u00E4nt\u00E4
vip.productDelivered = Toimitettu
vip.productQuantity = Lkm
vip.products = Tuote
vip.save = Tallenna
vip.shortdescr = Lyhyt kuvaus
vipProduct.create = Lis\u00E4\u00E4
vipProduct.deliver = Toimita
vipProduct.deliverNotes = Huomiot
vipProduct.delivered = Toimitettu
vipProduct.name = Tuote
vipProduct.quantity = Lukum\u00E4\u00E4r\u00E4
yes = Kyll\u00E4
infoview.multisearch=K\u00E4ytt\u00E4j\u00E4haku
incomingflow.placesummary=Paikkayhteenveto
incomingFlow.leftCount=Noutamatta
incomingflow.markEverythingGiven=Anna kaikki antamattomat tuotteet
submenu.admin.incoming.index=Sis\u00E4\u00E4ntulo
submenu.admin.incoming.printCard=
submenu.info.cardlessIncoming=Sis\u00E4\u00E4ntulo
incomingflow.changereader=Vaihda / valitse lukija
incomingFlow.count=M\u00E4\u00E4r\u00E4
user.birthday=
user.confirmUserToEventAdding=
user.invalidLoginCredentials=
barcodeReader.readBarcode=Lue viivakoodi
incomingflow.allGiven=Merkitty {0} lippu(a) annetuksi.
reader.noReader=Ei valittua lukijaa
etickets.mailSended=Lippu l\u00E4hetetty s\u00E4hk\u00F6postiisi
user.roles=Pakotetut roolit
......@@ -353,6 +353,7 @@ error.contact = If this happens again, contact Info with the following code:
error.error = You have encountered an error.
etickets.eticketcode = Ticket
etickets.mailSended = Ticket has been sended to your email
etickets.place = Place
etickets.placeinfo = Placeinfo
etickets.placemap = Places on map
......@@ -535,33 +536,40 @@ imagefile.file = Imagefile
importuser.file = File
importuser.template = Template
incomingFlow.count = Count
incomingFlow.leftCount = Ungiven
incomingView.attach = Attach
incomingView.attachDialogTitle = Attach code to user
incomingView.cancel = Cancel
incomingflow.allGiven = Marked {0} tickets given.
incomingflow.alreadyShowingUser.message = We are already showing selected user
incomingflow.alreadyShowingUser.title = Already selected
incomingflow.barcode = Barcode
incomingflow.cardCodes = Barcodes in card
incomingflow.cardfiling.label = Card filing:
incomingflow.changereader = Select or Change Reader
incomingflow.codeattached.message = Code attached to current user's card
incomingflow.codeattached.title = Code attached
incomingflow.giveplace = Mark given
incomingflow.groupmemberships = Group memberships
incomingflow.invalidbarcode.message = Nothing found with barcode, you can now add it to the user
incomingflow.invalidbarcode.title = Invalid code
incomingflow.multisearch = Multisearch
incomingflow.printedCard = Card
incomingflow.search = Search
incomingflow.ungiveplace = Mark not given
incomingflow.userdetails = User details
incomingflow.usereditor = User
incomingflow.usereditor.info = User
incomingflow.usereditor.picture = Picturetake
incomingflow.alreadyShowingUser.title = Already selected
incomingflow.barcode = Barcode
incomingflow.cardCodes = Barcodes in card
incomingflow.cardfiling.label = Card filing:
incomingflow.changereader = Select or Change Reader
incomingflow.codeattached.message = Code attached to current user's card
incomingflow.codeattached.title = Code attached
incomingflow.giveplace = Mark given
incomingflow.groupmemberships = Group memberships
incomingflow.invalidbarcode.message = Nothing found with barcode, you can now add it to the user
incomingflow.invalidbarcode.title = Invalid code
incomingflow.markEverythingGiven = Give ewerything ungiven stuff
incomingflow.multisearch = Multisearch
incomingflow.placesummary = Placesummary
incomingflow.printedCard = Card
incomingflow.search = Search
incomingflow.ungiveplace = Mark not given
incomingflow.userdetails = User details
incomingflow.usereditor = User
incomingflow.usereditor.info = User
incomingflow.usereditor.picture = Picturetake
infoview.back = Back
infoview.computerplace = Computer places
infoview.multisearch = Usersearch
infoview.shop = Shop
inventory.product.info = Info
......@@ -1074,6 +1082,7 @@ reader.description = Description
reader.edit = Edit
reader.identification = Identification
reader.name = Reader name
reader.noReader = No selected reader
reader.save = Save
reader.select = Select reader
reader.tag = Tag
......@@ -1254,6 +1263,7 @@ submenu.foodwave.list = Foodwaves
submenu.foodwave.listTemplates = Food provides
submenu.help = Ticket help
submenu.index = Frontpage
submenu.info.cardlessIncoming = Incoming
submenu.info.foodwave.foodwaveshop = Foodshop
submenu.info.incoming = Extendet Incomingview
submenu.info.index = Infoview
......@@ -1328,6 +1338,7 @@ subnavi.info = Info
subnavi.products = Products
subnavi.readers = Readers
subnavi.roles = Roles
subnavi.vips = VIP-list
success = Success
......@@ -1598,6 +1609,7 @@ user.successfullySaved = Changes saved successfully
user.superadmin = Superadmin
user.thisIsCurrentImage = Current image
user.town = City
user.unauthenticated = Unauthenticated
user.uploadimage = Send image
user.userSelectableRoles = Select one
user.username = Username
......@@ -1650,6 +1662,26 @@ viewexpired.title = Login expired. Please login again.
viewlectures.title = Courses and lectures
vip.create = Create
vip.createNew = Create new
vip.deliver = Deliver
vip.description = Description
vip.edit = Edit
vip.host = Host
vip.hostsName = Host
vip.productDelivered = Delivered
vip.productQuantity = Qty
vip.products = Product
vip.save = Save
vip.shortdescr = Short description
vipProduct.create = Create
vipProduct.deliver = Deliver
vipProduct.deliverNotes = Notes
vipProduct.delivered = Delivered
vipProduct.name = Product
vipProduct.quantity = Quantity
voting.allcompos.curEntries = # of entries
voting.allcompos.descri = Description
voting.allcompos.description = List of all compos and theirs information.
......@@ -1693,12 +1725,3 @@ voting.create.voteEnd = Voting close
voting.create.voteStart = Voting start
yes = Yes
infoview.multisearch=Usersearch
incomingflow.placesummary=Placesummary
incomingFlow.leftCount=Ungiven
incomingflow.markEverythingGiven=Give ewerything ungiven stuff
submenu.info.cardlessIncoming=Incoming
incomingFlow.count=Count
incomingflow.allGiven=Marked {0} tickets given.
reader.noReader=No selected reader
etickets.mailSended=Ticket has been sended to your email
......@@ -4,6 +4,7 @@
acc_line.eventuser = Asiakas
acc_line.nick = Nimimerkki
acc_line.place = Paikka
acc_line.product = Tuote
acc_line.quantity = M\u00E4\u00E4r\u00E4
acc_line.time = Ostoaika
......@@ -354,6 +355,7 @@ error.contact = Jos t\u00E4m\u00E4 toistuu, ota seuraava koodi talteen ja ota yh
error.error = Olet kohdannut virheen.
etickets.eticketcode = Lippu
etickets.mailSended = Lippu l\u00E4hetetty s\u00E4hk\u00F6postiisi
etickets.place = Paikka
etickets.placeinfo = Paikkatiedot
etickets.placemap = Paikat kartalla
......@@ -543,35 +545,42 @@ imagefile.file = Kuvatiedosto
importuser.file = Tiedosto
importuser.template = Malli
incomingFlow.count = M\u00E4\u00E4r\u00E4
incomingFlow.leftCount = Noutamatta
incomingView.attach = Liit\u00E4
incomingView.attachDialogTitle = Liit\u00E4 koodi k\u00E4ytt\u00E4j\u00E4\u00E4n
incomingView.cancel = Peruuta
incomingflow.allGiven = Merkitty {0} lippu(a) annetuksi.
incomingflow.alreadyShowingUser.message = Piipattu k\u00E4ytt\u00E4j\u00E4 on jo n\u00E4kyviss\u00E4
incomingflow.alreadyShowingUser.title = Valmiiksi valittu
incomingflow.barcode = Viivakoodi
incomingflow.cardCodes = Korttiin liitetyt koodit
incomingflow.cardfiling.label = Kortin kansiointi:
incomingflow.changereader = Vaihda / valitse lukija
incomingflow.codeattached.message = Piipattu koodi liitetty aktiiviseen k\u00E4ytt\u00E4j\u00E4\u00E4n
incomingflow.codeattached.title = Koodi liitetty
incomingflow.giveplace = Merkitse annetuksi
incomingflow.groupmemberships = Konepaikat sek\u00E4 liput
incomingflow.invalidbarcode.message = Piipatulla koodilla ei l\u00F6ytynyt mit\u00E4\u00E4n, voit lis\u00E4t\u00E4 koodin k\u00E4ytt\u00E4j\u00E4\u00E4n
incomingflow.invalidbarcode.title = Virheellinen koodi
incomingflow.multisearch = Monihaku
incomingflow.printedCard = Kortti
incomingflow.search = Etsi
incomingflow.ungiveplace = Ei olekkaan annettu
incomingflow.userdetails = K\u00E4ytt\u00E4j\u00E4n tiedot
incomingflow.usereditor = K\u00E4ytt\u00E4j\u00E4
incomingflow.usereditor.info = K\u00E4vij\u00E4
incomingflow.usereditor.picture = Kuvanotto
incomingflow.alreadyShowingUser.title = Valmiiksi valittu
incomingflow.barcode = Viivakoodi
incomingflow.cardCodes = Korttiin liitetyt koodit
incomingflow.cardfiling.label = Kortin kansiointi:
incomingflow.changereader = Vaihda / valitse lukija
incomingflow.codeattached.message = Piipattu koodi liitetty aktiiviseen k\u00E4ytt\u00E4j\u00E4\u00E4n
incomingflow.codeattached.title = Koodi liitetty
incomingflow.giveplace = Merkitse annetuksi
incomingflow.groupmemberships = Konepaikat sek\u00E4 liput
incomingflow.invalidbarcode.message = Piipatulla koodilla ei l\u00F6ytynyt mit\u00E4\u00E4n, voit lis\u00E4t\u00E4 koodin k\u00E4ytt\u00E4j\u00E4\u00E4n
incomingflow.invalidbarcode.title = Virheellinen koodi
incomingflow.markEverythingGiven = Anna kaikki antamattomat tuotteet
incomingflow.multisearch = Monihaku
incomingflow.placesummary = Paikkayhteenveto
incomingflow.printedCard = Kortti
incomingflow.search = Etsi
incomingflow.ungiveplace = Ei olekkaan annettu
incomingflow.userdetails = K\u00E4ytt\u00E4j\u00E4n tiedot
incomingflow.usereditor = K\u00E4ytt\u00E4j\u00E4
incomingflow.usereditor.info = K\u00E4vij\u00E4
incomingflow.usereditor.picture = Kuvanotto
index.title = Etusivu
infoview.back = Takaisin
infoview.computerplace = Tietokonepaikat
infoview.multisearch = K\u00E4ytt\u00E4j\u00E4haku
infoview.shop = Kauppa
inventory.product.info = Info
......@@ -1059,6 +1068,7 @@ reader.description = Kuvaus
reader.edit = Muokkaa
reader.identification = Tunniste
reader.name = Lukijan nimi
reader.noReader = Ei valittua lukijaa
reader.save = Tallenna
reader.select = Valitse lukija
reader.tag = Tag
......@@ -1234,6 +1244,7 @@ submenu.foodwave.list = Ruokatilaukset
submenu.frontpage = Etusivu
submenu.help = Lippuopas
submenu.index = Etusivu
submenu.info.cardlessIncoming = Sis\u00E4\u00E4ntulo
submenu.info.foodwave.foodwaveshop = Ruokakauppa
submenu.info.incoming = Laaja Sis\u00E4\u00E4ntulon\u00E4kym\u00E4
submenu.info.index = Infon\u00E4kym\u00E4
......@@ -1311,6 +1322,7 @@ subnavi.info = Info
subnavi.products = Tuotteet
subnavi.readers = Lukijat
subnavi.roles = Roolit
subnavi.vips = Vippilista
success = Onnistui
......@@ -1581,6 +1593,7 @@ user.successfullySaved = Tiedot tallennettu onnistuneesti
user.superadmin = Superadmin
user.thisIsCurrentImage = Nykyinen kuva
user.town = Kaupunki
user.unauthenticated = Kirjautumaton
user.uploadimage = L\u00E4het\u00E4 kuva
user.userSelectableRoles = Valitse yksi
user.username = K\u00E4ytt\u00E4j\u00E4tunnus
......@@ -1632,6 +1645,26 @@ viewexpired.title = N\u00E4kym\u00E4 on vanhentunut
viewlectures.title = Kurssit ja luennot
vip.create = Luo
vip.createNew = Luo uusi
vip.deliver = Toimita
vip.description = Kuvaus
vip.edit = Muokkaa
vip.host = Is\u00E4nt\u00E4
vip.hostsName = Is\u00E4nt\u00E4
vip.productDelivered = Toimitettu
vip.productQuantity = Lkm
vip.products = Tuote
vip.save = Tallenna
vip.shortdescr = Lyhyt kuvaus
vipProduct.create = Lis\u00E4\u00E4
vipProduct.deliver = Toimita
vipProduct.deliverNotes = Huomiot
vipProduct.delivered = Toimitettu
vipProduct.name = Tuote
vipProduct.quantity = Lukum\u00E4\u00E4r\u00E4
voting.allcompos.curEntries = Entryja
voting.allcompos.descri = Kuvaus
voting.allcompos.description = Compojen informaatiot.
......@@ -1675,14 +1708,3 @@ voting.create.voteEnd = \u00C4\u00E4nestys kiinni
voting.create.voteStart = \u00C4\u00E4nestys auki
yes = Kyll\u00E4
acc_line.place=Paikka
infoview.multisearch=K\u00E4ytt\u00E4j\u00E4haku
incomingflow.placesummary=Paikkayhteenveto
incomingFlow.leftCount=Noutamatta
user.unauthenticated=
incomingflow.markEverythingGiven=Anna kaikki antamattomat tuotteet
submenu.info.cardlessIncoming=Sis\u00E4\u00E4ntulo
incomingFlow.count=M\u00E4\u00E4r\u00E4
incomingflow.allGiven=Merkitty {0} lippu(a) annetuksi.
reader.noReader=Ei valittua lukijaa
etickets.mailSended=Lippu l\u00E4hetetty s\u00E4hk\u00F6postiisi
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!