Commit e9b0113b by Tuomas Riihimäki

Merge branch 'product-billine-summary' into 'master'

Add per product bill summary page

See merge request !430
2 parents 327aa8cc 05ec88b2
......@@ -29,10 +29,7 @@ import javax.ejb.Local;
import fi.codecrew.moya.bortal.views.BillSummary;
import fi.codecrew.moya.entitysearch.BillSearchQuery;
import fi.codecrew.moya.exceptions.BillException;
import fi.codecrew.moya.model.Bill;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.FoodWave;
import fi.codecrew.moya.model.Product;
import fi.codecrew.moya.model.*;
import fi.codecrew.moya.utilities.SearchResult;
@Local
......@@ -70,4 +67,5 @@ public interface BillBeanLocal {
SearchResult<Bill> findUsers(BillSearchQuery q);
List<BillLine> getBillLinesForProduct(Integer productId);
}
......@@ -22,18 +22,27 @@ import java.io.Serializable;
import java.math.BigDecimal;
import fi.codecrew.moya.model.BillLine;
import fi.codecrew.moya.model.Product;
public class BillSummary implements Serializable{
public class BillSummary implements Serializable {
public BillSummary(String name) {
this.name = name;
}
private final Product product;
private final String name;
private String name;
private BigDecimal active = BigDecimal.ZERO;
private BigDecimal paid = BigDecimal.ZERO;
private BigDecimal expired = BigDecimal.ZERO;
public BillSummary(BillLine line) {
this.name = line.getName();
this.product = line.getLineProduct();
}
public BillSummary(Product product) {
this.name = product.getName();
this.product = product;
}
public String getName() {
return name;
}
......@@ -61,4 +70,7 @@ public class BillSummary implements Serializable{
return expired;
}
public Product getProduct() {
return product;
}
}
......@@ -20,11 +20,7 @@ package fi.codecrew.moya.beans;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.*;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
......@@ -218,10 +214,14 @@ public class BillBean implements BillBeanLocal {
@Override
@RolesAllowed(BillPermission.S_READ_ALL)
public Collection<BillSummary> getBillLineSummary() {
Collection<BillSummary> ret = billLineFacade.getLineSummary(eventbean
.getCurrentEvent());
return ret;
Map<String, BillSummary> retmap = new HashMap<String, BillSummary>();
for (BillLine bl : billLineFacade.getAllLines(eventbean.getCurrentEvent())) {
retmap.computeIfAbsent(bl.getName(), (k) -> new BillSummary(bl)).addLine(bl);
}
return retmap.values();
}
/**
......@@ -398,4 +398,11 @@ public class BillBean implements BillBeanLocal {
return billFacade.find(q);
}
@Override
@RolesAllowed(BillPermission.S_READ_ALL)
public List<BillLine> getBillLinesForProduct(Integer productId) {
return billLineFacade.getLinesForProduct(productBean.findById(productId));
}
}
......@@ -18,17 +18,16 @@
*/
package fi.codecrew.moya.facade;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -46,34 +45,22 @@ public class BillLineFacade extends IntegerPkGenericFacade<BillLine> {
@SuppressWarnings("unused")
private static final Logger logger = LoggerFactory.getLogger(BillLineFacade.class);
@EJB
private EventBeanLocal eventbean;
public BillLineFacade() {
super(BillLine.class);
}
// @Override
// public void create(BillLine entity) {
// super.create(entity);
// billfacade.evict(entity.getBill());
// }
public Collection<BillSummary> getLineSummary(LanEvent event) {
public List<BillLine> getAllLines(LanEvent event) {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<BillLine> cq = cb.createQuery(BillLine.class);
Root<BillLine> root = cq.from(BillLine.class);
cq.where(cb.equal(root.get(BillLine_.bill).get(Bill_.event), event));
List<BillLine> lines = getEm().createQuery(cq).getResultList();
Map<String, BillSummary> retmap = new HashMap<String, BillSummary>();
return getEm().createQuery(cq).getResultList();
for (BillLine bl : lines) {
if (!retmap.containsKey(bl.getName())) {
retmap.put(bl.getName(), new BillSummary(bl.getName()));
}
retmap.get(bl.getName()).addLine(bl);
}
return retmap.values();
}
public BillSummary getLineSummary(Product list, LanEvent event) {
......@@ -84,7 +71,7 @@ public class BillLineFacade extends IntegerPkGenericFacade<BillLine> {
cb.equal(root.get(BillLine_.lineProduct), list));
List<BillLine> lines = getEm().createQuery(cq).getResultList();
BillSummary ret = new BillSummary(list.getName());
BillSummary ret = new BillSummary(list);
for (BillLine bl : lines) {
ret.addLine(bl);
......@@ -92,17 +79,18 @@ public class BillLineFacade extends IntegerPkGenericFacade<BillLine> {
return ret;
}
public BillSummary getLineSummary(Product list, LanEvent event, EventUser user) {
public BillSummary getLineSummary(Product product, LanEvent event, EventUser user) {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<BillLine> cq = cb.createQuery(BillLine.class);
Root<BillLine> root = cq.from(BillLine.class);
cq.where(cb.equal(root.get(BillLine_.bill).get(Bill_.event), event),
cb.equal(root.get(BillLine_.lineProduct), list),
cb.equal(root.get(BillLine_.lineProduct), product),
cb.equal(root.get(BillLine_.bill).get(Bill_.user), user)
);
List<BillLine> lines = getEm().createQuery(cq).getResultList();
BillSummary ret = new BillSummary(list.getName());
BillSummary ret = new BillSummary(product);
for (BillLine bl : lines) {
ret.addLine(bl);
......@@ -110,4 +98,16 @@ public class BillLineFacade extends IntegerPkGenericFacade<BillLine> {
return ret;
}
public List<BillLine> getLinesForProduct(Product product) {
if (product == null) {
return null;
}
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<BillLine> cq = cb.createQuery(BillLine.class);
Root<BillLine> root = cq.from(BillLine.class);
cq.where(cb.equal(root.get(BillLine_.lineProduct), product),
cb.equal(root.get(BillLine_.bill).get(Bill_.event), eventbean.getCurrentEvent()));
return getEm().createQuery(cq).getResultList();
}
}
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:bills="http://java.sun.com/jsf/composite/tools/bills"
xmlns:f="http://java.sun.com/jsf/core">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui">
<h:body>
<ui:composition template="#{sessionHandler.template}">
<f:metadata>
<f:event type="preRenderView" listener="#{billListView.initSummaryView}" />
<f:event type="preRenderView" listener="#{billListView.initSummaryView}"/>
</f:metadata>
<ui:define name="content">
<h:form id="billsummary" styleClass="moya_datatable2">
<h:dataTable border="0" id="billSummary" value="#{billListView.billsummary}" var="sumline" styleClass="moya_datatable2">
<h:column>
<f:facet name="header">
<h:outputText value="${i18n['product.name']}" />
</f:facet>
<h:outputText value="#{sumline.name}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="${i18n['product.boughtTotal']}" />
</f:facet>
<p:dataTable border="0" id="billSummary" value="#{billListView.billsummary}" var="sumline"
styleClass="moya_datatable2">
<p:column headerText="${i18n['product.name']}">
<h:outputText value="#{sumline.name}"/>
</p:column>
<p:column headerText="${i18n['product.name']}">
<p:link rendered="#{!empty sumline.product}" outcome="/bill/productSummary"
value="#{sumline.product.name}">
<f:param name="productId" value="#{sumline.product.id}"/>
</p:link>
</p:column>
<p:column headerText="${i18n['product.boughtTotal']}">
<h:outputText value="#{sumline.active}">
<f:convertNumber />
<f:convertNumber/>
</h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="${i18n['product.paid']}" />
</f:facet>
</p:column>
<p:column headerText="${i18n['product.paid']}">
<h:outputText value="#{sumline.paid}">
<f:convertNumber />
<f:convertNumber/>
</h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="${i18n['product.expired']}" />
</f:facet>
</p:column>
<p:column headerText="${i18n['product.expired']}">
<h:outputText value="#{sumline.expired}">
<f:convertNumber />
<f:convertNumber/>
</h:outputText>
</h:column>
</h:dataTable>
</p:column>
</p:dataTable>
</h:form>
</ui:define>
</ui:composition>
......
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui">
<h:body>
<ui:composition template="#{sessionHandler.template}">
<f:metadata>
<f:viewParam value="#{productSummaryView.productId}" name="productId"/>
<f:event type="preRenderView" listener="#{productSummaryView.initProductSummary}"/>
</f:metadata>
<ui:define name="content">
<h:form id="billsummary" styleClass="moya_datatable2">
<p:dataTable id="lines" value="#{productSummaryView.billLines}" var="line" widgetVar="lineTable">
<p:column headerText="${i18n['bill.id_str']}" sortBy="#{line.bill.id }" sortable="true"
filterBy="#{line.bill.paid}" filterMatchMode="exact">
<f:facet name="filter">
<p:selectOneButton onchange="PF('lineTable').filter()" styleClass="custom-filter">
<f:converter converterId="javax.faces.Boolean"/>
<f:selectItem itemLabel="#{i18n['bill.filter_all']}" itemValue=""/>
<f:selectItem itemLabel="#{i18n['bill.isPaid']}" itemValue="true"/>
<f:selectItem itemLabel="#{i18n['bill.isNotPaid']}" itemValue="false"/>
</p:selectOneButton>
</f:facet>
<p:link outcome="/bill/edit" value="#{line.bill.id} (#{line.bill.paid?i18n['bill.isPaid']:i18n['bill.isNotPaid']})">
<f:param name="billid" value="#{line.bill.id}"/>
</p:link>
</p:column>
<p:column sortable="true" sortBy="#{line.bill.paidDate}" headerText="#{i18n['bill.paidDate']}">
<h:outputText value="#{line.bill.paidDate}">
<f:convertDateTime pattern="#{sessionHandler.datetimeFormat}"
timeZone="#{sessionHandler.timezone}"/>
</h:outputText>
</p:column>
<p:column headerText="Purchaser" sortBy="#{line.bill.user.wholeName}" sortable="true">
<p:link outcome="/user/edit" value="#{line.bill.user.wholeName}">
<f:param name="userid" value="#{line.bill.user.user.id}"/>
</p:link>
</p:column>
<p:column headerText="${i18n['billLine.product']}" sortBy="#{line.name}" sortable="true">
<p:link outcome="/product/edit" value="#{line.name}">
<f:param name="productid" value="#{line.lineProduct.id}"/>
</p:link>
</p:column>
<p:column headerText="${i18n['billLine.quantity']}" sortBy="#{line.quantity}" sortable="true">
<h:outputText value="#{line.quantity}">
<f:convertNumber/>
</h:outputText>
</p:column>
</p:dataTable>
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html>
\ No newline at end of file
......@@ -57,3 +57,8 @@
100% { opacity: 1.0; }
}
.ui-filter-column .ui-column-customfilter .custom-filter {
width: 100%;
box-sizing: border-box;
}
/*
* 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.cdiview.shop;
import fi.codecrew.moya.beans.BillBeanLocal;
import fi.codecrew.moya.beans.EventBeanLocal;
import fi.codecrew.moya.beans.VerkkomaksutFiBeanLocal;
import fi.codecrew.moya.bortal.views.BillSummary;
import fi.codecrew.moya.entitysearch.BillSearchQuery;
import fi.codecrew.moya.enums.apps.BillPermission;
import fi.codecrew.moya.exceptions.BillException;
import fi.codecrew.moya.model.Bill;
import fi.codecrew.moya.model.BillLine;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.utilities.SearchQuery.QuerySortOrder;
import fi.codecrew.moya.utilities.SearchResult;
import fi.codecrew.moya.utilities.jsf.MessageHelper;
import fi.codecrew.moya.web.annotations.SelectedUser;
import fi.codecrew.moya.web.cdiview.GenericCDIView;
import fi.codecrew.moya.web.helpers.LazyEntityDataModel;
import org.primefaces.model.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ejb.EJB;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
@Named
@ConversationScoped
public class ProductSummaryView extends GenericCDIView {
private static final long serialVersionUID = -4668803787903428161L;
private static final Logger logger = LoggerFactory.getLogger(ProductSummaryView.class);
@EJB
private transient BillBeanLocal billbean;
private Integer productId;
private List<BillLine> billLines;
public void initProductSummary() {
if (super.requirePermissions(BillPermission.READ_ALL) && billLines == null) {
beginConversation();
logger.info("Initializing lazyList");
billLines = billbean.getBillLinesForProduct(productId);
}
}
public Integer getProductId() {
return productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public List<BillLine> getBillLines() {
return billLines;
}
public void setBillLines(List<BillLine> billLines) {
this.billLines = billLines;
}
}
......@@ -1944,3 +1944,5 @@ holderize.row = Row
holderize.barcode = Barcode
holderize.nextCodeHeader = Next card position
holderize.parametersHeader = Folder parameters
bill.id_str=Bill id
bill.filter_all=All
\ No newline at end of file
......@@ -1916,17 +1916,19 @@ role.source.ACCOUNTEVENT = Tilitapah
role.source.PLACE_PRODUCT = Tuote paikan kautta
role.source.EVENT_DEFAULT = Tapahtuman oletusrooli
user.allroles = Kaikki k\u00E4ytt\u00E4j\u00E4n roolit
voting.create.entrysubmitrole = Teosten lhettmiseen tarvittava rooli
voting.create.entrysubmitrole = Teosten l\u00E4hett\u00E4miseen tarvittava rooli
compo.filetype.name = Tiedostotyypin nimi
compo.filetype.sort = Jrjestysnumero
compo.filetype.sort = J\u00E4rjestysnumero
compo.filetype.filetype = Tyyppi
feature.name = Ominaisuus
feature.user_permission = Kyttj
feature.info_permission = Jrjestj
feature.admin_permission = Pkyttj
feature.user_permission = K\u00E4ytt\u00E4j\u00E4
feature.info_permission = J\u00E4rjest\u00E4j\u00E4
feature.admin_permission = P\u00E4\u00E4k\u00E4ytt\u00E4j\u00E4
role.features = Tapahtuman ominaisuuksien oikeudet
bill.id_str=Laskun ID
bill.filter_all=Kaikki
holderize.header = Tulostettujen korttien kansiotus
holderize.pageRows = Rivej sivulla
holderize.pageRows = Rivej sivulla
holderize.pageColumns = Sarakkeita sivulla
holderize.folderName = Kansion nimi
holderize.page = Sivu
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!