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

View File

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

View File

@ -51,14 +51,14 @@ public class Ingredient implements Serializable, IngredientIF {
@Column(name = "inggroup") @Column(name = "inggroup")
private String inggroup; private String inggroup;
@Column(name = "ingkey",insertable = false, updatable = false) @Column(name = "ingkey", insertable = false, updatable = false)
private String ingkey; private String ingkey;
@Column(name = "item") @Column(name = "item")
private String item; private String item;
@Column(name = "optional") @Column(name = "optional")
//@NotNull // @NotNull
private Integer optional; private Integer optional;
@Column(name = "position") @Column(name = "position")
@ -80,6 +80,29 @@ public class Ingredient implements Serializable, IngredientIF {
@Column(name = "unit") @Column(name = "unit")
private String 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() { public Ingredient() {
// Attempt to remedy lack of constraints in DB // Attempt to remedy lack of constraints in DB
this.optional = 0; this.optional = 0;

View File

@ -3,52 +3,58 @@ package com.mousetech.gourmetj.persistence.model;
import java.io.Serializable; import java.io.Serializable;
import javax.persistence.*; import javax.persistence.*;
/** /**
* The persistent class for the "pantry" database table. * The persistent class for the "pantry" database table.
* *
*/ */
@Entity @Entity
@Table(name="\"pantry\"") @Table(name = "pantry")
@NamedQuery(name="Pantry.findAll", query="SELECT p FROM Pantry p")
public class Pantry implements Serializable { public class Pantry implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Id @Id
@Column(name="\"id\"") @Column(name = "id")
private int id; private Long id;
@Column(name="\"ingkey\"") @Column(name = "ingkey", nullable=false)
private Integer ingkey; private String ingkey;
@Column(name="\"pantry\"") @Column(name = "pantry")
private String pantry; private Boolean pantry;
/**
* Default Constructor.
*/
public Pantry() { public Pantry() {
} }
public int getId() { public Long getId() {
return this.id; return this.id;
} }
public void setId(int id) { public void setId(Long id) {
this.id = id; this.id = id;
} }
public Integer getIngkey() { public String getIngkey() {
return this.ingkey; return this.ingkey;
} }
public void setIngkey(Integer ingkey) { public void setIngkey(String ingkey) {
this.ingkey = ingkey; this.ingkey = ingkey;
} }
public String getPantry() { public Boolean getPantry() {
return this.pantry; return this.pantry;
} }
public void setPantry(String pantry) { public void setPantry(Boolean pantry) {
this.pantry = 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") + " ORDER BY cuisine ASC")
@NamedEntityGraph(name = "Recipe.findWorkingSet", attributeNodes = { @NamedEntityGraph(name = "Recipe.findWorkingSet", attributeNodes = {
@NamedAttributeNode(value = "categories"), @NamedAttributeNode(value = "categories"),
@NamedAttributeNode(value = "ingredientHash", subgraph = "subgraph.shopcat") }, subgraphs = { @NamedAttributeNode(value = "ingredientHash", subgraph = "subgraph.shopcat"),
@NamedSubgraph(name = "subgraph.shopcat", attributeNodes = @NamedAttributeNode(value = "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 { public class Recipe implements Serializable {
private static final long serialVersionUID = 1L; 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" <p:dialog id="editShopcatDlg"
widgetVar="editShopcatDlg" widgetVar="editShopcatDlg"
> >
<ui:include src="editShopcat.xhtml" /> <ui:include src="/WEB-INF/layout/dialog/editShopcat.xhtml" />
</p:dialog> </p:dialog>
</ui:define> </ui:define>
</ui:composition> </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:p="http://primefaces.org/ui"
xmlns:c="http://xmlns.jcp.org/jstl" 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="title">Gourmet Recipe Manager - Shopping</ui:define>
<ui:define name="content"> <ui:define name="content">
<style> <style>
@ -66,7 +67,9 @@
</p:dataTable> </p:dataTable>
<!-- ====== Ingredients To Buy ======================= --> <!-- ====== Ingredients To Buy ======================= -->
<p:column id="dlIng"> <p:column id="dlIng">
<p:commandButton value="Download List" ajax="false"> <p:commandButton value="Download List"
ajax="false"
>
<p:fileDownload <p:fileDownload
value="#{shoppingListBean.dlIngredientList}" value="#{shoppingListBean.dlIngredientList}"
/> />
@ -112,6 +115,7 @@
> >
<h:outputText <h:outputText
value="#{item.item}" value="#{item.item}"
styleClass="#{(item.inPantry) ? 'noRecipe' :'plusRecipe' }"
/> />
</p:column> </p:column>
</p:dataTable> </p:dataTable>

View File

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