Commit 61f29bdd by Tuukka Kivilahti

now it should work, tested on tkwtf computer

1 parent c4d1cc2c
Showing with 556 additions and 74 deletions
...@@ -62,7 +62,7 @@ public interface BillBeanLocal { ...@@ -62,7 +62,7 @@ public interface BillBeanLocal {
Bill expireBill(Bill bill); Bill expireBill(Bill bill);
Bill addProductToBill(Bill bill, Product product, BigDecimal count, FoodWave foodwave); Bill addProductToBill(Bill bill, Product product, BigDecimal count, FoodWave foodwave, String additionalDescription);
Bill addProductToBill(Bill bill, Product product, BigDecimal count); Bill addProductToBill(Bill bill, Product product, BigDecimal count);
......
...@@ -27,13 +27,7 @@ import java.util.Map; ...@@ -27,13 +27,7 @@ import java.util.Map;
import javax.ejb.Local; import javax.ejb.Local;
import fi.codecrew.moya.model.AccountEvent; import fi.codecrew.moya.model.*;
import fi.codecrew.moya.model.Discount;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.InventoryEvent;
import fi.codecrew.moya.model.Product;
import fi.codecrew.moya.model.ProductFlag;
import fi.codecrew.moya.model.Role;
@Local @Local
public interface ProductBeanLocal { public interface ProductBeanLocal {
...@@ -93,4 +87,7 @@ public interface ProductBeanLocal { ...@@ -93,4 +87,7 @@ public interface ProductBeanLocal {
AccountEvent markDelivered(AccountEvent e, Calendar c); AccountEvent markDelivered(AccountEvent e, Calendar c);
List<Product> getPlaceProducts(); List<Product> getPlaceProducts();
ProductOption findOptionById(Integer id);
} }
...@@ -101,7 +101,7 @@ Each class, interface, nested class and nested interface has its own separate pa ...@@ -101,7 +101,7 @@ Each class, interface, nested class and nested interface has its own separate pa
<LI>Nested Class Summary<LI>Field Summary<LI>Constructor Summary<LI>Method Summary <LI>Nested Class Summary<LI>Field Summary<LI>Constructor Summary<LI>Method Summary
<P> <P>
<LI>Field Detail<LI>Constructor Detail<LI>Method Detail</UL> <LI>Field Detail<LI>Constructor Detail<LI>Method Detail</UL>
Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.</BLOCKQUOTE> Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the priority they appear in the source code. This preserves the logical groupings established by the programmer.</BLOCKQUOTE>
</BLOCKQUOTE> </BLOCKQUOTE>
<H3> <H3>
Annotation Type</H3> Annotation Type</H3>
......
...@@ -351,11 +351,11 @@ public class BillBean implements BillBeanLocal { ...@@ -351,11 +351,11 @@ public class BillBean implements BillBeanLocal {
@Override @Override
public Bill addProductToBill(Bill bill, Product product, BigDecimal count) { public Bill addProductToBill(Bill bill, Product product, BigDecimal count) {
return this.addProductToBill(bill, product, count, null); return this.addProductToBill(bill, product, count, null, null);
} }
@Override @Override
public Bill addProductToBill(Bill bill, Product product, BigDecimal count, FoodWave foodwave) { public Bill addProductToBill(Bill bill, Product product, BigDecimal count, FoodWave foodwave, String additionalDescription) {
// If bill number > 0 bill has been sent and extra privileges are needed // If bill number > 0 bill has been sent and extra privileges are needed
// to modify. // to modify.
...@@ -368,7 +368,7 @@ public class BillBean implements BillBeanLocal { ...@@ -368,7 +368,7 @@ public class BillBean implements BillBeanLocal {
bill.setBillLines(new ArrayList<BillLine>()); bill.setBillLines(new ArrayList<BillLine>());
} }
bill.getBillLines().add(new BillLine(bill, product, count, foodwave)); bill.getBillLines().add(new BillLine(bill, product, count, foodwave, additionalDescription));
for (Discount disc : discountBean.getActiveDiscountsByProduct(product, count, bill.getSentDate(), bill.getUser())) { for (Discount disc : discountBean.getActiveDiscountsByProduct(product, count, bill.getSentDate(), bill.getUser())) {
bill.getBillLines().add(new BillLine(bill, product, disc, count)); bill.getBillLines().add(new BillLine(bill, product, disc, count));
......
...@@ -407,6 +407,16 @@ public class BootstrapBean implements BootstrapBeanLocal { ...@@ -407,6 +407,16 @@ public class BootstrapBean implements BootstrapBeanLocal {
"ALTER TABLE tournament_roles ADD CONSTRAINT FK_tournament_roles_role_id FOREIGN KEY (role_id) REFERENCES roles (id)", "ALTER TABLE tournament_roles ADD CONSTRAINT FK_tournament_roles_role_id FOREIGN KEY (role_id) REFERENCES roles (id)",
}); });
dbUpdates.add(new String[] {
"CREATE TABLE product_option_groups (id SERIAL NOT NULL, meta json, name TEXT, required BOOLEAN NOT NULL, default_product_option_id INTEGER, product_id INTEGER NOT NULL, PRIMARY KEY (id))",
"CREATE TABLE product_options (id SERIAL NOT NULL, meta json, name TEXT, priority INTEGER, price_change INTEGER, product_option_group_id INTEGER NOT NULL, PRIMARY KEY (id))",
"ALTER TABLE product_option_groups ADD CONSTRAINT FK_product_option_groups_default_product_option_id FOREIGN KEY (default_product_option_id) REFERENCES product_options (id)",
"ALTER TABLE product_option_groups ADD CONSTRAINT FK_product_option_groups_product_id FOREIGN KEY (product_id) REFERENCES products (id)",
"ALTER TABLE product_options ADD CONSTRAINT FK_product_options_product_option_group_id FOREIGN KEY (product_option_group_id) REFERENCES product_option_groups (id)",
});
} }
public BootstrapBean() { public BootstrapBean() {
......
...@@ -38,6 +38,8 @@ import javax.ejb.EJBException; ...@@ -38,6 +38,8 @@ import javax.ejb.EJBException;
import javax.ejb.LocalBean; import javax.ejb.LocalBean;
import javax.ejb.Stateless; import javax.ejb.Stateless;
import fi.codecrew.moya.facade.*;
import fi.codecrew.moya.model.*;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -45,28 +47,6 @@ import fi.codecrew.moya.bortal.views.BillSummary; ...@@ -45,28 +47,6 @@ import fi.codecrew.moya.bortal.views.BillSummary;
import fi.codecrew.moya.enums.apps.ShopPermission; import fi.codecrew.moya.enums.apps.ShopPermission;
import fi.codecrew.moya.enums.apps.SpecialPermission; import fi.codecrew.moya.enums.apps.SpecialPermission;
import fi.codecrew.moya.enums.apps.UserPermission; import fi.codecrew.moya.enums.apps.UserPermission;
import fi.codecrew.moya.facade.AccountEventFacade;
import fi.codecrew.moya.facade.BillLineFacade;
import fi.codecrew.moya.facade.DiscountFacade;
import fi.codecrew.moya.facade.EventMapFacade;
import fi.codecrew.moya.facade.EventUserFacade;
import fi.codecrew.moya.facade.GroupMembershipFacade;
import fi.codecrew.moya.facade.InventoryEventFacade;
import fi.codecrew.moya.facade.PlaceFacade;
import fi.codecrew.moya.facade.PlaceSlotFacade;
import fi.codecrew.moya.facade.ProductFacade;
import fi.codecrew.moya.facade.UserFacade;
import fi.codecrew.moya.model.AccountEvent;
import fi.codecrew.moya.model.Discount;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.InventoryEvent;
import fi.codecrew.moya.model.LanEvent;
import fi.codecrew.moya.model.LanEventPropertyKey;
import fi.codecrew.moya.model.PlaceSlot;
import fi.codecrew.moya.model.Product;
import fi.codecrew.moya.model.ProductFlag;
import fi.codecrew.moya.model.ProductLimitation;
import fi.codecrew.moya.model.Role;
import fi.codecrew.moya.utilities.moyamessage.MoyaEventType; import fi.codecrew.moya.utilities.moyamessage.MoyaEventType;
/** /**
...@@ -114,6 +94,7 @@ public class ProductBean implements ProductBeanLocal { ...@@ -114,6 +94,7 @@ public class ProductBean implements ProductBeanLocal {
@EJB @EJB
private BillBeanLocal billbean; private BillBeanLocal billbean;
@EJB @EJB
private EventBeanLocal eventbean; private EventBeanLocal eventbean;
@EJB @EJB
...@@ -145,6 +126,12 @@ public class ProductBean implements ProductBeanLocal { ...@@ -145,6 +126,12 @@ public class ProductBean implements ProductBeanLocal {
@EJB @EJB
private PlaceSlotFacade slotfacade; private PlaceSlotFacade slotfacade;
@EJB
private ProductOptionGroupFacade productOptionGroupFacade;
@EJB
private ProductOptionFacade productOptionFacade;
private static final Logger logger = LoggerFactory.getLogger(ProductBean.class); private static final Logger logger = LoggerFactory.getLogger(ProductBean.class);
/** /**
...@@ -650,4 +637,10 @@ public class ProductBean implements ProductBeanLocal { ...@@ -650,4 +637,10 @@ public class ProductBean implements ProductBeanLocal {
} }
@Override
public ProductOption findOptionById(Integer id) {
return productOptionFacade.find(id);
}
} }
/*
* Copyright Codecrew Ry
*
* All rights reserved.
*
* This license applies to any software containing a notice placed by the
* copyright holder. Such software is herein referred to as the Software.
* This license covers modification, distribution and use of the Software.
*
* Any distribution and use in source and binary forms, with or without
* modification is not permitted without explicit written permission from the
* copyright owner.
*
* 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
* future versions of the Software.
*
*/
package fi.codecrew.moya.facade;
import fi.codecrew.moya.facade.IntegerPkGenericFacade;
import fi.codecrew.moya.model.ProductOption;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
@Stateless
@LocalBean
public class ProductOptionFacade extends IntegerPkGenericFacade<ProductOption> {
public ProductOptionFacade() {
super(ProductOption.class);
}
}
/*
* Copyright Codecrew Ry
*
* All rights reserved.
*
* This license applies to any software containing a notice placed by the
* copyright holder. Such software is herein referred to as the Software.
* This license covers modification, distribution and use of the Software.
*
* Any distribution and use in source and binary forms, with or without
* modification is not permitted without explicit written permission from the
* copyright owner.
*
* 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
* future versions of the Software.
*
*/
package fi.codecrew.moya.facade;
import fi.codecrew.moya.model.ProductOptionGroup;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
@Stateless
@LocalBean
public class ProductOptionGroupFacade extends IntegerPkGenericFacade<ProductOptionGroup> {
public ProductOptionGroupFacade() {
super(ProductOptionGroup.class);
}
}
...@@ -118,14 +118,18 @@ public class BillLine extends GenericEntity { ...@@ -118,14 +118,18 @@ public class BillLine extends GenericEntity {
} }
public BillLine(Bill bill2, Product product, BigDecimal count) { public BillLine(Bill bill2, Product product, BigDecimal count) {
this(bill2, product, count, null); this(bill2, product, count, null, null);
} }
public BillLine(Bill bill2, Product product, BigDecimal count, FoodWave foodwave) { public BillLine(Bill bill2, Product product, BigDecimal count, FoodWave foodwave, String additionalDescription) {
super(); super();
this.bill = bill2; this.bill = bill2;
this.lineProduct = product; this.lineProduct = product;
this.name = product.getName(); this.name = product.getName();
if(additionalDescription != null && !additionalDescription.trim().isEmpty())
this.name += ", "+ additionalDescription;
this.setUnitName(product.getUnitName()); this.setUnitName(product.getUnitName());
this.setQuantity(count); this.setQuantity(count);
this.setUnitPrice(product.getPrice().abs()); this.setUnitPrice(product.getPrice().abs());
......
...@@ -143,6 +143,10 @@ public class Product extends GenericEntity { ...@@ -143,6 +143,10 @@ public class Product extends GenericEntity {
}) })
private List<FoodWaveTemplate> foodWaveTemplates; private List<FoodWaveTemplate> foodWaveTemplates;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "product")
private List<ProductOptionGroup> productOptionGroups;
public Product() { public Product() {
super(); super();
} }
...@@ -173,6 +177,14 @@ public class Product extends GenericEntity { ...@@ -173,6 +177,14 @@ public class Product extends GenericEntity {
this.vat = src.vat; this.vat = src.vat;
} }
public List<ProductOptionGroup> getProductOptionGroups() {
return productOptionGroups;
}
public void setProductOptionGroups(List<ProductOptionGroup> productOptionGroups) {
this.productOptionGroups = productOptionGroups;
}
public BigDecimal getSoldCash() { public BigDecimal getSoldCash() {
BigDecimal tot = BigDecimal.ZERO; BigDecimal tot = BigDecimal.ZERO;
for (AccountEvent ac : this.getAccountEvents()) { for (AccountEvent ac : this.getAccountEvents()) {
...@@ -408,4 +420,8 @@ public class Product extends GenericEntity { ...@@ -408,4 +420,8 @@ public class Product extends GenericEntity {
this.shopRequiredRole = shopRequiredRole; this.shopRequiredRole = shopRequiredRole;
} }
public boolean isContainsProductOptionGroups() {
return productOptionGroups != null && productOptionGroups.size() > 0;
}
} }
...@@ -22,13 +22,10 @@ ...@@ -22,13 +22,10 @@
*/ */
package fi.codecrew.moya.model; package fi.codecrew.moya.model;
import javax.persistence.Column; import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.Table;
/** /**
* Group for lectures, so you can set limits how many of these the user can * Product option
* choose
*/ */
@Entity @Entity
@Table(name = "product_options") @Table(name = "product_options")
...@@ -42,6 +39,14 @@ public class ProductOption extends GenericEntity implements Cloneable { ...@@ -42,6 +39,14 @@ public class ProductOption extends GenericEntity implements Cloneable {
@Column(name = "price_change") @Column(name = "price_change")
private Integer priceChange; private Integer priceChange;
@Column(name = "priority")
private Integer priority;
@ManyToOne()
@JoinColumn(nullable = false, name = "product_option_group_id")
private ProductOptionGroup productOptionGroup;
public Integer getPriceChange() { public Integer getPriceChange() {
return priceChange; return priceChange;
...@@ -51,6 +56,22 @@ public class ProductOption extends GenericEntity implements Cloneable { ...@@ -51,6 +56,22 @@ public class ProductOption extends GenericEntity implements Cloneable {
this.priceChange = priceChange; this.priceChange = priceChange;
} }
public Integer getPriority() {
return priority;
}
public void setPriority(Integer priority) {
this.priority = priority;
}
public ProductOptionGroup getProductOptionGroup() {
return productOptionGroup;
}
public void setProductOptionGroup(ProductOptionGroup productOptionGroup) {
this.productOptionGroup = productOptionGroup;
}
public String getName() { public String getName() {
return name; return name;
} }
......
...@@ -22,13 +22,12 @@ ...@@ -22,13 +22,12 @@
*/ */
package fi.codecrew.moya.model; package fi.codecrew.moya.model;
import javax.persistence.Column; import javax.persistence.*;
import javax.persistence.Entity; import java.util.ArrayList;
import javax.persistence.Table; import java.util.List;
/** /**
* Group for lectures, so you can set limits how many of these the user can *
* choose
*/ */
@Entity @Entity
@Table(name = "product_option_groups") @Table(name = "product_option_groups")
...@@ -39,6 +38,46 @@ public class ProductOptionGroup extends GenericEntity implements Cloneable { ...@@ -39,6 +38,46 @@ public class ProductOptionGroup extends GenericEntity implements Cloneable {
@Column(name = "name") @Column(name = "name")
private String name; private String name;
@ManyToOne(optional = false)
@JoinColumn(nullable = false, name = "product_id")
private Product product;
@ManyToOne()
@JoinColumn(nullable = true, name = "default_product_option_id")
private ProductOption defaultOption;
@OrderBy("priority")
@OneToMany(cascade = CascadeType.ALL, mappedBy = "productOptionGroup")
private List<ProductOption> options = new ArrayList<>();
@Column(name = "required", nullable = false)
private boolean required = false;
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public ProductOption getDefaultOption() {
return defaultOption;
}
public void setDefaultOption(ProductOption defaultOption) {
this.defaultOption = defaultOption;
}
public boolean isRequired() {
return required;
}
public void setRequired(boolean required) {
this.required = required;
}
public String getName() { public String getName() {
return name; return name;
} }
...@@ -46,4 +85,12 @@ public class ProductOptionGroup extends GenericEntity implements Cloneable { ...@@ -46,4 +85,12 @@ public class ProductOptionGroup extends GenericEntity implements Cloneable {
public void setName(String name) { public void setName(String name) {
this.name = name; this.name = name;
} }
public List<ProductOption> getOptions() {
return options;
}
public void setOptions(List<ProductOption> options) {
this.options = options;
}
} }
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
<property name="eclipselink.session.customizer" <property name="eclipselink.session.customizer"
value="fi.codecrew.moya.database.eclipselink.MoyaSessionCustomizer" /> value="fi.codecrew.moya.database.eclipselink.MoyaSessionCustomizer" />
<property name="eclipselink.ddl-generation" value="none"/> <property name="eclipselink.ddl-generation" value="none"/>
<property name="eclipselink.ddl-generation.output-mode" value="sql-script"/>
</properties> </properties>
</persistence-unit> </persistence-unit>
......
...@@ -83,7 +83,7 @@ ...@@ -83,7 +83,7 @@
<h:form id="limits"> <h:form id="limits">
<h:commandButton rendered="#{!empty productView.product.id}" action="#{productView.initCreateLimit()}" value="#{i18n['product.createLimit']}"> <h:commandButton rendered="#{!empty productView.product.id}" action="#{productView.initCreateLimit()}" value="#{i18n['product.createLimit']}">
</h:commandButton> </h:commandButton>
<p:dataTable border="1" id="discount" value="#{productView.productLimits}" var="limit" rendered="#{!empty productView.product.id and !empty productView.product.productLimits}"> <p:dataTable border="1" id="limit" value="#{productView.productLimits}" var="limit" rendered="#{!empty productView.product.id and !empty productView.product.productLimits}">
<p:column rowHeader="#{i18n['productLimit.name']}"> <p:column rowHeader="#{i18n['productLimit.name']}">
<h:outputText value="#{limit.name}" /> <h:outputText value="#{limit.name}" />
</p:column> </p:column>
...@@ -99,8 +99,31 @@ ...@@ -99,8 +99,31 @@
</p:dataTable> </p:dataTable>
</h:form> </h:form>
<hr />
<h:form id="options">
<h:commandButton rendered="#{!empty productView.product.id}" action="#{productView.initCreateProductOptionGroup()}" value="#{i18n['product.createProductOptionGroup']}"><br /><br />
</h:commandButton>
<p:dataTable border="1" id="optiongroups" value="#{productView.productOptionGroups}" var="group" rendered="#{!empty productView.product.id and !empty productView.product.productOptionGroups}">
<p:column rowHeader="#{i18n['name']}">
<h:outputText value="#{group.name}" />
</p:column>
<p:column>
<p:commandButton ajax="false" action="#{productView.editProductOptionGroup}" value="#{i18n['edit']}" />
</p:column>
</p:dataTable>
</h:form>
</ui:define> </ui:define>
</ui:composition> </ui:composition>
</h:body> </h:body>
</html> </html>
<?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:composite="http://java.sun.com/jsf/composite"
xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:p="http://primefaces.org/ui">
<h:head>
<title></title>
</h:head>
<h:body>
<ui:composition template="#{sessionHandler.template}">
<ui:define name="content">
<h:form id="optionGroup">
<h:link id="back" outcome="/product/edit" value="#{i18n['product.returnProductEdit']} #{productView.product.name}">
<f:param name="productid" value="#{productView.product.id}" />
</h:link>
<h1>#{i18n['productOptionGroup.title']}</h1>
<p:panelGrid columns="2">
<p:outputLabel value="#{i18n['productOptionGroup.name']}" />
<p:inputText value="#{productView.productOptionGroup.name}" />
<p:outputLabel value="#{i18n['productOptionGroup.required']}" />
<p:selectBooleanCheckbox value="#{productView.productOptionGroup.required}" />
<p:outputLabel value="#{i18n['productOptionGroup.default']}" />
<h:outputText id="defaultName" value="#{productView.productOptionGroup.defaultOption.name}" />
<!--
<p:outputLabel value="#{i18n['oeltus']}" />
<p:inputText value="#{productView.productOptionGroup}" /> -->
</p:panelGrid>
<h2>#{i18n['productOption.title']}</h2>
<p:dataTable id="productOptions" value="#{productView.productOptionGroup.options}" var="option">
<p:column headerText="name">
<p:inputText value="#{option.name}" />
</p:column>
<p:column headerText="priority">
<p:inputNumber value="#{option.priority}" />
</p:column>
<p:column headerText="setAsDefault">
<p:commandButton value="#{i18n['option.setAsDefault']}" update="optionGroup:defaultName" action="#{productView.setDefaultOption(option.id)}" rendered="#{option.id ne null and option.id ne 0}" />
</p:column>
<!-- TODO: EI IMPLEMENTOITU VIELA MYYNTIPUOLELLE!!!!!
<p:column headerText="priceChange">
<p:inputText value="#{option.priceChange}" />
</p:column> -->
</p:dataTable>
<p:panelGrid id="addOption" columns="2">
<p:outputLabel for="name" value="#{i18n['productOption.name']}" />
<p:inputText id="name" value="#{productView.productOption.name}" />
<p:commandButton action="#{productView.addProductOption}" value="#{i18n['productOption.add']}" update="productOptions addOption" />
</p:panelGrid>
<p:commandButton id="commitbtn" action="#{productView.saveProductOptionGroup}" value="#{i18n['productLimit.save']}" />
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html>
...@@ -23,7 +23,10 @@ ...@@ -23,7 +23,10 @@
<!-- <h:outputScript target="head" library="script" name="shopscript.js" /> --> <!-- <h:outputScript target="head" library="script" name="shopscript.js" /> -->
<h:outputScript library="primefaces" name="jquery/jquery.js" /> <h:outputScript library="primefaces" name="jquery/jquery.js" />
<p:dataTable columnClasses="nowrap,numalign,numalign,numalign,nowrap" id="billcart" value="#{cc.attrs.items}" var="cart"> <p:dataTable columnClasses="nowrap,numalign,numalign,numalign,nowrap" id="billcart" value="#{cc.attrs.items}" var="cart" expandedRow="true">
<p:column style="width:16px">
<p:rowToggler rendered="#{cart.product.containsProductOptionGroups}" />
</p:column>
<p:column> <p:column>
<f:facet name="header"> <f:facet name="header">
<h:outputText id="name" value="${i18n['shop.product.name']}" /> <h:outputText id="name" value="${i18n['shop.product.name']}" />
...@@ -44,25 +47,18 @@ ...@@ -44,25 +47,18 @@
<h:outputText id="count" value="${i18n['product.cart.count']}" /> <h:outputText id="count" value="${i18n['product.cart.count']}" />
</f:facet> </f:facet>
<p:outputPanel rendered="#{cart.product.usershopAutoproduct}"> <p:outputPanel id="countPanel" rendered="#{cart.product.usershopAutoproduct}">
<h:outputText value="#{cart.count}" /> <h:outputText value="#{cart.count}" />
</p:outputPanel> </p:outputPanel>
<p:outputPanel rendered="#{!cart.product.usershopAutoproduct}"> <p:outputPanel rendered="#{!cart.product.usershopAutoproduct}">
<h:commandButton action="#{productShopView.addMinusOne}" <p:commandButton action="#{productShopView.addMinusOne}" value="#{i18n['productshop.minusOne']}" update="billcart" />
value="#{i18n['productshop.minusOne']}"> <p:inputText size="2" id="cartcount" escape="false" value="#{cart.count}">
<f:ajax render="@form" />
</h:commandButton>
<p:inputText size="2" id="cartcount" escape="false"
value="#{cart.count}">
<f:ajax render="@form" <f:ajax render="@form"
listener="#{productShopView.countChangeListener}" /> listener="#{productShopView.countChangeListener}" />
<f:convertNumber maxFractionDigits="2" minFractionDigits="0" /> <f:convertNumber maxFractionDigits="2" minFractionDigits="0" />
</p:inputText> </p:inputText>
<h:commandButton action="#{productShopView.addOne}" <p:commandButton action="#{productShopView.addOne}" update="billcart" value="#{i18n['productshop.plusOne']}" />
value="#{i18n['productshop.plusOne']}">
<f:ajax render="@form" />
</h:commandButton>
</p:outputPanel> </p:outputPanel>
</p:column> </p:column>
<p:column rendered="#{productShopView.hasLimits}"> <p:column rendered="#{productShopView.hasLimits}">
...@@ -95,6 +91,7 @@ ...@@ -95,6 +91,7 @@
<f:convertNumber maxFractionDigits="2" minFractionDigits="2" currencyCode="EUR" type="currency" locale="#{sessionHandler.locale}" /> <f:convertNumber maxFractionDigits="2" minFractionDigits="2" currencyCode="EUR" type="currency" locale="#{sessionHandler.locale}" />
</h:outputText> </h:outputText>
</p:column> </p:column>
<p:columnGroup type="footer"> <p:columnGroup type="footer">
<p:row> <p:row>
<p:column style="text-align: right;" <p:column style="text-align: right;"
...@@ -109,7 +106,24 @@ ...@@ -109,7 +106,24 @@
</p:column> </p:column>
</p:row> </p:row>
</p:columnGroup> </p:columnGroup>
<p:rowExpansion rendered="#{cart.product.containsProductOptionGroups}">
<p:dataTable value="#{cart.productOptionGroups}" var="group">
<p:column>
<h:outputText value="#{group.name}" />
</p:column>
<p:column>
<p:selectOneMenu value="#{cart.selectedProductOption}" converter="#{productOptionConverter}" >
<f:selectItem itemDisabled="#{group.required}" itemLabel="---" itemValue="0" />
<f:selectItems value="#{group.options}" var="option" itemLabel="#{option.name}" />
</p:selectOneMenu>
</p:column>
</p:dataTable> </p:dataTable>
</p:rowExpansion>
</p:dataTable>
<h:panelGrid columns="3" rendered="#{productShopView.checkAllowStats}"> <h:panelGrid columns="3" rendered="#{productShopView.checkAllowStats}">
<p><h:outputText for="allowStats" value="#{i18n['bill.allowStatistics']}" /></p> <p><h:outputText for="allowStats" value="#{i18n['bill.allowStatistics']}" /></p>
......
...@@ -155,7 +155,7 @@ public class FoodWaveFoodView extends GenericCDIView { ...@@ -155,7 +155,7 @@ public class FoodWaveFoodView extends GenericCDIView {
for (ProductShopItem shopitem : shoppingcart) { for (ProductShopItem shopitem : shoppingcart) {
if (shopitem.getCount().compareTo(BigDecimal.ZERO) > 0) { if (shopitem.getCount().compareTo(BigDecimal.ZERO) > 0) {
billBean.addProductToBill(bill, shopitem.getProduct(), shopitem.getCount(), getFoodWave()); billBean.addProductToBill(bill, shopitem.getProduct(), shopitem.getCount(), getFoodWave(), null);
} }
} }
logger.warn("Committing shoppingcart for user {}. Cart prize: {}", userview.getSelectedUser().getWholeName(), bill.getTotalPrice()); logger.warn("Committing shoppingcart for user {}. Cart prize: {}", userview.getSelectedUser().getWholeName(), bill.getTotalPrice());
......
...@@ -323,7 +323,7 @@ public class ProductShopView extends GenericCDIView { ...@@ -323,7 +323,7 @@ public class ProductShopView extends GenericCDIView {
for (ProductShopItem shopitem : shoppingcart) { for (ProductShopItem shopitem : shoppingcart) {
if (shopitem.getCount().compareTo(BigDecimal.ZERO) > 0) { if (shopitem.getCount().compareTo(BigDecimal.ZERO) > 0) {
billbean.addProductToBill(bill, shopitem.getProduct(), shopitem.getCount()); billbean.addProductToBill(bill, shopitem.getProduct(), shopitem.getCount(), null, shopitem.getSelectedProductOptionString());
} }
} }
billbean.createBill(bill); billbean.createBill(bill);
......
...@@ -27,16 +27,13 @@ import javax.enterprise.context.ConversationScoped; ...@@ -27,16 +27,13 @@ import javax.enterprise.context.ConversationScoped;
import javax.faces.model.ListDataModel; import javax.faces.model.ListDataModel;
import javax.inject.Named; import javax.inject.Named;
import fi.codecrew.moya.model.*;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import fi.codecrew.moya.beans.EventBeanLocal; import fi.codecrew.moya.beans.EventBeanLocal;
import fi.codecrew.moya.beans.ProductBeanLocal; import fi.codecrew.moya.beans.ProductBeanLocal;
import fi.codecrew.moya.enums.apps.ShopPermission; import fi.codecrew.moya.enums.apps.ShopPermission;
import fi.codecrew.moya.model.Discount;
import fi.codecrew.moya.model.Product;
import fi.codecrew.moya.model.ProductFlag;
import fi.codecrew.moya.model.ProductLimitation;
import fi.codecrew.moya.web.cdiview.GenericCDIView; import fi.codecrew.moya.web.cdiview.GenericCDIView;
@Named @Named
...@@ -59,8 +56,14 @@ public class ProductView extends GenericCDIView { ...@@ -59,8 +56,14 @@ public class ProductView extends GenericCDIView {
private ProductLimitation limit; private ProductLimitation limit;
private ProductOptionGroup productOptionGroup;
private ListDataModel<ProductLimitation> productLimits; private ListDataModel<ProductLimitation> productLimits;
private ListDataModel<ProductOptionGroup> productOptionGroups;
private ProductOption productOption = null;
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static final Logger logger = LoggerFactory.getLogger(ProductView.class); private static final Logger logger = LoggerFactory.getLogger(ProductView.class);
...@@ -150,12 +153,27 @@ public class ProductView extends GenericCDIView { ...@@ -150,12 +153,27 @@ public class ProductView extends GenericCDIView {
return "/product/editLimit"; return "/product/editLimit";
} }
public String initCreateProductOptionGroup()
{
this.productOptionGroup = new ProductOptionGroup();
this.productOptionGroup.setProduct(product);
//this.product.getProductOptionGroups().add(this.productOptionGroup);
return "/product/editProductOptionGroup";
}
public String editLimit() public String editLimit()
{ {
limit = productLimits.getRowData(); limit = productLimits.getRowData();
return "/product/editLimit"; return "/product/editLimit";
} }
public String editProductOptionGroup()
{
this.productOptionGroup = productOptionGroups.getRowData();
//this.productOptionGroup = prodbean.refreshProductOptionGroup(this.productOptionGroup);
return "/product/editProductOptionGroup";
}
public String editDiscount() public String editDiscount()
{ {
discount = productDiscounts.getRowData(); discount = productDiscounts.getRowData();
...@@ -174,6 +192,12 @@ public class ProductView extends GenericCDIView { ...@@ -174,6 +192,12 @@ public class ProductView extends GenericCDIView {
return productLimits; return productLimits;
} }
public ListDataModel<ProductOptionGroup> getProductOptionGroups()
{
productOptionGroups = new ListDataModel<>(product.getProductOptionGroups());
return productOptionGroups;
}
public List<ProductFlag> getProductFlags() public List<ProductFlag> getProductFlags()
{ {
return Arrays.asList(ProductFlag.values()); return Arrays.asList(ProductFlag.values());
...@@ -186,4 +210,68 @@ public class ProductView extends GenericCDIView { ...@@ -186,4 +210,68 @@ public class ProductView extends GenericCDIView {
public void setLimit(ProductLimitation limit) { public void setLimit(ProductLimitation limit) {
this.limit = limit; this.limit = limit;
} }
public ProductOptionGroup getProductOptionGroup() {
return productOptionGroup;
}
public ProductOption getProductOption() {
if(productOption == null) {
productOption = new ProductOption();
}
return productOption;
}
public void setProductOption(ProductOption productOption) {
this.productOption = productOption;
}
public void addProductOption() {
this.productOption.setProductOptionGroup(this.productOptionGroup);
this.productOptionGroup.getOptions().add(this.productOption);
/*
if(productOptionGroup.getId() != null) {
prodbean.createProductOption(this.productOption);
}
*/
this.productOption = null;
}
public String saveProductOptionGroup() {
if (product.getProductOptionGroups() == null) {
product.setProductOptionGroups(new ArrayList<>());
}
if (!product.getProductOptionGroups().contains(productOptionGroup)) {
product.getProductOptionGroups().add(productOptionGroup);
}
prodbean.mergeChanges(product);
// need to update this instance
//productOptionGroup = product.getProductOptionGroups().get(product.getProductOptionGroups().indexOf(productOptionGroup));
/*
for(ProductOption option : productOptionGroup.getOptions()) {
if(!option.getProductOptionGroup().equals(productOptionGroup))
option.setProductOptionGroup(productOptionGroup);
prodbean.createOrMerge(option);
}
productOptionGroup = null;*/
return "/product/edit";
}
public void setDefaultOption(int id) {
for(ProductOption o : productOptionGroup.getOptions()) {
if(o.getId() == id)
productOptionGroup.setDefaultOption(o);
}
}
} }
/*
* Copyright Codecrew Ry
*
* All rights reserved.
*
* This license applies to any software containing a notice placed by the
* copyright holder. Such software is herein referred to as the Software.
* This license covers modification, distribution and use of the Software.
*
* Any distribution and use in source and binary forms, with or without
* modification is not permitted without explicit written permission from the
* copyright owner.
*
* 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
* future versions of the Software.
*
*/
package fi.codecrew.moya.web.converter;
import fi.codecrew.moya.beans.ProductBeanLocal;
import fi.codecrew.moya.model.Product;
import fi.codecrew.moya.model.ProductOption;
import fi.codecrew.moya.utilities.jsf.GenericIntegerEntityConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
@Named("productOptionConverter")
@RequestScoped()
public class ProductOptionConverter extends GenericIntegerEntityConverter<ProductOption> {
@EJB
private ProductBeanLocal productbean;
private static final Logger logger = LoggerFactory.getLogger(ProductOptionConverter.class);
@Override
protected ProductOption find(Integer id) {
ProductOption ret = productbean.findOptionById(id);
return ret;
}
}
...@@ -20,16 +20,15 @@ package fi.codecrew.moya.web.helpers; ...@@ -20,16 +20,15 @@ package fi.codecrew.moya.web.helpers;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import fi.codecrew.moya.model.*;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import fi.codecrew.moya.model.Discount; import javax.faces.model.ListDataModel;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.Product;
import fi.codecrew.moya.model.ProductFlag;
public class ProductShopItem { public class ProductShopItem {
...@@ -43,6 +42,10 @@ public class ProductShopItem { ...@@ -43,6 +42,10 @@ public class ProductShopItem {
private BigDecimal limit; private BigDecimal limit;
private EventUser user; private EventUser user;
private ListDataModel<ProductOptionGroup> productOptionGroups = null;
private Map<ProductOptionGroup, ProductOption> selectedOptions = new HashMap<>();
private BigDecimal overriddenUnitPrice = BigDecimal.ZERO; private BigDecimal overriddenUnitPrice = BigDecimal.ZERO;
...@@ -75,6 +78,8 @@ public class ProductShopItem { ...@@ -75,6 +78,8 @@ public class ProductShopItem {
id = this.product.getId(); id = this.product.getId();
setCount(BigDecimal.ZERO); setCount(BigDecimal.ZERO);
setInternalPrice(BigDecimal.ZERO); setInternalPrice(BigDecimal.ZERO);
this.productOptionGroups = new ListDataModel<>(product.getProductOptionGroups());
} }
/** /**
...@@ -261,4 +266,53 @@ public class ProductShopItem { ...@@ -261,4 +266,53 @@ public class ProductShopItem {
this.overrideUnitPrice = overrideUnitPrice; this.overrideUnitPrice = overrideUnitPrice;
} }
public ListDataModel<ProductOptionGroup> getProductOptionGroups() {
return productOptionGroups;
}
public void setSelectedProductOption(ProductOption option) {
if(this.productOptionGroups == null || this.productOptionGroups.getRowData() == null)
return;
/*
if(option.getPriceChange() != null && option.getPriceChange() != 0) {
} */
this.selectedOptions.put(this.productOptionGroups.getRowData(), option);
}
public ProductOption getSelectedProductOption() {
if(this.productOptionGroups == null || this.productOptionGroups.getRowData() == null)
return null;
ProductOptionGroup curGroup = this.productOptionGroups.getRowData();
ProductOption selectedOption = this.selectedOptions.get(curGroup);
if(selectedOption == null && curGroup.getDefaultOption() != null) {
return curGroup.getDefaultOption();
}
return selectedOption;
}
public String getSelectedProductOptionString() {
String retString = "";
for(ProductOption option : this.selectedOptions.values()) {
if(option == null)
continue;
if(!retString.isEmpty()) {
retString += ", ";
}
retString += option.getName();
}
return retString;
}
} }
...@@ -264,7 +264,7 @@ foodshop.buyAndPayWithCredits = Reserve and pay with credits ...@@ -264,7 +264,7 @@ foodshop.buyAndPayWithCredits = Reserve and pay with credits
foodshop.buyFromCounter = Pay at info foodshop.buyFromCounter = Pay at info
foodshop.buyFromInternet = Pay online foodshop.buyFromInternet = Pay online
foodshop.buyProceedToPay = Reserve and continue to paying foodshop.buyProceedToPay = Reserve and continue to paying
foodshop.canBuyToCounter = You can buy this bill on infodesk. If you would like to do so, you can close this window and come to the infodesk to pay this order. foodshop.canBuyToCounter = You can buy this bill on infodesk. If you would like to do so, you can close this window and come to the infodesk to pay this priority.
foodshop.total = Total foodshop.total = Total
foodwave.buyInPrice = Purchase price foodwave.buyInPrice = Purchase price
...@@ -845,7 +845,7 @@ product.vat = VAT-% ...@@ -845,7 +845,7 @@ product.vat = VAT-%
productFlag.CREATE_NEW_PLACE_WHEN_BOUGHT = Create new place when bought productFlag.CREATE_NEW_PLACE_WHEN_BOUGHT = Create new place when bought
productFlag.HIDE_FROM_INFOSHOP = Hide from Info shop productFlag.HIDE_FROM_INFOSHOP = Hide from Info shop
productFlag.PREPAID_CREDIT = Prepaid credit productFlag.PREPAID_CREDIT = Prepaid credit
productFlag.USERSHOP_AUTOPRODUCT = Product will be added to user's order productFlag.USERSHOP_AUTOPRODUCT = Product will be added to user's priority
productFlag.USER_SHOPPABLE = Users can buy productFlag.USER_SHOPPABLE = Users can buy
productLimit.description = Description productLimit.description = Description
...@@ -1561,3 +1561,12 @@ voting.create.voteStart = Voting start ...@@ -1561,3 +1561,12 @@ voting.create.voteStart = Voting start
yes = Yes yes = Yes
tournaments.admin.open_for_roles=Roles allowing registeration tournaments.admin.open_for_roles=Roles allowing registeration
productOptionGroup.name=Name
product.createProductOptionGroup=Create product feature
productOptionGroup.required=Required
productOption.name=Option name
productOption.add=Add new option
productOption.title=Options
productOptionGroup.title=Product feature
productOptionGroup.default=Default option
option.setAsDefault=set as default
...@@ -314,7 +314,7 @@ code.inputfield = Give barcode ...@@ -314,7 +314,7 @@ code.inputfield = Give barcode
compo.edit = Edit compo compo.edit = Edit compo
compo.saveVotes = Save votes compo.saveVotes = Save votes
compo.savesort = Save order compo.savesort = Save priority
compo.votesSaved = Votes saved compo.votesSaved = Votes saved
compoMgmtView.compo.entries = Entries compoMgmtView.compo.entries = Entries
...@@ -476,7 +476,7 @@ foodshop.buyAndPayWithCredits = Reserve and pay with credits ...@@ -476,7 +476,7 @@ foodshop.buyAndPayWithCredits = Reserve and pay with credits
foodshop.buyFromCounter = Pay at info foodshop.buyFromCounter = Pay at info
foodshop.buyFromInternet = Pay online foodshop.buyFromInternet = Pay online
foodshop.buyProceedToPay = Reserve and continue to paying foodshop.buyProceedToPay = Reserve and continue to paying
foodshop.canBuyToCounter = You can buy this bill on infodesk. If you would like to do so, you can close this window and come to the infodesk to pay this order. foodshop.canBuyToCounter = You can buy this bill on infodesk. If you would like to do so, you can close this window and come to the infodesk to pay this priority.
foodshop.total = Total foodshop.total = Total
foodwave.buyInPrice = Purchase price foodwave.buyInPrice = Purchase price
...@@ -1107,7 +1107,7 @@ productFlag.HIDE_FROM_INFOSHOP = Hide from Info shop ...@@ -1107,7 +1107,7 @@ productFlag.HIDE_FROM_INFOSHOP = Hide from Info shop
productFlag.PREPAID_CREDIT = Prepaid credit productFlag.PREPAID_CREDIT = Prepaid credit
productFlag.PREPAID_INSTANT_CREATE = Prepaid instant create productFlag.PREPAID_INSTANT_CREATE = Prepaid instant create
productFlag.RESERVE_PLACE_WHEN_BOUGHT = Reserve place when bought productFlag.RESERVE_PLACE_WHEN_BOUGHT = Reserve place when bought
productFlag.USERSHOP_AUTOPRODUCT = Product will be added to user's order productFlag.USERSHOP_AUTOPRODUCT = Product will be added to user's priority
productFlag.USER_SHOPPABLE = Users can buy productFlag.USER_SHOPPABLE = Users can buy
productLimit.description = Description productLimit.description = Description
...@@ -1837,3 +1837,12 @@ voting.create.voteStart = Voting start ...@@ -1837,3 +1837,12 @@ voting.create.voteStart = Voting start
yes = Yes yes = Yes
tournaments.admin.open_for_roles=Roles allowing registeration tournaments.admin.open_for_roles=Roles allowing registeration
productOptionGroup.name=Name
product.createProductOptionGroup=Create product feature
productOptionGroup.required=Required
productOption.name=Option name
productOption.add=Add new option
productOption.title=Options
productOptionGroup.title=Product feature
productOptionGroup.default=Default option
option.setAsDefault=set as default
...@@ -1824,3 +1824,12 @@ voting.create.voteStart = \u00C4\u00E4nestys auki ...@@ -1824,3 +1824,12 @@ voting.create.voteStart = \u00C4\u00E4nestys auki
yes = Kyll\u00E4 yes = Kyll\u00E4
tournaments.admin.open_for_roles=Rekister\u00F6itymiseen oikeuttavat ryhm\u00E4t tournaments.admin.open_for_roles=Rekister\u00F6itymiseen oikeuttavat ryhm\u00E4t
productOptionGroup.name=Nimi
product.createProductOptionGroup=Luo ominaisuus
productOptionGroup.required=Vaaditaan
productOption.name=Vaihtoehdon nimi
productOption.add=Lis\u00E4\u00E4 uusi vaihtoehto
productOption.title=Ominaisuuden vaihtoehdot
productOptionGroup.title=Tuotevaihtoehto
productOptionGroup.default=Oletusvaihtoehto
option.setAsDefault=Aseta oletukseksi
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!