Detect in-pantry

This commit is contained in:
Tim Holloway 2022-01-16 08:52:04 -05:00
parent c80b8598d4
commit ec823ff784
11 changed files with 153 additions and 163 deletions

View File

@ -4,6 +4,7 @@ import com.mousetech.gourmetj.utils.IngredientDigester;
import com.mousetech.gourmetj.utils.IngredientDigester.IngredientAmountFormat;
public class ShopIngredient implements Comparable<Object> {
/**
* Constructor.
*
@ -27,12 +28,13 @@ public class ShopIngredient implements Comparable<Object> {
*/
public ShopIngredient( Double amount, String unit,
String item, String ingkey,
String shopCat) {
String shopCat, boolean inPantry) {
this.amount = amount;
this.unit = unit;
this.item = item;
this.ingkey = ingkey;
this.shopCat = shopCat;
this.inPantry = inPantry;
}
private String shopCat;
@ -119,6 +121,22 @@ public class ShopIngredient implements Comparable<Object> {
private Double amount;
private String displayAmount;
private String unit;
private boolean inPantry;
/**
* @return the inPantry
*/
public boolean isInPantry() {
return inPantry;
}
/**
* @param inPantry the inPantry to set
*/
public void setInPantry(boolean inPantry) {
this.inPantry = inPantry;
}
@Override
public int compareTo(Object o) {

View File

@ -1,7 +1,5 @@
package com.mousetech.gourmetj;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
@ -14,18 +12,23 @@ import javax.inject.Inject;
import javax.inject.Named;
import org.apache.commons.lang3.StringUtils;
import org.primefaces.model.ByteArrayContent;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.mousetech.gourmetj.persistence.dao.ShopcatRepository;
import com.mousetech.gourmetj.persistence.model.Ingredient;
import com.mousetech.gourmetj.persistence.model.Pantry;
import com.mousetech.gourmetj.persistence.model.Recipe;
import com.mousetech.gourmetj.persistence.model.Shopcat;
import com.mousetech.gourmetj.utils.YamlShoppingList;
/** Backing bean for the Shopping List tab of the "More..."
* page.
* _TestedBy ShoppingListBeanTest
* @author timh
* @since Jan 16, 2022
*/
@Named
@ViewScoped
public class ShoppingListBean implements Serializable {
@ -160,9 +163,14 @@ public class ShoppingListBean implements Serializable {
if (multiplier > 1 && (amt != null)) {
amt *= multiplier;
}
boolean inPantry = false;
Pantry pantry = ing.getPantry();
if ( (pantry != null) && pantry.getPantry()) {
inPantry = true;
}
sing = new ShopIngredient(amt, ing.getUnit(),
ing.getItem(), ing.getIngkey(),
shopCatName);
shopCatName, inPantry);
siList.add(sing);
} catch (Exception e) {
log.error("Unable to create ShopIngredient for "

View File

@ -80,6 +80,29 @@ public class Ingredient implements Serializable, IngredientIF {
@Column(name = "unit")
private String unit;
@ManyToOne(fetch = FetchType.EAGER, cascade = {
CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.REFRESH }, optional = true)
@JoinColumn(name = "ingkey", referencedColumnName = "ingkey", insertable = false, updatable = false)
private Pantry pantry;
/**
* @return the pantry
*/
public Pantry getPantry() {
return pantry;
}
/**
* @param pantry the pantry to set
*/
public void setPantry(Pantry pantry) {
this.pantry = pantry;
}
/**
* Default Constructor.
*/
public Ingredient() {
// Attempt to remedy lack of constraints in DB
this.optional = 0;

View File

@ -3,52 +3,58 @@ package com.mousetech.gourmetj.persistence.model;
import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the "pantry" database table.
*
*/
@Entity
@Table(name="\"pantry\"")
@NamedQuery(name="Pantry.findAll", query="SELECT p FROM Pantry p")
@Table(name = "pantry")
public class Pantry implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="\"id\"")
private int id;
@Column(name = "id")
private Long id;
@Column(name="\"ingkey\"")
private Integer ingkey;
@Column(name = "ingkey", nullable=false)
private String ingkey;
@Column(name="\"pantry\"")
private String pantry;
@Column(name = "pantry")
private Boolean pantry;
/**
* Default Constructor.
*/
public Pantry() {
}
public int getId() {
public Long getId() {
return this.id;
}
public void setId(int id) {
public void setId(Long id) {
this.id = id;
}
public Integer getIngkey() {
public String getIngkey() {
return this.ingkey;
}
public void setIngkey(Integer ingkey) {
public void setIngkey(String ingkey) {
this.ingkey = ingkey;
}
public String getPantry() {
public Boolean getPantry() {
return this.pantry;
}
public void setPantry(String pantry) {
public void setPantry(Boolean pantry) {
this.pantry = pantry;
}
@Override
public String toString() {
return ("Pantry " + getId() + " " + ingkey + " "
+ getPantry());
}
}

View File

@ -22,8 +22,10 @@ import javax.persistence.*;
+ " ORDER BY cuisine ASC")
@NamedEntityGraph(name = "Recipe.findWorkingSet", attributeNodes = {
@NamedAttributeNode(value = "categories"),
@NamedAttributeNode(value = "ingredientHash", subgraph = "subgraph.shopcat") }, subgraphs = {
@NamedSubgraph(name = "subgraph.shopcat", attributeNodes = @NamedAttributeNode(value = "shopCat")) })
@NamedAttributeNode(value = "ingredientHash", subgraph = "subgraph.shopcat"),
@NamedAttributeNode(value = "ingredientHash", subgraph = "subgraph.pantry") }, subgraphs = {
@NamedSubgraph(name = "subgraph.shopcat", attributeNodes = @NamedAttributeNode(value = "shopCat")),
@NamedSubgraph(name = "subgraph.pantry", attributeNodes = @NamedAttributeNode(value = "pantry")) })
public class Recipe implements Serializable {
private static final long serialVersionUID = 1L;

View File

@ -0,0 +1,58 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
>
<!-- Popup dialog to edit shopping category.
Included from detailEdit
-->
<h:head>
<title>Shopping Category</title>
<style type="text/css">
html {
font-size: 14px;
}
</style>
</h:head>
<h:body>
<ui:component>
<h:form id="frmShopcat">
<p:panelGrid columns="1">
<div>Ingredient key:
#{editShopcatBean.ingkey}</div>
<p:outputLabel for="@next" value="Category Name" />
<p:inputText id="ctlShopcat"
value="#{editShopcatBean.shopcatName}"
>
</p:inputText>
<h:outputText value="suggestion:" />
<p:selectOneMenu id="ctlShopcatMenu"
value="#{editShopcatBean.shopcatSuggestion}"
>
<f:selectItems
value="#{editShopcatBean.shopcatSuggestionList}"
/>
<p:ajax event="change"
listener="#{editShopcatBean.ajaxShopcatSuggest}"
update="ctlShopcat"
/>
</p:selectOneMenu>
<p:panelGrid columns="2" style="width: 100%">
<p:commandButton id="scDlgOK" value="OK"
style="width: 6em"
action="#{recipeDetailBean.doUpdateShopcat}"
update="form1:tabGroupClient:ingredientTable"
oncomplete="PF('editShopcatDlg').hide()"
/>
<p:commandButton id="scDlgCan" value="Cancel"
style="width: 6em"
onclick="PF('editShopcatDlg').hide()"
/>
</p:panelGrid>
</p:panelGrid>
</h:form>
</ui:component>
</h:body>
</html>

View File

@ -423,7 +423,7 @@
<p:dialog id="editShopcatDlg"
widgetVar="editShopcatDlg"
>
<ui:include src="editShopcat.xhtml" />
<ui:include src="/WEB-INF/layout/dialog/editShopcat.xhtml" />
</p:dialog>
</ui:define>
</ui:composition>

View File

@ -1,61 +0,0 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
>
<h:head>
<title>Shopping Category</title>
<style type="text/css">
html {
font-size: 14px;
}
</style>
</h:head>
<h:body>
<ui:component>
<h:form id="frmShopcat">
<p:panelGrid columns="1">
<div>Ingredient key:
#{editShopcatBean.ingkey}
</div>
<p:outputLabel for="@next"
value="Category Name" />
<p:inputText id="ctlShopcat"
value="#{editShopcatBean.shopcatName}"
>
</p:inputText>
<h:outputText
value="suggestion:" />
<p:selectOneMenu
id="ctlShopcatMenu"
value="#{editShopcatBean.shopcatSuggestion}"
>
<f:selectItems
value="#{editShopcatBean.shopcatSuggestionList}" />
<p:ajax event="change"
listener="#{editShopcatBean.ajaxShopcatSuggest}"
update="ctlShopcat" />
</p:selectOneMenu>
<p:panelGrid columns="2"
style="width: 100%"
>
<p:commandButton
id="scDlgOK" value="OK"
style="width: 6em"
action="#{recipeDetailBean.doUpdateShopcat}"
update="form1:tabGroupClient:ingredientTable"
oncomplete="PF('editShopcatDlg').hide()" />
<p:commandButton
id="scDlgCan" value="Cancel"
style="width: 6em"
onclick="PF('editShopcatDlg').hide()" />
</p:panelGrid>
</p:panelGrid>
</h:form>
</ui:component>
</h:body>
</html>

View File

@ -1,68 +0,0 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
>
<h:head>
<title>Shopping Category</title>
<style type="text/css">
html {
font-size: 14px;
}
</style>
</h:head>
<h:body>
<ui:component>
<h:form id="frmShopcat">
<p:panelGrid columns="1">
<p:dataTable id="tblShopcats"
style="width: 600px"
value="#{shoppingListBean.shopcatList}"
sortBy="#{item.shopCat}" var="item"
>
<p:headerRow>
<p:column colspan="4">
<h:outputText value="#{item.shopCat}" />
</p:column>
</p:headerRow>
</p:dataTable>
<div>Ingredient key:
#{editShopcatBean.ingkey}</div>
<p:outputLabel for="@next"
value="Category Name"
/>
<p:inputText id="ctlShopcat"
value="#{editShopcatBean.shopcatName}"
>
</p:inputText>
<h:outputText value="suggestion:" />
<p:selectOneMenu id="ctlShopcatMenu"
value="#{editShopcatBean.shopcatSuggestion}"
>
<f:selectItems
value="#{editShopcatBean.shopcatSuggestionList}"
/>
<p:ajax event="change"
listener="#{editShopcatBean.ajaxShopcatSuggest}"
update="ctlShopcat"
/>
</p:selectOneMenu>
<p:panelGrid columns="2" style="width: 100%">
<p:commandButton id="scDlgOK" value="OK"
style="width: 6em"
action="#{recipeDetailBean.doUpdateShopcat}"
update="form1:tabGroupClient:ingredientTable"
oncomplete="PF('editShopcatDlg').hide()"
/>
<p:commandButton id="scDlgCan"
value="Cancel" style="width: 6em"
onclick="PF('editShopcatDlg').hide()"
/>
</p:panelGrid>
</p:panelGrid>
</h:form>
</ui:component>
</h:body>
</html>

View File

@ -6,6 +6,7 @@
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://xmlns.jcp.org/jstl"
>
<!-- Tabbed page for the Mainpage "More..." button -->
<ui:define name="title">Gourmet Recipe Manager - Shopping</ui:define>
<ui:define name="content">
<style>
@ -66,7 +67,9 @@
</p:dataTable>
<!-- ====== Ingredients To Buy ======================= -->
<p:column id="dlIng">
<p:commandButton value="Download List" ajax="false">
<p:commandButton value="Download List"
ajax="false"
>
<p:fileDownload
value="#{shoppingListBean.dlIngredientList}"
/>
@ -112,6 +115,7 @@
>
<h:outputText
value="#{item.item}"
styleClass="#{(item.inPantry) ? 'noRecipe' :'plusRecipe' }"
/>
</p:column>
</p:dataTable>

View File

@ -32,15 +32,15 @@ class ShoppingListBeanTest {
static void setUpBeforeClass() throws Exception {
testList = new ArrayList<ShopIngredient>();
testList.add(new ShopIngredient(2.0d, "cup",
"sugar", "sugar", "baking"));
"sugar", "sugar", "baking", false));
testList.add(new ShopIngredient(1.5, "tsp",
"salt", "salt", "condiments"));
"salt", "salt", "condiments", false));
testList.add(new ShopIngredient(0.5, "tsp",
"pepper", "pepper", "condiments"));
"pepper", "pepper", "condiments", false));
testList.add(new ShopIngredient(2.0d, "cup",
"milk", "milk", "dairy"));
"milk", "milk", "dairy", false));
testList.add(new ShopIngredient(0.75d, "cup",
"sugar", "sugar", "baking"));
"sugar", "sugar", "baking", false));
}
@Test