Commit cad83996 by Tuomas Riihimäki

Merge branch 'issue_74_discountForShop' into 'master'

Issue 74 discount for shop

Fixes issue #74

See merge request !133
2 parents c6d5c2cc 4ee37211
...@@ -53,6 +53,8 @@ public interface ProductBeanLocal { ...@@ -53,6 +53,8 @@ public interface ProductBeanLocal {
AccountEvent createAccountEvent(Product product, BigDecimal quantity, EventUser user); AccountEvent createAccountEvent(Product product, BigDecimal quantity, EventUser user);
AccountEvent createAccountEvent(Product product, BigDecimal overriddenUnitPrice, BigDecimal quantity, EventUser user);
// List<Discount> getActiveDiscounts(Product product, BigDecimal quantity); // List<Discount> getActiveDiscounts(Product product, BigDecimal quantity);
Product findById(int parseInt); Product findById(int parseInt);
......
...@@ -72,12 +72,12 @@ public class BillBean implements BillBeanLocal { ...@@ -72,12 +72,12 @@ public class BillBean implements BillBeanLocal {
private BillFacade billFacade; private BillFacade billFacade;
@EJB @EJB
private EventBeanLocal eventbean; private EventBean eventbean;
@EJB @EJB
private BillLineFacade billLineFacade; private BillLineFacade billLineFacade;
@EJB @EJB
private PermissionBeanLocal permbean; private PermissionBean permbean;
@EJB @EJB
private ProductBean productBean; private ProductBean productBean;
...@@ -308,7 +308,7 @@ public class BillBean implements BillBeanLocal { ...@@ -308,7 +308,7 @@ public class BillBean implements BillBeanLocal {
logger.debug("Creating Bill prepaidInstant product {}, {}", prod.getName(), bl.getQuantity()); logger.debug("Creating Bill prepaidInstant product {}, {}", prod.getName(), bl.getQuantity());
AccountEvent ac2 = productPBean.createAccountEvent(prod, bl.getQuantity(), user, bill.getSentDate(), bl.getFoodwave()); AccountEvent ac2 = productPBean.createAccountEvent(prod, bl.getQuantity(), null, user, bill.getSentDate(), bl.getFoodwave());
logger.info("Created ac from product. {}, userproducts {}", ac2, user.getAccountEvents().size()); logger.info("Created ac from product. {}, userproducts {}", ac2, user.getAccountEvents().size());
ac2.setSeller(permbean.getCurrentUser()); ac2.setSeller(permbean.getCurrentUser());
......
...@@ -406,7 +406,16 @@ public class ProductBean implements ProductBeanLocal { ...@@ -406,7 +406,16 @@ public class ProductBean implements ProductBeanLocal {
return ret; return ret;
} }
@Override @Override
public AccountEvent createAccountEvent(Product product, BigDecimal overriddenUnitPrice, BigDecimal quantity, EventUser user) {
user = eventUserFacade.reload(user);
AccountEvent ret = productPBean.createAccountEvent(product, quantity, overriddenUnitPrice, user, Calendar.getInstance(), null);
cardTemplateBean.checkPrintedCard(user);
return ret;
}
@Override
// @RolesAllowed(ShopPermission.S_LIST_ALL_PRODUCTS) // @RolesAllowed(ShopPermission.S_LIST_ALL_PRODUCTS)
public Product findByBarcode(String barcode) { public Product findByBarcode(String barcode) {
return productFacade.findProductByBarcode(barcode); return productFacade.findProductByBarcode(barcode);
......
...@@ -23,10 +23,7 @@ import java.util.ArrayList; ...@@ -23,10 +23,7 @@ import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
import javax.ejb.EJB; import javax.ejb.*;
import javax.ejb.EJBException;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -62,6 +59,10 @@ public class ProductPBean { ...@@ -62,6 +59,10 @@ public class ProductPBean {
@EJB @EJB
private ProductFacade productFacade; private ProductFacade productFacade;
@EJB
private LoggingBean lbean;
private static final Logger logger = LoggerFactory private static final Logger logger = LoggerFactory
.getLogger(ProductPBean.class); .getLogger(ProductPBean.class);
...@@ -72,9 +73,9 @@ public class ProductPBean { ...@@ -72,9 +73,9 @@ public class ProductPBean {
// TODO Auto-generated constructor stub // TODO Auto-generated constructor stub
} }
public AccountEvent createAccountEvent(Product product, public AccountEvent createAccountEvent(Product product, BigDecimal quantity, EventUser user, Calendar date) {
BigDecimal quantity, EventUser user, Calendar date) {
return this.createAccountEvent(product, quantity, user, date, null); return this.createAccountEvent(product, null, quantity, user, date, null);
} }
/** /**
...@@ -93,9 +94,7 @@ public class ProductPBean { ...@@ -93,9 +94,7 @@ public class ProductPBean {
* AccountEvent creation time * AccountEvent creation time
* @return The created AccountEvent entity * @return The created AccountEvent entity
*/ */
public AccountEvent createAccountEvent(Product product, public AccountEvent createAccountEvent(Product product, BigDecimal overriddenUnitPrice, BigDecimal quantity, EventUser user, Calendar date, FoodWave foodwave) {
BigDecimal quantity, EventUser user, Calendar date,
FoodWave foodwave) {
if (!accounteventfacade.isAttached(product)) { if (!accounteventfacade.isAttached(product)) {
product = productFacade.reload(product); product = productFacade.reload(product);
...@@ -104,12 +103,25 @@ public class ProductPBean { ...@@ -104,12 +103,25 @@ public class ProductPBean {
if (!product.getEvent().equals(user.getEvent())) { if (!product.getEvent().equals(user.getEvent())) {
throw new EJBException("Trying to create accountevent for different event in user and product"); throw new EJBException("Trying to create accountevent for different event in user and product");
} }
BigDecimal unitPrice = product.getPrice().negate(); BigDecimal unitPrice = product.getPrice().negate();
List<Discount> discounts = discountBean.getActiveDiscountsByProduct(product, quantity, date, user); List<Discount> discounts = new ArrayList<>();
for (Discount d : discounts) {
unitPrice = unitPrice.multiply(d.getPercentage()); if(overriddenUnitPrice != null && BigDecimal.ZERO.compareTo(overriddenUnitPrice) < 0) {
}
unitPrice = overriddenUnitPrice;
lbean.logMessage(SecurityLogType.accountEvent, permbean.getCurrentUser(), "User creating accountevent with discount");
} else {
// no discounts if custom price
discounts = discountBean.getActiveDiscountsByProduct(product, quantity, date, user);
for (Discount d : discounts) {
unitPrice = unitPrice.multiply(d.getPercentage());
}
}
AccountEvent ret = new AccountEvent(user, product, unitPrice, quantity, Calendar.getInstance()); AccountEvent ret = new AccountEvent(user, product, unitPrice, quantity, Calendar.getInstance());
...@@ -124,17 +136,18 @@ public class ProductPBean { ...@@ -124,17 +136,18 @@ public class ProductPBean {
foodwave.getAccountEvents().add(ret); foodwave.getAccountEvents().add(ret);
} }
if (product.getProductFlags().contains(ProductFlag.RESERVE_PLACE_WHEN_BOUGHT) if (product.getProductFlags().contains(ProductFlag.RESERVE_PLACE_WHEN_BOUGHT) || product.getProductFlags().contains(ProductFlag.CREATE_NEW_PLACE_WHEN_BOUGHT)) {
|| product.getProductFlags().contains(ProductFlag.CREATE_NEW_PLACE_WHEN_BOUGHT)) {
placebean.lockPlaceProduct(user, product, quantity); placebean.lockPlaceProduct(user, product, quantity);
} }
List<DiscountInstance> accEventdiscounts = ret.getDiscountInstances(); List<DiscountInstance> accEventdiscounts = ret.getDiscountInstances();
for (Discount d : discounts) { for (Discount d : discounts) {
// discountsArray.add(discInst); // discountsArray.add(discInst);
// discountinstancefacade.create(discInst); // discountinstancefacade.create(discInst);
accEventdiscounts.add(new DiscountInstance(ret, d)); accEventdiscounts.add(new DiscountInstance(ret, d));
} }
if (product.getAccountEvents() == null) { if (product.getAccountEvents() == null) {
product.setAccountEvents(new ArrayList<AccountEvent>()); product.setAccountEvents(new ArrayList<AccountEvent>());
} }
...@@ -145,6 +158,8 @@ public class ProductPBean { ...@@ -145,6 +158,8 @@ public class ProductPBean {
logger.debug("create ac {} for user {}", ret, user.getUser()); logger.debug("create ac {} for user {}", ret, user.getUser());
// flush changes to db. // flush changes to db.
// userFacade.flush(); // userFacade.flush();
lbean.logMessage(SecurityLogType.accountEvent, permbean.getCurrentUser(), "User created accountevent: ", ret.getId());
return ret; return ret;
} }
} }
Manifest-Version: 1.0
Class-Path: lib/MoyaUtilities.jar
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
<composite:implementation> <composite:implementation>
<h:form id="shoppingcartform"> <h:form id="shoppingcartform">
<h:panelGrid columns="2" style="width:100%;" columnClasses="shopProductbuttons,topalign"> <h:panelGrid columns="2" style="width:100%;" columnClasses="shopProductbuttons,topalign">
<h:panelGroup> <h:panelGroup>
<div id="shopItems"> <div id="shopItems">
...@@ -36,10 +36,14 @@ ...@@ -36,10 +36,14 @@
<h:panelGroup > <h:panelGroup >
<reader:codefield selectaction="#{productShopView.readCode}" selectvalue="#{i18n['shop.readBarcode']}" /> <!-- TODO: barcode does not work, fix and re-enable -->
<!-- reader:codefield selectaction="#{productShopView.readCode}" selectvalue="#{i18n['shop.readBarcode']}" / -->
<br /> <br />
<p:dataTable id="prods" value="#{productShopView.boughtItems}" var="prods" style="width:500px;"> <p:dataTable id="prods" value="#{productShopView.boughtItems}" editable="true" var="prods" style="width:600px;">
<p:ajax event="rowEdit" listener="#{productShopItemHelper.updateProductShopItemCount(prods)}" update="prods @(.inputval)" />
<p:column headerText="#{i18n['shop.count']}"> <p:column headerText="#{i18n['shop.count']}">
<p:inputText value="#{prods.count}" size="2"> <p:inputText value="#{prods.count}" size="2">
<f:ajax render="@form" listener="#{productShopView.countBoughtChangeListener}" /> <f:ajax render="@form" listener="#{productShopView.countBoughtChangeListener}" />
...@@ -55,13 +59,29 @@ ...@@ -55,13 +59,29 @@
<f:convertNumber maxFractionDigits="2" minFractionDigits="2" /> <f:convertNumber maxFractionDigits="2" minFractionDigits="2" />
</h:outputText> </h:outputText>
</p:column> </p:column>
<p:column headerText="#{i18n['shop.customPrice']}">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{prods.overriddenUnitPrice}" /></f:facet>
<f:facet name="input"><p:inputText value="#{prods.overriddenUnitPrice}" /></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="#{i18n['shop.unitdiscount']}">
<h:outputText value="#{prods.unitDiscount}">
<f:convertNumber maxFractionDigits="2" minFractionDigits="2" />
</h:outputText>
</p:column>
<p:column headerText="#{i18n['shop.totalPrice']}"> <p:column headerText="#{i18n['shop.totalPrice']}">
<h:outputText value="#{prods.price}"> <h:outputText value="#{prods.price}">
<f:convertNumber maxFractionDigits="2" minFractionDigits="2" /> <f:convertNumber maxFractionDigits="2" minFractionDigits="2" />
</h:outputText> </h:outputText>
</p:column> </p:column>
<p:column headerText="#{i18n['shop.actions']}"> <p:column headerText="#{i18n['shop.actions']}">
<p:commandButton action="#{productShopView.removeBought()}" update="@form" onerror="location.reload(true);" value="Poista" /> <p:rowEditor />
<p:commandButton action="#{productShopView.removeBought()}" update="@form" onerror="location.reload(true);" icon="ui-icon-trash" />
</p:column> </p:column>
</p:dataTable> </p:dataTable>
...@@ -83,7 +103,7 @@ ...@@ -83,7 +103,7 @@
</div> </div>
<h:panelGrid columns="2"> <h:panelGrid columns="2">
<h:outputLabel value="#{i18n['shop.toAccountValue']}" /> <h:outputLabel value="#{i18n['shop.toAccountValue']}" />
<h:inputText styleClass="inputval" size="5" value="#{productShopView.cash}"> <h:inputText styleClass="inputval" size="5" value="#{productShopView.cash}">
<f:ajax render="@form" event="valueChange" listener="#{productShopView.cashChanged}" /> <f:ajax render="@form" event="valueChange" listener="#{productShopView.cashChanged}" />
...@@ -114,7 +134,6 @@ ...@@ -114,7 +134,6 @@
$(function() { $(function() {
$("#shoppingcartform\\:barcode").focus(); $("#shoppingcartform\\:barcode").focus();
}); });
function blip() { function blip() {
......
...@@ -163,7 +163,7 @@ ...@@ -163,7 +163,7 @@
} }
</h:outputScript> </h:outputScript>
<h:form id="usermetaform" enctype="multipart/form-data"> <h:form id="usermetaform" enctype="multipart/form-data">
<p:fieldset legend="#{i18n['user.meta.box.legend']}"> <p:fieldset legend="#{i18n['user.meta.box.title']}">
<p:panelGrid columns="1" cellpadding="1"> <p:panelGrid columns="1" cellpadding="1">
<div id="usermetaview">#{userView.meta}</div> <div id="usermetaview">#{userView.meta}</div>
</p:panelGrid> </p:panelGrid>
......
...@@ -19,9 +19,10 @@ ...@@ -19,9 +19,10 @@
</ui:define> </ui:define>
<ui:define name="edittab"> <ui:define name="edittab">
<users:usertabs tabId="shop" /> <users:usertabs tabId="shop" />
</ui:define> </ui:define>
<ui:define name="content"> <ui:define name="content">
<shop:shoppingcart /> <shop:shoppingcart />
</ui:define> </ui:define>
......
...@@ -124,8 +124,6 @@ public class FoodWaveFoodView extends GenericCDIView { ...@@ -124,8 +124,6 @@ public class FoodWaveFoodView extends GenericCDIView {
public String add(Integer count) { public String add(Integer count) {
ProductShopItem item = getShoppingcart().getRowData(); ProductShopItem item = getShoppingcart().getRowData();
psiHelper.setProductShopItemCount(item, item.getCount().add(BigDecimal.valueOf(count))); psiHelper.setProductShopItemCount(item, item.getCount().add(BigDecimal.valueOf(count)));
System.out.println("foobar" + item.getCount());
return null; return null;
} }
......
...@@ -177,6 +177,7 @@ public class ProductShopView extends GenericCDIView { ...@@ -177,6 +177,7 @@ public class ProductShopView extends GenericCDIView {
} }
} }
public void countBoughtChangeListener() public void countBoughtChangeListener()
{ {
ProductShopItem item = boughtItems.getRowData(); ProductShopItem item = boughtItems.getRowData();
...@@ -361,11 +362,13 @@ public class ProductShopView extends GenericCDIView { ...@@ -361,11 +362,13 @@ public class ProductShopView extends GenericCDIView {
public String commitShoppingCart() { public String commitShoppingCart() {
EventUser retuser = null; EventUser retuser = null;
for (ProductShopItem shopitem : shoppingcart) { for (ProductShopItem shopitem : shoppingcart) {
if (shopitem.getCount().compareTo(BigDecimal.ZERO) > 0) { if (shopitem.getCount().compareTo(BigDecimal.ZERO) > 0) {
retuser = productBean.createAccountEvent(shopitem.getProduct(), shopitem.getCount(), userView.getSelectedUser()).getUser(); retuser = productBean.createAccountEvent(shopitem.getProduct(), shopitem.getCount(), shopitem.getOverriddenUnitPrice(), userView.getSelectedUser()).getUser();
} }
} }
if (cash != null && cash.compareTo(BigDecimal.ZERO) != 0) { if (cash != null && cash.compareTo(BigDecimal.ZERO) != 0) {
Product credProd = productBean.findCreditProduct(); Product credProd = productBean.findCreditProduct();
retuser = productBean.createAccountEvent(credProd, cash, userView.getSelectedUser()).getUser(); retuser = productBean.createAccountEvent(credProd, cash, userView.getSelectedUser()).getUser();
......
...@@ -43,6 +43,29 @@ public class ProductShopItemHelper extends GenericCDIView { ...@@ -43,6 +43,29 @@ public class ProductShopItemHelper extends GenericCDIView {
@EJB @EJB
private DiscountBeanLocal discountBean; private DiscountBeanLocal discountBean;
public void updateProductShopItemCount(ProductShopItem item) {
// Discounts or overridden price, you cannot get both
if(item.isPriceOverridden()) {
item.setInternalPrice(item.getOverriddenUnitPrice().multiply(item.getCount()));
} else {
item.setInternalPrice(item.getProduct().getPrice().abs().multiply(item.getCount()));
item.setInternalDiscounts(discountBean.getActiveDiscountsByProduct(item.getProduct(), item.getCount(), Calendar.getInstance(), item.getUser()));
item.setInternalDiscountValues(new HashMap<Integer, BigDecimal>());
for (Discount d : item.getDiscounts())
{
BigDecimal newprice = item.getPrice().multiply(d.getPercentage());
item.getInternalDiscountValues().put(d.getId(), item.getPrice().subtract(newprice));
item.setInternalPrice(newprice);
}
}
}
public void setProductShopItemCount(ProductShopItem item, BigDecimal count) { public void setProductShopItemCount(ProductShopItem item, BigDecimal count) {
if (count == null || count.compareTo(BigDecimal.ZERO) < 0) if (count == null || count.compareTo(BigDecimal.ZERO) < 0)
...@@ -50,19 +73,8 @@ public class ProductShopItemHelper extends GenericCDIView { ...@@ -50,19 +73,8 @@ public class ProductShopItemHelper extends GenericCDIView {
count = BigDecimal.ZERO; count = BigDecimal.ZERO;
} }
item.setCount(count); item.setCount(count);
updateProductShopItemCount(item);
item.setInternalPrice(item.getProduct().getPrice().abs().multiply(count));
item.setInternalDiscounts(discountBean.getActiveDiscountsByProduct(item.getProduct(), count, Calendar.getInstance(), item.getUser()));
item.setInternalDiscountValues(new HashMap<Integer, BigDecimal>());
for (Discount d : item.getDiscounts())
{
BigDecimal newprice = item.getPrice().multiply(d.getPercentage());
item.getInternalDiscountValues().put(d.getId(), item.getPrice().subtract(newprice));
item.setInternalPrice(newprice);
}
} }
public boolean updateProductShopItemLimit(ProductShopItem item, BigDecimal limitValue) { public boolean updateProductShopItemLimit(ProductShopItem item, BigDecimal limitValue) {
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
package fi.codecrew.moya.web.helpers; package fi.codecrew.moya.web.helpers;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -42,6 +43,12 @@ public class ProductShopItem { ...@@ -42,6 +43,12 @@ public class ProductShopItem {
private BigDecimal limit; private BigDecimal limit;
private EventUser user; private EventUser user;
private BigDecimal overriddenUnitPrice = BigDecimal.ZERO;
public BigDecimal getCreditPrice() public BigDecimal getCreditPrice()
{ {
if (BigDecimal.ZERO.compareTo(price) < 0) if (BigDecimal.ZERO.compareTo(price) < 0)
...@@ -106,7 +113,7 @@ public class ProductShopItem { ...@@ -106,7 +113,7 @@ public class ProductShopItem {
* *
* p.s. This still needs to exist because we want to set count from jsf, but * p.s. This still needs to exist because we want to set count from jsf, but
* this value needs to be updated with * this value needs to be updated with
* ProductShopIteHelper.setProductShopItemCount * ProductShopIteHelper.updateProductShopItemCount
* *
* @param count * @param count
*/ */
...@@ -114,6 +121,11 @@ public class ProductShopItem { ...@@ -114,6 +121,11 @@ public class ProductShopItem {
this.count = count; this.count = count;
} }
/**
* Price and discounts are only stored so we can show them to user, changing there does not change end price of card
* @param discounts
*/
public void setInternalPrice(BigDecimal price) { public void setInternalPrice(BigDecimal price) {
this.price = price; this.price = price;
} }
...@@ -123,6 +135,10 @@ public class ProductShopItem { ...@@ -123,6 +135,10 @@ public class ProductShopItem {
return discounts; return discounts;
} }
/**
* Price and discounts are only stored so we can show them to user, changing there does not change end price of card
* @param discounts
*/
public void setInternalDiscounts(List<Discount> discounts) { public void setInternalDiscounts(List<Discount> discounts) {
this.discounts = discounts; this.discounts = discounts;
} }
...@@ -144,7 +160,7 @@ public class ProductShopItem { ...@@ -144,7 +160,7 @@ public class ProductShopItem {
public void setId(Integer setid) { public void setId(Integer setid) {
logger.info("Setting id {} to cart {}", setid, id); logger.info("Setting id {} to cart {}", setid, id);
if (!id.equals(setid)) { if (!id.equals(setid)) {
throw new RuntimeException("Carts mixed up! Please raport an error to coders! "); throw new RuntimeException("Carts mixed up! Please report an error to coders! ");
} }
} }
...@@ -175,4 +191,34 @@ public class ProductShopItem { ...@@ -175,4 +191,34 @@ public class ProductShopItem {
public void setInternalDiscountValues(Map<Integer, BigDecimal> discountValues) { public void setInternalDiscountValues(Map<Integer, BigDecimal> discountValues) {
this.discountValues = discountValues; this.discountValues = discountValues;
} }
public BigDecimal getOverriddenUnitPrice() {
if(overriddenUnitPrice == null)
overriddenUnitPrice = BigDecimal.ZERO;
return overriddenUnitPrice;
}
/**
* Warning: this will not work if you do not run also: ProductShopIteHelper.setProductShopItemCount
*
* Overridden unit price will also override discounts
*
* @param overrideUnitPrice
*/
public void setOverriddenUnitPrice(BigDecimal overrideUnitPrice) {
this.overriddenUnitPrice = overrideUnitPrice;
}
public boolean isPriceOverridden() {
return (getOverriddenUnitPrice() != null && getOverriddenUnitPrice().compareTo(BigDecimal.ZERO) > 0);
}
public BigDecimal getUnitDiscount() {
return getPrice().divide(getCount()).subtract(getProduct().getPrice());
}
} }
#Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net) #Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net)
#Sat Mar 30 17:56:44 EET 2013 #Sat Mar 30 17:56:44 EET 2013
shop.unitdiscount = Alennus
shop.customPrice = Uusi hinta
accountEvent.commit = Tallenna accountEvent.commit = Tallenna
actionlog.create.header = Create new actionmessage actionlog.create.header = Create new actionmessage
......
...@@ -1614,3 +1614,5 @@ voting.create.voteEnd = Voting close ...@@ -1614,3 +1614,5 @@ voting.create.voteEnd = Voting close
voting.create.voteStart = Voting start voting.create.voteStart = Voting start
yes = Yes yes = Yes
shop.unitdiscount=Discount
shop.customPrice=new price
...@@ -1596,3 +1596,5 @@ voting.create.voteEnd = \u00C4\u00E4nestys kiinni ...@@ -1596,3 +1596,5 @@ voting.create.voteEnd = \u00C4\u00E4nestys kiinni
voting.create.voteStart = \u00C4\u00E4nestys auki voting.create.voteStart = \u00C4\u00E4nestys auki
yes = Kyll\u00E4 yes = Kyll\u00E4
shop.unitdiscount=Alennus
shop.customPrice=Uusi hinta
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!